秋月でも売ってるI2C EEPROM.こんなの動かすの簡単じゃーん.実際動かしたことあるし.
なのですが、Arduinoでなら簡単ポンで出来たことがSTM32だと難儀したりして、忘備録だか備忘録だか忘れたが書き留めておこうそうしよう.
かつてのこちらの投稿でも少し書いたのですが、STM32のライブラリでI2C EEPROMを動かすとき、
HAL_I2C_Master_Transmit()
HAL_I2C_Master_Receive()
だと実装できんと思います.
代わりにこれを使う必要がある.
HAL_I2C_Mem_Write()
なぜか?
EEPROMのBYTE readシーケンスを見ていただきたい.
total 4bytesのI2C動作になるのだが、前半はwrite動作、後半はread動作になっている.
すなわち、
1BYTE目 device address CPU→EEPROM
2BYTE目 memory address CPU→EEPROM
3BYTE目 device address CPU→EEPROM
4BYTE目 read data EEPROM→CPU
ならば前半をHAL_I2C_Master_Transmit()でやって後半をHAL_I2C_Master_Receive()でやればいいと思っても、中央部でSTOPを発行するの禁止なので無理.これが1つ目の地雷.
地雷回避は、HAL_I2C_Mem_Read()を使ったこのような関数でやることになる.
uint8_t EEP_read1(int adrs){
uint8_t rd;
HAL_I2C_Mem_Read(
&hi2c2,
0b10100000 + ((adrs&0x700)>>7), // adrs[10:8]
(uint16_t)(adrs & 0xff),
I2C_MEMADD_SIZE_8BIT,
&rd,
1,
500);
return rd;
}
writeは HAL_I2C_Mem_Write()を使ったこのような関数でやることになる.
void EEP_write1(int adrs, uint8_t wdata){
HAL_I2C_Mem_Write(
&hi2c2,
0b10100000 + ((adrs&0x700)>>7), // adrs[10:8]
adrs & 0xff, // adrs[7:0]
I2C_MEMADD_SIZE_8BIT,
&wdata,
1,
500);
HAL_Delay(5); ←地雷その2
}
writeにおける地雷その2は5mSec waitしないとうまく書けない.
これはdatasheetにも書かれていて、正統にはACKをpollingしたら良いのかもしれないが、面倒なので一律5mSec入れてる.
ArduinoのI2C libraryだと裏で勝手に地雷回避してくれてた記憶があるので、STM32だと悩んでしまいました.
ご注意のほど.
かしこ
0 件のコメント:
コメントを投稿