2014年3月5日水曜日

STM32F1でUSART

以前にもSTM32F1でUSARTを使う方法を書きましたが

今回はUSART1で説明します
また、割り込みを使った送信/受信は話がややこしいのでまた今度ということで


まずクロックの供給
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,  ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART1モジュールにクロックを供給します
また、TXとRXがあるGPIOA9とGPIOA10を使うためにGPIOAにクロックを供給します

GPIOの初期化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIOは入力と出力で2回に分けて初期化する必要があります
受信ポートはFLOATINGでもいいですが、Openの場合に困るのでPullUpにしておきました

USART1の初期化
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 115200;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE);
まず構造体をStructInit関数で初期化します
この関数内では9600bps データ8bit ストップビット1 パリティなし ハードウェアフロー制御なし 送信と受信の両方が有効 という設定になります
今回は115.2kbpsで使いたいので、その設定を行っています
9600bpsでいいなら何も変更しなくてもいいです

そしてUSART_Init関数で初期化してから、USART_Cmd関数でモジュールをアクティブにします

この時点でUSARTモジュールを使えるようになっています

次に送信と受信ですが
送信の場合は送信バッファが埋まっていないかを確認してからデータをセットします
受信の場合はデータが有るかどうかを確認してから読み込みます
関数例を以下に示します

void USART1_putch(char ch) {
    while (!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
    USART_SendData(USART1, ch);
}

void USART1_puts(const char *str)
{ while (*str) { USART1_putch(*str++); } }

int USART1_getch(void) {
    if (!USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
    { return(-1); }

    return(USART_ReceiveData(USART1));
}
まずputchですが、これは文字出力関数です
次にputsですが、これはputchのラッパー関数になっていて、文字列を与えると1文字ずつ送信してくれます

最後にgetchですが、この関数は少し特殊な実装で、データを受信していない場合はループで待機ではなく、-1を返しています
これによりソフトウェアのLチカ等を停止せずにデータの受信を検出することができます


上記関数群の使い方ですが
文字列出力は
    USART1_puts("\r\nHello World!! " __DATE__ " " __TIME__ "\r\n");
のように使うことができます
__DATE__はそのファイルがコンパイルされた日付を
__TIME__はそのファイルがコンパイルされた時間を文字列として持っています
また文字列は連結することが可能なので、このように記述すると"Hello World!! Mar  5 2014 03:10:33"のように1つの文字列として出力することが可能です

次に入力ですが
int i;という変数を用意しておき
        i = USART1_getch();
        if (i > -1) { USART1_putch(i); }
とすると入力されたキーのエコーバックができます
ただしこれだけでは行入力や、入力された文字列の解析はできません

1行の読み取りや、文字列の解析を行いたい場合は入力バッファが必要になります
これはかなり面倒なので、今回は説明しません


printfのようなフォーマット出力を行いたい場合はxprintf関数が便利です
xprintf関数を使う前に
    xdev_out(USART1_putch);
を呼べばUSART1を標準出力として使用できます

使う場合は
    xprintf("\nHello World!! %s %s : %s %d\n",
        __DATE__, __TIME__, __FILE__, __LINE__);
のように書けば上記のコンパイル日時とともにファイル名と行番号が表示されます


/* *** */
次のSTM32F1関連のエントリはUSARTの送信割り込みにしようかと思いましたが、先にタイマ割り込みをやっちゃおうと思います
タイマ割り込みがあったほうがUSARTの送信割り込みの有り難みがわかりやすいので

0 件のコメント:

コメントを投稿