0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[組み込み] レジスタ制御しようぜのUART編

Last updated at Posted at 2025-02-02

はじめに

これは以下記事の内容の一部なります。

設計

基本的な処理が決まったため、次は詳細な設計をしていきたいと思います。

この設計パートでは初期化処理のみ説明します。
その他の処理について大したことないため実装パートにて説明します。

UARTレジスタ制御モジュールUARTを制御するためのモジュールになります。

今回の用途としては、外部とのデータの通信制御になります。

以下が初期化制御フローになります。
デバドラ_led制御-UART制御フロー.png

何をしているか順に説明していきます。

1. RCCの設定

こちらの設定はGPIO編にて説明した内容と同じになります。

STM32にはUART機能が複数搭載されています。今回はUART2(USART2)を使用します。
また、UART機能を使うということはGPIOピンのどこかしらを使わないと通信できないですよね。
そのため、GPIO機能に繋がっているバスも有効化する必要があります。
この辺の説明は後でします。
UART使用時のブロック図.png
[DS10693 P16]

UART2がAPB1バスで、GPIOがAHB1バスなのでこれらのクロックを有効化します。

今回はGPIOAを使用するためRCC_AHB1ENRレジスタの0bit目を設定します。
UARTのRCC_GPIOクロック設定.png
[RM0390 P144]

次にUARTのクロックですが、こちらはRCC_APB1レジスタになります。
17bit目がUART2になりますのでこちらを設定します。
UARTのRCC_UARTクロック設定.png
[RM0390 P147]

2. GPIOの設定

次はGPIOの端子設定をしていきます。

ここで重要なのが、GPIOのオルタネート機能を使用します。
GPIO端子には単純な入出力モード以外に他機能の専用モードで使用することができます。
今回はUART2のTXとRXが使用したいので、PA2とPA3のAF7が対象になります。
オルタネートモード説明.png
[DS10693 P57]

ではTX(送信)の設定していきましょう。

まずは、GPIO編同様にGPIO_MODERレジスタを設定します。
GPIOレジスタ設定.png
[RM0390 P187]

PA2なので4-5bit目が対象で、ここに"10"を設定します。

次に、オルタネート機能の設定をします。
オルタネートレジスタ.png
[RM0390 P192]

ここで一つ注意点があります。このレジスタ、AFRLとAFRHの2つがありますよね。
なぜ2つに分かれているかと言うと、GPIOの端子によって上位と下位で分かれています。
AFRLがGPIO0〜GPIO7までで、AFRHがGPIO8〜GPIO15となっています。

今回はPA2になるため8-11bit目が対象となります。
AF7を使用したいので、設定値は"0111"を設定すればよさそうですね。

最後にGPIO_PUPDRレジスタでプルアップの設定をします。
UARTのプルアップレジスタ.png
[RM0390 P189]

プルアップにしたいので"01"を設定します。

これでTX(送信)の方は完了で、同じ要領でRX(受信)も設定すればOKです。

3. UARTの設定

ここではuARTの設定をしていきます。UARTの設定というのは、
ボーレート、パリティビットの有無、割り込みなどを設定します。

改めて今回のUARTの仕様を以下に記載しました。
UART仕様
 データビット:8bit
 パリティ:なし
 ストップビット:1bit
 ボーレート:115200

実はこの仕様だとほぼ設定し直すレジスタはありません。ボーレートだけになります。
UART_BRRレジスタを設定するだけになります。
UART_ボーレートレジスタ.png
[RM0390 P838]

あれ?なにを設定すればいいんだ?と思ったはずです。
もう一つ見るページがあって、それが以下になります。
UART_ボーレート設定値.png
[RM0390 P811]

ボーレートの設定値はシステムクロックに依存します。今回システムクロックを変更していため
デフォルトの16MHzになったままです。そのため「fPCLK=16MHz」の図を見ています。
で、今回使用したいボーレートは115200なのでNo7の"8.6875"を設定してあげればよさそうですね。

次に割り込みの設定をします。
今回は受信割り込みを使用するのでその設定をします。
UART_CR1レジスタがUARTの全体的な制御をするものになっています。
UART_CR1レジスタ.png
[RM0390 P839]

この5bit目のRXNEIEというのが受信割り込みを有効にする設定となります。
なのでこれを設定し、その後にGPIO編にもあったNVICの設定をしたら割り込みの設定は完了です。

で、このレジスタは他にも設定が必要にもなります。
2-3bit目のRETE、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のレジスタ制御モジュール作成は完了となります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?