你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32CubeMX + STM32F407VET6读写AT24C08的实验

[复制链接]
giveup 发布时间:2016-5-30 19:31
本帖最后由 giveup 于 2016-5-31 08:03 编辑

采用STM32CubeMX 配置一块STM32F407VET6的核心板,通过I2C1读写AT24C08 EEPROM。可以选择BSP方式,或者到HAL库中挑选BSP驱动,效果一样。因为我的工程已经初始化过了,所以采用后种方式。
采用默认值配置I2C1,选中NVIC Settings中的 I2C1 event interrupt和 I2C1 error interrupt。生成工程模板。将AT24C98N EEPROM连接到PB6,PB7。器件A0,A1,A2引脚悬空,地址为0。
在安装库中复制eeprom的BSP驱动,应该都一样。如复制下列4个文件到工程目录下:
STM32Cube/Repository/STM32Cube_FW_F4_V1.12.0/Drivers/BSP/STM324xG_EVAL/stm324xg_eval_eeprom.c
STM32Cube/Repository/STM32Cube_FW_F4_V1.12.0/Drivers/BSP/STM324xG_EVAL/stm324xg_eval_eeprom.h
STM32Cube/Repository/STM32Cube_FW_F4_V1.12.0/Drivers/BSP/STM324xG_EVAL/stm324xg_eval.c
STM32Cube/Repository/STM32Cube_FW_F4_V1.12.0/Drivers/BSP/STM324xG_EVAL/stm324xg_eval.h

stm324xg_eval.c和stm324xg_eval.h中保留和EEPROM相关内容即可。

重点的问题是,这个驱动支持的是M24C64 EEPROM,和AT24C08 EEPROM有一定差异,需要修改部分内容才能使用。主要体现在读写页面尺寸、容量和器件地址表示不一致。
根据手册,AT24C04~AT24C32的内存地址是分为两部分,除低八位外,高3位占用了器件的地址。如AT24C08,内存大小为1024字节,地址为10位,高2位占用了器件地址A1,A0。M24C64 EEPROM的内存地址为16位,和AT24C32以上的EEPROM保持一致。
因此,主要修改点为:
1。修改页面尺寸与地址大小
stm324xg_eval_eeprom.h中,修改定义:
#define EEPROM_PAGESIZE             16
#define EEPROM_MAX_SIZE             0x400  /* 8Kbit */
添加定义
#define EEPROM_MEMADD_SIZE         I2C_MEMADD_SIZE_8BIT
#define MEMADD_MSB_MASK     0x3
2。修改读写函数
2.1 读操作部分修改逻辑:
该部分的逻辑是 BSP_EEPROM_ReadBuffer 经过 EEPROM_IO_ReadData 调用I2Cx_ReadMultiple完成实际读写。
因为读函数采用连续读方式,只要设定了正确的内存起始地址,就能正常完成读操作。因此,修改只涉及到BSP_EEPROM_ReadBuffer和EEPROM_IO_ReadData两个函数。具体修改如下,红色部分是增加和修改的:
  1.     uint32_t BSP_EEPROM_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead) {
  2.     uint32_t buffersize = *NumByteToRead;

  3.     /* Set the pointer to the Number of data to be read. This pointer will be used
  4.      by the DMA Transfer Completer interrupt Handler in order to reset the
  5.      variable to 0. User should check on this variable in order to know if the
  6.      DMA transfer has been complete or not. */
  7.     EEPROMDataRead = *NumByteToRead;
  8.     <font color="Red">uint16_t A_EEPROMAddress = EEPROMAddress;
  9.     uint8_t A2A1A0 = (uint8_t) ((ReadAddr >> 8) & MEMADD_MSB_MASK);
  10.     A_EEPROMAddress = A_EEPROMAddress | (A2A1A0<<1);</font>

  11.     if (EEPROM_IO_ReadData(<font color="Red">A_EEPROMAddress</font>, ReadAddr, pBuffer, buffersize) != HAL_OK) {
  12.         BSP_EEPROM_TIMEOUT_UserCallback();
  13.         return EEPROM_FAIL;
  14.     }
  15.     /* If all operations OK, return EEPROM_OK (0) */
  16.     return EEPROM_OK;
  17. }
