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?

STマイコンでI2C通信する方法

Last updated at Posted at 2024-11-24

ハード構成について

執筆中

STマイコンのI2C通信での注意点

  1. コードジェネレーターでジェネレートを行うと、ソースコードが生成されますが、IDE側のバグ?でI2C通信の初期化設定が正しくないです。
stm32c0xx_hal_msp.c
void HAL_I2C_MspInit(){
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;     /*$ <-- ここが誤り $*/
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

I2C通信を行う際は、プルアップ抵抗が必ず必要なので、メンバー変数Pullの設定が誤っています。よって、以下のように設定し直してください。

stm32c0xx_hal_msp.c
void HAL_I2C_MspInit(){
    GPIO_InitStruct.Pull = GPIO_PULLUP;
}

2. スレーブアドレス設定の注意点1。
まず、スレーブアドレスはコントロールレジスタの1ビット目~7ビット目までの7ビットで指定します。 その為、スレーブアドレスをスレーブ側のSTマイコンで設定する際には、設定するスレーブアドレスから1ビット左シフトした値を設定する必要があります。

例えば、スレーブアドレスが0x6F(111)の場合は、コーディング上では左に1ビットシフトした0xDE(222)を設定する必要があります。

main.c
MX_I2C1_Init(){
  hi2c1.Init.OwnAddress1 = 0xDE;
}

3. I2C通信をする際は、エラー処理を忘れずに。
I2C通信を行うと、何かしらの原因で通信エラーとなる事があります(HAL関数の場合、戻り値がHAL_ERRORになる)。この時、通信の初期化処理を行わないと、通信エラーが永遠に続きます(原因は不明ですが、私の測定環境ですと20分ぐらい連続でI2C通信を行うとこの現象になります)。

ですので、以下のように通信エラーになった時の処理を設けておきましょう。

main.c
dummy_func()
  ret_val = HAL_I2C_Master_Transmit();
  if( ret_val == HAL_ERROR ){
      I2C_RESET() ;
  }

void I2C_RESET( void ){
  HAL_I2C_DeInit(&hi2c1) ;
  HAL_I2C_Init(&hi2c1) ;
}

ソースコード

マスタ側マイコンのmain.cの主な処理は以下の通り

main.c
int main(void){
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) ;

	/*$ I2Cマスター送信を行う $*/
	ret_val = HAL_I2C_Master_Transmit(&hi2c1, slave_add, (uint8_t *)buf, 1, 3000);

	/*$ マスター送信を正しく行えた場合 $*/
    if( ret_val == HAL_OK ){
	    /*$ スレーブからデータを取得する $*/
	   	ret_val = HAL_I2C_Master_Receive(&hi2c1, slave_add, (uint8_t *)buf, 1, 3000);
	    /*$ マスター受信を正しく取得出来た場合 $*/
	   	if( ret_val == HAL_OK ){
	    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET) ;
	    	HAL_Delay(100) ;
	    } else {
		     I2C_RESET() ;
		 }
	 } else {
	     I2C_RESET() ;
	 }
	/*$ 1byteを超えた場合 $*/
	if( buf[0] >= 255 ){
	    buf[0] = 0 ;
	}
  }
}

スレーブ側マイコンのmain.cの主な処理は以下の通り

main.c
int main(void){
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	/*$ LEDを点灯 $*/
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) ;

	/*$ I2C_スレーブ受信 $*/
	ret_val = HAL_I2C_Slave_Receive(&hi2c1, (uint8_t *)buf, 1, 1000) ;

	/*$ 受信が無事に成功出来た場合 $*/
	if( ret_val == HAL_OK ){
	    /*$ 1だけインクリメントする $*/
	    buf[0] += 1 ;
	    /*$ buf[0]をスレーブ送信する $*/
	    ret_val = HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t *)buf, 1, 1000) ;
	    /*$ スレーブ送信が成功した場合 $*/
	    if( ret_val == HAL_OK ){
	    	/*$ 100msecだけLEDを消す $*/
	    	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET) ;
	    	HAL_Delay(100) ;
	    	buf_record[index++] = buf[0] ;
	    	if( index >= 1000 ){
	    		index = 0 ;
	    	}
	    } else {
		     I2C_RESET() ;
		 }
	 } else {
	     I2C_RESET() ;
	 }
  }
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?