STM32F446REでI2Cなどの機能を使用する際に設定が必要となるGPIOのAFモードについて理解した点を纏めてみました。
ポートに各機能を割り当てるには、該当ポートを「Alternate function mode(オルタネート・ファンクション・モード)」(以下AF)で使用します。
AFは16種類ありポートに割り当て可能なAFは予め決められています。
ポートとAFの関係は下記のデータシート(stm32f446re.pdf)に記載されています。
https://www.st.com/ja/microcontrollers-microprocessors/stm32f446re.html
I2C1を使用する際は、Table.11よりPB8と PB9をAF4に設定する必要があります。
設定するレジスタはGPIOB_MODERとGPIOB_AFRHの2つになります。
MODERレジスタでモードをAFに設定して、AFRHレジスタでAF番号「4」を指定します。
今回はPB8とPB9の設定なのでAFRHレジスタとなりますが、PB0~7のAFを設定する際はAFRLレジスタになります。
I2Cで使用する際にはオープンドレインと、内部Pull-upも設定しておきます。
SPLを使用した記述はこんな感じになりました。
GPIOB->MODER |= ((0x2 << 18) | (0x2 << 16)); GPIOB->AFR[1] |= ((0x4 << 4) | (0x4 << 0)); GPIOB->OTYPER |= ((0x1 << 9) | (0x1 << 8)); GPIOB->PUPDR |= ((0x1 << 18) | (0x1 << 16));
または
*(volatile unsigned int *)(GPIOB_BASE + 0x00) |= ((0x2 << 18) | (0x2 << 16)); // MODER *(volatile unsigned int *)(GPIOB_BASE + 0x24) |= ((0x4 << 4) | (0x4 << 0)); // AFRH *(volatile unsigned int *)(GPIOB_BASE + 0x04) |= ((0x1 << 9) | (0x1 << 8)); // OTYPER *(volatile unsigned int *)(GPIOB_BASE + 0x0c) |= ((0x1 << 18) | (0x1 << 16)); // PUPDR
これでI2C1が使用できました。
NUCLEO-F446REのピンは下記の位置になります。
ちなみにPB6, PB7もI2C1に割り当てられています。
こちらでも使用できましたが、PB8, PB9と両方同時にAF4に設定すると動作しませんでした。
[参考記事]