2014年3月6日木曜日

STM32F1でUSARTの送信割り込み

STM32F103でUSART1の送信割り込みを使います
ベースは以前のエントリの「割り込みを使用しないUSART」です

まず変更点1カ所目 USART初期化部分です
    USART_ClearITPendingBit(USART1, USART_IT_TXE);

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
このようにNVICの初期化を行います
今回はUSART_IT_TXE割り込みを使いますが、この時点ではTXEの有効化はしません

次に割り込みハンドラ
char USART1txBuff[500];
volatile uint16_t USART1txSet = 0;
volatile uint16_t USART1txGet = 0;
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_TXE)) {
        USART_ClearITPendingBit(USART1, USART_IT_TXE);

        USART_SendData(USART1, USART1txBuff[USART1txGet]);
        USART1txGet++;
        if (USART1txGet == sizeof(USART1txBuff))
        {   USART1txGet  = 0; }

        if (USART1txGet == USART1txSet)
        { USART_ITConfig(USART1, USART_IT_TXE, DISABLE); }

    }
}
このようになります
文字列を保存するバッファと、カウンタが2本です
バッファは今回は500バイトにしましたが、これは任意に設定できます
送出する文字列の量とマイコンのスペックに応じて設定してください

次にputch関数ですが、バッファ書き出すため、このようになります
void USART1_putch(char ch) {
    USART1txBuff[USART1txSet] = ch;
    if (++USART1txSet == sizeof(USART1txBuff))
    { USART1txSet  = 0; }

    if (USART1txSet == USART1txGet) {
        if (++USART1txGet == sizeof(USART1txBuff))
        { USART1txGet  = 0; }
    }

    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}
送信バッファに文字を設定し、Setカウンタをインクリメント
Setカウンタがバッファ外に出た場合は0に戻す
次にGetカウンタと比較し、Getカウンタと同じ場所になった(送信が追いついていない)場合はGetカウンタをインクリメント
Setカウンタと同様にバッファ外に出た場合は0に戻す
最後にUSART_ITConfigでTXEを有効に
という動作です
見て分かる通り、バッファが埋まった場合は開くのを待つのではなく、データを上書きします 大量に連続して文字列を送信する場合には注意が必要です

putsやgetchに変更はありませんが、1つ関数を追加しておきます
void USART1txDelay(void)
{ while (USART1txSet != USART1txGet); }
この関数はバッファの中身を送信し終わるまでループで待機する というものです


さて、STM32F1のUSARTは前々回に実装し、前回はタイマ割り込みを使ったRTCで送信にかかる時間を計測しました
その時は200文字を送出するのに17mSecが必要でした
今回も同じように計測してみます
start:0.004
end  :0.004
del  :0.021
diff1:0.000
diff2:0.017
startがxputsの前 endがxputsの後 そしてdelがUSART1txDelay();の後の時間です
diff1がstart-endで diff2がstart-delです
このようにバッファを使うとxputs関数では最低限の処理時間しか必要としていないことがわかります
そして実際に送出するには17mSecかかっていることがわかります

USARTの送信割り込みは受信割込みほど重要ではありませんが、使い方を知っておくといざ処理時間が少し足りない といった場合に便利だったりする可能性があります
特にXBeeでデータを飛ばす場合など、フロー制御でウエイトが入る場合に重要になります

次はUSARTの受信割り込みを実装したいところですが、実のところ送信割り込みよりはるかに複雑な動作になってしまうので、やりたくないというのがほんとうのところです
しかしまぁやらないわけにも行かないので、近いうちにUSARTの受信割り込み(+行読み取り)も書こうと思います

0 件のコメント:

コメントを投稿