2014年12月15日月曜日

mbedのSerialから1行読み出す

最近mbedでプログラムを作っています
で、ノンブロッキングな1行読み取り関数が欲しかったの、とりあえず作ってみました

本来であればmbedのWebページで公開するべきですが、とりあえずこちらに書いておきます

とりあえずコンストラクタとデストラクタ、それ以外にAdd,Getc,Getsの3個の関数が用意されています
mbedのSerialで使いたい場合はSerialの受信割り込みハンドラで1文字を読み出したらAddに渡す というコードを作っておけば、メインループスレッドでGetcで1文字読み出すこともできるし、Getsで1行読み出すこともできます

現在はASCIIコードの英数しか対応していません 半角カタカナとかも非対応です
また改行コードは\rと\nに対応しており、改行コードしか無い文字列は無視されます

いちおう動作はしていますが、本当に問題なく使用できるかは確認していないので、自己責任でご使用ください


mbedって「コピペでなんでも作れる!」みたいなことを言われているイメージだったんですが、Serialから1行読み出すって何度ググってもやり方が出てきませんでした
やっぱこの程度なら自分で作ったほうが早いよ(´・ω・`)



ヘッダファイル
#ifndef __LineBuffer_H
#define __LineBuffer_H

#include "mbed.h"

#define LineBufferSize (150)
#define LineReturnSize (50)

class LineBuffer {
public:
    LineBuffer();
    LineBuffer(uint16_t BufferSize, uint16_t ReturnSize);
    ~LineBuffer();
    void Add(char ch);
    int Getc();
    const char* Gets();
private:
    inline void AddNullChar();
    inline void SetInc();
    inline void GetInc();
    
    char *str, *ret;
    uint16_t _BufferSize, _ReturnSize, bSet, bGet, rSet;
};

#endif

ソースファイル
#include "LineBuffer.h"

LineBuffer::LineBuffer() {
    LineBuffer(LineBufferSize, LineReturnSize);
}

LineBuffer::LineBuffer(uint16_t BufferSize, uint16_t ReturnSize) {
    _BufferSize = BufferSize;
    _ReturnSize = ReturnSize;
    str = new char[_BufferSize];
    ret = new char[_ReturnSize];
    bSet = bGet = rSet = 0;
}

LineBuffer::~LineBuffer() {
    delete[] str;
    delete[] ret;
}

void LineBuffer::Add(char ch) {
    str[bSet] = ch;
    SetInc();
}

int LineBuffer::Getc() {
    if (bSet == bGet) { return(-1); }
    unsigned char ch = (unsigned char)str[bGet];
    GetInc();
    return(ch);
}

const char* LineBuffer::Gets() {
    while (bSet != bGet) {
        int ch = Getc();
        if (ch >= ' ' && ch <= '~') {
            ret[rSet++] = ch;
            if (rSet + 1 == _ReturnSize) {
                AddNullChar();
                return(ret);
            }
        } else if (ch == '\r' || ch == '\n') {
            if (rSet) {
                AddNullChar();
                return(ret);
            }
        }
    }
    return(NULL);
}

inline void LineBuffer::AddNullChar() {
    ret[rSet] = '\0';
    rSet = 0;
}

inline void LineBuffer::SetInc() {
    bSet++;
    if (bSet == _BufferSize) 
    { bSet = 0; }
    if (bSet == bGet)
    { GetInc(); }
}

inline void LineBuffer::GetInc() {
    bGet++;
    if (bGet == _BufferSize) 
    { bGet = 0; }
}

0 件のコメント:

コメントを投稿