I2Cについては以下の記事を参考にしました。
- <STM32Cube>\Repository\STM32Cube_FW_F4_V1.24.0\Projects\STM32F4-Discovery\Examples\I2C\I2C_TwoBoards_ComPolling
- 「がれすたさんのDIY日記」の「STM32でI2C通信をやってみる」
- 「Crescent」さんの「SPI/I2C シリアル通信」
- 「CCWO」さんの「STM32F303K8 I2C」
- 「DSP空挺団」さんの「STM32 HALのHAL_I2C_Mem_Read」※HAL_I2C_Mem_Write()などとHAL_I2C_Master_Transmit()などの違いについての記事
プロジェクト
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_I2C_AQM1602_Test1
実行環境
- Nucleo-F446RE
- STM32CubeMX Version 5.1.0
- System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911
配線
SCLとSDAは4.7kΩでPullUpしています。
STM32Cubeの設定
Connectivity
I2C1
Mode: I2C
Prameter Settings
Master Features
I2C Speed Mode: Standard Mode
I2C Clock Speed(Hz): 100000
Pinout ViewでPinを割り当て
PB8: I2C1_SCL
PB9: I2C1_SDA
SW4STM32でコードを追加(一部抜粋)
/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define AQM1602_ADDRESS (0x3e << 1) /* USER CODE END PD */
AQM1602のI2Cアドレスを指定します。Arduinoは7bit右詰めですが、STM32Cubeは7bitで左詰めなので左シフトしています。
参考「I2C addressing on STM32F4-Discovery」
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ // I2C LCD : Akizuki AQM1602 void lcd_cmd(uint8_t x) { uint8_t aTxBuffer[2] = { 0x00, x }; while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)AQM1602_ADDRESS, (uint8_t*)aTxBuffer, 2, 1000) != HAL_OK) { if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { Error_Handler(); } } } void lcd_data(uint8_t x) { uint8_t aTxBuffer[2] = { 0x40, x }; while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)AQM1602_ADDRESS, (uint8_t*)aTxBuffer, 2, 1000) != HAL_OK) { if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { Error_Handler(); } } } void lcd_puts(const char *s) { while(*s) lcd_data(*s++); } // param: // contrast: 0 ~ 63 (最初は大きくして調整) void lcd_init(uint8_t contrast) { // LCD initialize lcd_cmd(0x38); // function set lcd_cmd(0x39); // function set lcd_cmd(0x14); // interval osc lcd_cmd(0x70 | (contrast & 15)); // contrast low lcd_cmd(0x5c | (contrast >> 4 & 3)); // contrast high / icon / power lcd_cmd(0x6c); // follower control HAL_Delay(300); lcd_cmd(0x38); // function set lcd_cmd(0x0c); // display on lcd_cmd(0x01); // clear display HAL_Delay(2); } void lcd_move(uint8_t pos){ lcd_cmd(0x80 | pos); } void lcd_pos(uint8_t raw, uint8_t col) { lcd_cmd(0x80 | ((raw & 0x01) << 6) | col); } void lcd_clear() { lcd_cmd(0x01); } /* USER CODE END 0 */
AQM1602の制御関数です。
/* USER CODE BEGIN 2 */ lcd_init(32); lcd_puts("Hello STM32"); lcd_pos(1, 0); lcd_puts("AQM1602"); /* USER CODE END 2 */
AQM1602を初期化。
/* Infinite loop */ /* USER CODE BEGIN WHILE */ uint16_t cnt = 0; while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); char strBuffer[17] = {0}; sprintf(strBuffer, "CNT=%05d", cnt); lcd_pos(1, 0); lcd_puts(strBuffer); cnt++; HAL_Delay(100); } /* USER CODE END 3 */
メインループではインクリメントした数値の表示とLチカを行っています。
I2C通信のようす
ch1:SDA ch2:SCL
0 件のコメント:
コメントを投稿