复制代码

将I2C_MEMADD_SIZE_16BIT替换为上面新增加的EEPROM_MEMADD_SIZE定义:
  1. HAL_StatusTypeDef EEPROM_IO_ReadData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize)
  2. {
  3.   return
  4. (I2Cx_ReadMultiple(DevAddress, MemAddress, <font color="Red">EEPROM_MEMADD_SIZE</font>, pBuffer, BufferSize));
  5. }
复制代码


2.2写操作部分函数修改逻辑:
写操作调用关系是BSP_EEPROM_WriteBuffer负责将写地址分页,并完成页面对齐后,调用BSP_EEPROM_WritePage经过EEPROM_IO_WriteData完成实际写操作。修改部分只涉及到后边两个函数,具体见下面红色部分:
  1.     uint32_t BSP_EEPROM_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite) {
  2.     uint32_t buffersize = *NumByteToWrite;
  3.     uint32_t status = EEPROM_OK;

  4.     /* Set the pointer to the Number of data to be written. This pointer will be used
  5.      by the DMA Transfer Completer interrupt Handler in order to reset the
  6.      variable to 0. User should check on this variable in order to know if the
  7.      DMA transfer has been complete or not. */
  8.     EEPROMDataWrite = *NumByteToWrite;

  9. <font color="Red">  uint16_t A_EEPROMAddress = EEPROMAddress;
  10.     uint8_t A2A1A0 = (uint8_t) ((WriteAddr >> 8) & MEMADD_MSB_MASK);
  11.     A_EEPROMAddress = A_EEPROMAddress | (A2A1A0<<1);</font>

  12.     if (EEPROM_IO_WriteData(<font color="Red">A_EEPROMAddress</font>, WriteAddr, pBuffer, buffersize) != HAL_OK) {
  13.         BSP_EEPROM_TIMEOUT_UserCallback();
  14.         status = EEPROM_FAIL;
  15.     }

  16.     if (BSP_EEPROM_WaitEepromStandbyState() != EEPROM_OK) {
  17.         return EEPROM_FAIL;
  18.     }
  19.     /* If all operations OK, return EEPROM_OK (0) */
  20.     return status;
  21. }
复制代码

具体写操作修改和读操作差不多:
  1. HAL_StatusTypeDef EEPROM_IO_WriteData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize)
  2. {
  3.   return
  4. (I2Cx_WriteMultiple(DevAddress, MemAddress,<font color="Red"> EEPROM_MEMADD_SIZE</font>, pBuffer, BufferSize));
  5. }
复制代码


3. 初始化及其他操作修改。STM32CubeMX已经正确生成了初始化代码,因此除了下面的两个,大部分BSP的初始化代码都可以删除。
  1. void EEPROM_IO_Init(void)
  2. {
  3.   I2Cx_Init();
  4. }
复制代码
修改为MX的初始化代码
  1. void EEPROM_IO_Init(void)
  2. {
  3.    MX_I2C1_Init();
  4. }
复制代码

修改函数,取消一些不必要的调用:
  1. uint32_t BSP_EEPROM_Init(void) {
  2.     /* I2C Initialization */
  3. <font color="Red">//  EEPROM_IO_Init();</font>
  4.     /* Select the EEPROM address for A01 and check if OK */
  5.     EEPROMAddress = EEPROM_I2C_ADDRESS_A01;
  6.     if (EEPROM_IO_IsDeviceReady(EEPROMAddress, EEPROM_MAX_TRIALS) != HAL_OK) {
  7. //    /* Select the EEPROM address for A02 and check if OK */
  8. //    EEPROMAddress = EEPROM_I2C_ADDRESS_A02;
  9. //    if(EEPROM_IO_IsDeviceReady(EEPROMAddress, EEPROM_MAX_TRIALS) != HAL_OK)
  10. //    {
  11.         return EEPROM_FAIL;
  12. //    }
  13.     }
  14.     return EEPROM_OK;
  15. }
