2019年4月8日月曜日

STM32: I2C接続のLCD:AQM1602を使う(Nucleo-F446RE)

秋月のI2C接続のキャラクタLCDのAQM1602を動作させました。

I2Cについては以下の記事を参考にしました。


プロジェクト
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 件のコメント:

コメントを投稿