STM32G0を使ってみる3 -I2Cライブラリの拡張そしてAHT20-

●AHT20だ!
今回は前回ご紹介したAOSUNGの温湿度センサAHT20を動作させてみます。



AHT20はAOSUNG(ブランド名はASAIR)の新世代の温湿度センサです。これを搭載し、
さらにLDOと信号レベル変換FETを搭載したモジュールをアマゾン経由で入手しました。

そしてつい最近秋月よりDIPモジュール版のAHT25も登場してもう入手されて方もいる
かと思いますが過去世代のAM23xx系よりもさらに使いやすくなっているようですね。


●I2Cドライバを10年ぶりくらいに改造する
さて、私が過去に作成したI2Cライブラリは送信受信ともバイトorワード単位でしか
やり取りすることができず、2バイトコマンドが存在するI2Cデバイスのコントロール
すらできないガバガバっぷりです☠(RaspiのSMBusも同じだし私は悪くなi)

そしてAHT20は温度取得トリガーコマンドが2バイトどころか3バイトもあった…

そんなわけで重い腰を上げてSTM32G0のI2Cレジスタをたたいてマルチバイトを
送受信できる関数を整備してみました。
※受信※

/**************************************************************************/
/*!
Read RAW MultiByteData Middlelevel.
*/
/**************************************************************************/
uint8_t I2CDev_ReadBytesRaw(uint8_t sla,uint8_t *data,uint8_t count)
{
/* Wait Bus Busy */
I2CDevTimer = I2CDEV_SHORT_TIMEOUT;
while((I2CDEV_PORT->ISR & I2C_ISR_BUSY))
{
if((I2CDevTimer--) == 0) return I2CDev_Timeout();
}

/* Send Slave Address and Memory Address */
/* Configure slave address, nbytes, NOLELOAD,NOAUTOSTOP */
I2C_TransferHandling(I2CDEV_PORT, sla|I2CDEV_SD_READ, count, 0, (uint32_t)(I2C_CR2_START | I2C_CR2_RD_WRN));

for(int i = 0;i<(count-1);i++){
*data = I2CDev_RecvData(I2CDEV_ACK);
data++;
}
*data = I2CDev_RecvData(I2CDEV_NACK); /* Last data MUST be NACK */

/* Send Stop Condition */
I2CDev_StopCondition();

/* Wait until STOPF flag is reset */
I2CDevTimer = I2CDEV_SHORT_TIMEOUT;
while(!(I2CDEV_PORT->ISR & I2C_FLAG_STOPF))
{
if(I2CDev_ReadNAck() ==I2CDEV_NACK) return I2CDev_Timeout();
if((I2CDevTimer--) == 0) return I2CDev_Timeout();
}

/* Clear STOP Flag */
I2CDEV_PORT->ICR =I2C_ISR_STOPF;

/* Clear Configuration Register 2 */
I2CDEV_PORT->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN));

return 1;
}


※送信※

/**************************************************************************/
/*!
Write RAW MultiBytes Middlelevel.
*/
/**************************************************************************/
uint8_t I2CDev_WriteBytesRaw(uint8_t sla,uint8_t *data,uint8_t count)
{
/* Wait Bus Busy */
I2CDevTimer = I2CDEV_SHORT_TIMEOUT;
while((I2CDEV_PORT->ISR & I2C_ISR_BUSY))
{
if((I2CDevTimer--) == 0) return I2CDev_Timeout();
}

/* Send Slave Address and Memory Address */
/* Configure slave address, nbytes, RELOAD,AUTOSTOP,AUTOSTART */
I2C_TransferHandling(I2CDEV_PORT, sla|I2CDEV_SD_WRITE, count, I2C_CR2_AUTOEND|I2C_CR2_RELOAD, I2C_CR2_START);

/* Send multibytes datas */
for(int i = 0; i < count ; i++){
/* Wait until TXIS flag is set */
I2CDevTimer = I2CDEV_SHORT_TIMEOUT;
while(!(I2CDEV_PORT->ISR & I2C_ISR_TXIS))
{
if(I2CDev_ReadNAck() == I2CDEV_NACK){
/* Clear STOP Flag */
I2CDEV_PORT->ICR =I2C_ISR_NACKF;
/* Clear STOP Flag */
I2CDEV_PORT->ICR =I2C_ISR_STOPF;
/* Clear TXE Flag */
I2CDEV_PORT->ISR |=I2C_ISR_TXE;

/* Clear Configuration Register 2 */
I2CDEV_PORT->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN));

return 0;
}

if((I2CDevTimer--) == 0) return I2CDev_Timeout();
}
I2CDev_SendData(*data);
data++;
//I2C_WaitFlag(I2C_ISR_TCR); /* Notneeded in auto STOP */
}

/* Send Stop Condition */
//I2CDev_StopCondition(); /* Notneeded in auto STOP */

/* Wait until STOPF flag is reset */
I2CDevTimer = I2CDEV_SHORT_TIMEOUT;
while(!(I2CDEV_PORT->ISR & I2C_FLAG_STOPF))
{
if(I2CDev_ReadNAck() ==I2CDEV_NACK) return I2CDev_Timeout();
if((I2CDevTimer--) == 0) return I2CDev_Timeout();
}

/* Clear STOP Flag */
I2CDEV_PORT->ICR |=I2C_ISR_STOPF;

/* Clear Configuration Register 2 */
I2CDEV_PORT->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN));

return 1;
}

STM32F0以降のI2Cブロックはハードウエアで細かい設定ができる分
ちゃんと仕組みを知っておかないとうまく使いこなせないのでご注意を…!


とりあえずサクッと動きました☆
値段も安くて精度もそこそこなので使い倒せるセンサですね〜


次はオシロで波形を観測してみます。
温湿度測定トリガコマンド送信時の波形は以下のようになります。

温度/湿度の受信パケットは以下の波形です。

画像の説明にもある通りCRCチェックが必要なければ6バイトで受信を打ち切って
しまうこともできます。私のプログラムはまだCRCチェックに対応してないので
6バイトめで打ち切りにしています。すみません後でCRC実装します。
20230929追:
現在おきぱで公開しているソースはCRC値チェックを入れております!
20230929追:



といううわけで10年越しでやっとこI2Cライブラリに拡張性持たせた
改造を行うことができました。これを応用して買いためたままの他の
温湿度センサもガンガン使って行こうと思います!!!
今回の内容を盛り込んだSTM32G0のプログラムも更新しましたのでよろしく!!!



次のネタですが実はもうソースコード見たら実装済みでわかるかと思いますが
1Wireなデバイスたちをオシロの波形と照らし合わせながら動かしてみます。

Go to top of page