复制代码

另外,需要将stm324xg_eval.c中的 heval_I2c 变量实例替换为hi2c1。可以用查找替换或者宏定义。
4. 使用例子
4.1 初始化
在main.c的  
  1. /* USER CODE BEGIN 2 */
  2. BSP_EEPROM_Init();
  3.   /* USER CODE END 2 */
复制代码
或者其他适当地方添加初始化设置,完成EEPROM地址的设定。
4.2使用可以参考相应代码。如:
  1. #define EEPROM_CFG_ADDRESS       0x120       //和页面对齐
  2. __IO uint8_t EEPROMConnected = 1;
  3. typedef struct {
  4.     uint16_t valide;
  5.     uint8_t databuf[16];
  6. }CfgData;
  7. CfgData cfg; //全局的一个结构变量
  8. /**
  9. * @brief  从EEPROM 中读出参数
  10. * @param  无
  11. * @retval 0成功 其他失败: 1 通信错误  2 无效设置
  12. */
  13. uint8_t read_cfg_eeprom(void) {
  14.     CfgData cfg_read;
  15.     uint16_t readSize= (uint16_t) sizeof(CfgData);

  16.     EEPROMConnected = 1; //超时回调函数设定

  17.     /* Wait for EEPROM standby state */
  18.     BSP_EEPROM_WaitEepromStandbyState();

  19.     /* Read old parameter in EEPROM */
  20.     if (EEPROMConnected == 1) {
  21.         /* Set the Number of data to be read */
  22.         memset((uint8_t*)&cfg_read,0,readSize);
  23.         /* Read from I2C EEPROM from EEPROM_CFG_ADDRESS */
  24.         if (BSP_EEPROM_ReadBuffer((uint8_t*)&cfg_read, EEPROM_CFG_ADDRESS, &readSize) != EEPROM_OK) {
  25.             return 1;  //通信错误
  26.         }
  27.         if (cfg_read.valide == 0x55aa) {  //有效的
  28.             memcpy((void*)&cfg, (void *)&cfg_read, sizeof(CfgData));
  29.             return 0; //正常
  30.         }
  31.     }
  32.     return 2; //无效设置
  33. }
  34. /**
  35. * @brief  保存参数到 EEPROM 中
  36. * @param  无
  37. * @retval 0成功 其他失败
  38. */
  39. uint8_t save_cfg2eeprom(void) {

  40.     EEPROMConnected = 1;

  41.     /* Wait for EEPROM standby state */
  42.     BSP_EEPROM_WaitEepromStandbyState();

  43.     /* Write new parameter in EEPROM */
  44.     if (EEPROMConnected == 1) {
  45.         /* Write on I2C EEPROM to EEPROM_CFG_ADDRESS */
  46.         if (BSP_EEPROM_WriteBuffer((uint8_t*)&cfg, EEPROM_CFG_ADDRESS, (uint16_t) sizeof(CfgData)) == EEPROM_OK) {
  47.             return 0;
  48.         }
  49.     }
  50.     return 1;
  51. }
  52. /**
  53. * @brief  Basic management of the timeout situation.
  54. * @param  None.
  55. * @retval None
  56. */
  57. void BSP_EEPROM_TIMEOUT_UserCallback(void) {
  58.     EEPROMConnected = 0;
  59. }

复制代码
经过调试并下载到核心板运行,测试结果正常。所用软件环境:
STM32CubeMX 4.15.0
STM32Cube_FW_F4_V1.12.0
GNU ARM C/C++ for eclipse 2.5.1.201604190915
eclipse 4.4.2 luna
Debian sid: Linux Debian 4.5.0-2-686-pae #1 SMP Debian 4.5.4-1 (2016-05-16) i686 GNU/Linux


收藏 评论3 发布时间:2016-5-30 19:31

举报

3个回答
giveup 回答时间:2016-5-31 08:04:02
红色字体显示出现问题。应该能看懂。
anny 回答时间:2016-5-31 08:26:55
谢谢分享
wbaojiang 回答时间:2020-3-23 11:56:38
感谢!

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版