はじめに
これは以下記事の内容の一部なります。
設計
基本的な処理が決まったため、次は詳細な設計をしていきたいと思います。
この設計パートでは初期化処理のみ説明します。
その他の処理について大したことないため実装パートにて説明します。
UARTレジスタ制御モジュールUARTを制御するためのモジュールになります。
今回の用途としては、外部とのデータの通信制御になります。
何をしているか順に説明していきます。
1. RCCの設定
こちらの設定はGPIO編にて説明した内容と同じになります。
STM32にはUART機能が複数搭載されています。今回はUART2(USART2)を使用します。
また、UART機能を使うということはGPIOピンのどこかしらを使わないと通信できないですよね。
そのため、GPIO機能に繋がっているバスも有効化する必要があります。
この辺の説明は後でします。
[DS10693 P16]
UART2がAPB1バスで、GPIOがAHB1バスなのでこれらのクロックを有効化します。
今回はGPIOAを使用するためRCC_AHB1ENRレジスタの0bit目を設定します。
[RM0390 P144]
次にUARTのクロックですが、こちらはRCC_APB1レジスタになります。
17bit目がUART2になりますのでこちらを設定します。
[RM0390 P147]
2. GPIOの設定
次はGPIOの端子設定をしていきます。
ここで重要なのが、GPIOのオルタネート機能を使用します。
GPIO端子には単純な入出力モード以外に他機能の専用モードで使用することができます。
今回はUART2のTXとRXが使用したいので、PA2とPA3のAF7が対象になります。
[DS10693 P57]
ではTX(送信)の設定していきましょう。
まずは、GPIO編同様にGPIO_MODERレジスタを設定します。
[RM0390 P187]
PA2なので4-5bit目が対象で、ここに"10"を設定します。
次に、オルタネート機能の設定をします。
[RM0390 P192]
ここで一つ注意点があります。このレジスタ、AFRLとAFRHの2つがありますよね。
なぜ2つに分かれているかと言うと、GPIOの端子によって上位と下位で分かれています。
AFRLがGPIO0〜GPIO7までで、AFRHがGPIO8〜GPIO15となっています。
今回はPA2になるため8-11bit目が対象となります。
AF7を使用したいので、設定値は"0111"を設定すればよさそうですね。
最後にGPIO_PUPDRレジスタでプルアップの設定をします。
[RM0390 P189]
プルアップにしたいので"01"を設定します。
これでTX(送信)の方は完了で、同じ要領でRX(受信)も設定すればOKです。
3. UARTの設定
ここではuARTの設定をしていきます。UARTの設定というのは、
ボーレート、パリティビットの有無、割り込みなどを設定します。
改めて今回のUARTの仕様を以下に記載しました。
UART仕様
データビット:8bit
パリティ:なし
ストップビット:1bit
ボーレート:115200
実はこの仕様だとほぼ設定し直すレジスタはありません。ボーレートだけになります。
UART_BRRレジスタを設定するだけになります。
[RM0390 P838]
あれ?なにを設定すればいいんだ?と思ったはずです。
もう一つ見るページがあって、それが以下になります。
[RM0390 P811]
ボーレートの設定値はシステムクロックに依存します。今回システムクロックを変更していため
デフォルトの16MHzになったままです。そのため「fPCLK=16MHz」の図を見ています。
で、今回使用したいボーレートは115200なのでNo7の"8.6875"を設定してあげればよさそうですね。
次に割り込みの設定をします。
今回は受信割り込みを使用するのでその設定をします。
UART_CR1レジスタがUARTの全体的な制御をするものになっています。
[RM0390 P839]
この5bit目のRXNEIEというのが受信割り込みを有効にする設定となります。
なのでこれを設定し、その後にGPIO編にもあったNVICの設定をしたら割り込みの設定は完了です。
で、このレジスタは他にも設定が必要にもなります。
2-3bit目のREとTE、13bit目のUEを設定する必要があります。
REとTEは送信と受信のイネーブル設定になって、UEはUARTを開始する設定になります。
なので、これらのbitに"1"を設定したらOKです。
実装
先ほどの設計を踏まえて実装していきます。
init_uart2:初期化処理
void init_uart2(void)
{
RCC_TypeDef *pRCC;
pRCC = RCC;
GPIO_TypeDef *pGPIOA;
pGPIOA = BASE_ADDR_GPIOA_PERI;
USART_TypeDef *pUART2;
pUART2 = USART2;
// UART2のクロックを有効化
pRCC->APB1ENR |= (1 << 17);
// UART TXピン(GPIOA2)とRXピン(GPIOA3)の設定
// PA2: UART2 TX PA3: UART2 RX
// PA2の設定
// GPIOAのクロックを有効化
pRCC->AHB1ENR |= (1 << 0);
// GPIOA2ピンをAFモードに設定(UART2 TX)
pGPIOA->MODER &= ~(0x3 << 4);
pGPIOA->MODER |= (0x2 << 4);
pGPIOA->AFR[0] &= ~(0xF << 8);
pGPIOA->AFR[0] |= (0x7 << 8);
// プルアップ設定
pGPIOA->PUPDR |= (0x1 << 4);
// PA3の設定
// GPIOA3ピンをAFモードに設定(UART2 RX)
pGPIOA->MODER &= ~(0x3 << 6);
pGPIOA->MODER |= (0x2 << 6);
pGPIOA->AFR[0] &= ~(0xF << 12);
pGPIOA->AFR[0] |= (0x7 << 12);
// プルアップ設定
pGPIOA->PUPDR |= (0x1 << 6);
// ボーレートの設定
pUART2->BRR = 0x8B; // 115200bps
// UARTのデータ幅、パリティ、ストップビットの設定
// デフォルトを使用するので設定不要(8bit, No parity, 1 stop bit)
// 受信の割り込み有効化
pUART2->CR1 |= (0x1 << 5); // RXNEIE割り込み有効化
NVIC_EnableIRQ(USART2_IRQn);
// UARTのTXとRXの有効化
pUART2->CR1 |= (0x3 << 2); // UARTの送受信有効化
// UARTの有効化
pUART2->CR1 |= (1 << 13);
}
一点だけ補足しておきます。
ボーレートの設定ですが、"8B"というのは"8.6875"を16進表記したものになります。
request_dma_start:DMA開始要求処理
void request_dma_start(void)
{
USART_TypeDef *pUART2;
pUART2 = USART2;
// DMAコントローラーに要求を送信
pUART2->CR3 |= (1 << 7);
}
概要:DMAに対して送信開始を要求する。
処理内容:概要と同じなので省略。
USART2_IRQHandler:割り込みハンドラ
以下に割り込みハンドラも記載します。
※こちらは「stm32f4xx_it.c」ファイルに記載しています。
void USART2_IRQHandler(void)
{
USART_TypeDef *pUART2;
pUART2 = USART2;
// ステータスレジスタで受信可能か確認
// 受信可能ならば、DRからデータを取得
if (pUART2->SR & (1 << 5)) {
uint32_t data = pUART2->DR;
set_led_data(data);
}
clear_usart2_pending_bit();
}
void clear_usart2_pending_bit(void)
{
USART_TypeDef *pUART2;
pUART2 = USART2;
if (pUART2->SR & (1 << 5)) {
// 受信フラグをクリア
pUART2->SR &= ~(1 << 5);
}
}
概要:UARTの受信割り込み処理を行う
処理内容:
以下のようなことをやっています。
1. UARTのステータスレジスタでリードデータが入っているかを確認する。
2. UARTのデータレジスタからデータを取得し、LED情報に設定する。
3. 受信フラグをクリアする。
終わりに
これにてUARTのレジスタ制御モジュール作成は完了となります。