[RISC-V MCU 应用开发] 十四、CH32V103应用教程——硬件I2C读写EEPROM

[复制链接]
 楼主| RISCVLAR 发表于 2020-11-20 16:00 | 显示全部楼层 |阅读模式
本帖最后由 RISCVLAR 于 2020-11-20 16:00 编辑

CH32V103应用教程——硬件I2C读写EEPROM

本章教程将使用CH32V103的硬件I2C读写EEPROM24C02,并通过串口调试助手将读写结果打印显示。

1、I2C简介及相关函数介绍
内部集成电路总线(I2C)广泛用在微控制器和传感器及其他片外模块的通讯上,它本身支持多主多从模式,仅仅使用两根线(SDA和SCL)就能以100KHz(标准)和400KHz(快速)两种速度通讯。I2C总线还兼容SMBus协议,不仅支持I2C的时序,还支持仲裁、定时和DMA,拥有CRC校验功能。

单片机I2C分为硬件I2C和模拟I2C。硬件I2C在进行程序编写时只需调用函数即可,且硬件I2C速度快、效率高、软件占用资源少,但其需使用固定GPIO脚,缺少灵活性,且某些单片机I2C并不稳定;模拟I2C通过软件程序控制管脚状态模拟I2C通信波形,使用灵活,且相对稳定,但其程序配置繁琐,代码量大,占用软件资源多。

关于I2C具体信息,可参考CH32V103应用手册。I2C标准库函数具体内容如下:
  1. void I2C_DeInit(I2C_TypeDef* I2Cx);
  2. void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
  3. void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
  4. void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  5. void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  6. void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  7. void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
  8. void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
  9. void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
  10. void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
  11. void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  12. void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  13. void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);
  14. void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
  15. uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
  16. void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
  17. uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);
  18. void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  19. void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition);
  20. void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert);
  21. void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
  22. void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition);
  23. void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
  24. uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);
  25. void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  26. void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
  27. void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle);
1.1、void I2C_DeInit(I2C_TypeDef* I2Cx)
功  能:将I2Cx外围寄存器初始化为其默认重置值。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。

1.2、void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
功  能:根据I2C_InitStruct中指定的参数初始化I2Cx外围设备。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_InitStruct:指向包含指定I2C外围设备配置信息的I2C_InitTypeDef结构的指针。

1.3、void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
功  能:用默认值填充每个I2C_InitStruct成员。
输  入:I2C_InitStruct:指向将被初始化的I2C_InitTypeDef结构的指针。

1.4、void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C外围设备。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.5、void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C DMA请求。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.6、void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:指定下一次DMA传输是否是最后一次。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.7、void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:生成I2Cx通信启动条件。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.8、void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:生成I2Cx通信停止条件。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.9、void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C确认功能。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.10、void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address)
功  能:配置指定的I2C自身地址2。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。地址:指定7bit I2C自身地址2。

1.11、void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C双寻址模式。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.12、void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C常规调用功能。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.13、void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState)
功  能:启用或禁用指定的I2C中断。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_-IT:指定要启用或禁用的I2C中断源。NewState:启用或禁用。

1.14、void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
功  能:通过I2Cx外围设备发送数据字节。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。数据:要传输的字节。

1.15、uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
功  能:返回I2Cx外围设备最近接收到的数据。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。

1.16、void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
功  能:发送地址字节以选择从设备。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。Address:指定将要传输的从属地址。I2C_Direction:指定I2C设备是发射机还是接收机。

1.17、uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register)
功  能:读取指定的I2C寄存器并返回其值。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_Register:指定要读取的寄存器。

1.18、void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C软件重置。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.19、void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition)
功  能:在主接收器模式下选择指定的I2C NACK位置。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_NACKPosition:指定NACK位置。

1.20、void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert)
功  能:驱动指定I2C的SMBusAlert引脚高或低。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_SMBusAlert:指定SMBAlert pin级别。

1.21、void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C PEC传输。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.22、void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition)
功  能:选择指定的I2C PEC位置。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_PECPosition:I2C配置位置:指定PEC位置。

1.23、void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用传输字节的PEC值计算。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.24、uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx)
功  能:返回指定I2C的PEC值。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。

1.25、void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C ARP。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.26、void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
功  能:启用或禁用指定的I2C时钟拉伸。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。NewState:启用或禁用。

1.27、void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle)
功  能:选择指定的I2C快速模式占空比。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_DutyCycle:指定快速模式占空比。

1.28、ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
功  能:检查最后一个I2Cx事件是否等于作为参数传递的事件。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_EVENT:指定要检查的事件。

1.29、uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx)
功  能:返回最后一个I2Cx事件。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。

1.30、FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG)
功  能:检查最后一个I2Cx事件是否等于作为参数传递的事件。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_FLAG:指定要检查的标志。

1.31、void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG)
功  能:清除I2Cx的挂起标志。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_FLAG:指定要清除的标志。

1.32、ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT)
功  能:检查指定的I2C中断是否发生。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_IT:指定要检查的中断源。

1.33、void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT)
功  能:清除I2Cx中断挂起位。
输  入:I2Cx:其中x可以是1或2,以选择I2C外围设备。I2C_-IT:指定要清除的中断挂起位。

以上函数使用时直接在程序中进行调用即可。

2、硬件设计
本章教程使用硬件I2C读写24C02,由原理图可知,24C02的IIC_SCL引脚和IIC_SDA引脚通过J5引出来。由CH32V103数据手册可知,CH32V103的PB6和PB7引脚分别对应I2C1_SCL和I2C1_SDA,PB10和PB11引脚对应I2C2_SCL和I2C2_SDA,本章教程使用I2C2,连接方式如下:
  • PB10连接J5的SCL引脚
  • PB11连接J5的SDA引脚

3、软件设计

硬件I2C读写24C02相较于模拟I2C读写24C02在程序代码量上少了很多,具体程序如下:
iic.h文件
  1. #ifndef __IIC_H
  2. #define __IIC_H

  3. #include "ch32v10x_conf.h"

  4. /* EERPOM DATA ADDRESS Length Definition */
  5. #define Address_8bit  0
  6. #define Address_16bit  1

  7. /* EERPOM DATA ADDRESS Length Selection */
  8. #define Address_Lenth   Address_8bit
  9. //#define Address_Lenth   Address_16bit

  10. void IIC_Init( u32 bound, u16 address );
  11. void AT24CXX_Init(void);
  12. u8 AT24CXX_ReadOneByte(u16 ReadAddr);
  13. void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);
  14. void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);
  15. void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);

  16. #endif
iic.h文件主要是相关定义及函数声明;

iic.c文件
  1. #include "iic.h"

  2. /*******************************************************************************
  3. * Function Name  : IIC_Init
  4. * Description    : Initializes the IIC peripheral.
  5. * Input          : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void IIC_Init( u32 bound, u16 address )
  9. {
  10.     GPIO_InitTypeDef GPIO_InitStructure;
  11.     I2C_InitTypeDef I2C_InitTSturcture;

  12.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟
  13.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE );  //使能I2C2时钟

  14.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  15.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //开漏复用模式
  16.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  18.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  19.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //开漏复用模式
  20.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  21.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  22.     I2C_InitTSturcture.I2C_ClockSpeed = bound;          //设置时钟频率
  23.     I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;         //设置I2C模式
  24.     I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2; //设置I2C快速模式占空比。
  25.     I2C_InitTSturcture.I2C_OwnAddress1 = address;       //设置第一个设备自己的地址
  26.     I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;        //使能应答
  27.     I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设置为7位应答
  28.     I2C_Init( I2C2, &I2C_InitTSturcture );              //I2C初始化

  29.     I2C_Cmd( I2C2, ENABLE );               //使能I2C2

  30.     I2C_AcknowledgeConfig( I2C2, ENABLE ); //使能I2C2应答功能
  31. }

  32. /*******************************************************************************
  33. * Function Name  : AT24CXX_Init
  34. * Description    : Initializes AT24xx EEPROM.
  35. * Input          : None
  36. * Return         : None
  37. ********************************************************************************/
  38. void AT24CXX_Init(void)
  39. {
  40.     IIC_Init( 100000, 0xA0);
  41. }

  42. /*******************************************************************************
  43. * Function Name  : AT24CXX_ReadOneByte
  44. * Description    : Read one data from EEPROM.
  45. * Input          : ReadAddr: Read frist address.
  46. * Return         : temp: Read data.
  47. ********************************************************************************/
  48. u8 AT24CXX_ReadOneByte(u16 ReadAddr)
  49. {
  50.     u8 temp=0;

  51.     while( I2C_GetFlagStatus( I2C2, I2C_FLAG_BUSY ) != RESET ); //等待总线空闲
  52.     I2C_GenerateSTART( I2C2, ENABLE ); //开始信号

  53.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) ); //检测EV5事件并清除标志
  54.     I2C_Send7bitAddress( I2C2, 0XA0, I2C_Direction_Transmitter );   //发送设备地址+写信号

  55.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) ); //检测EV6事件并清除标志

  56. #if (Address_Lenth  == Address_8bit)
  57.     I2C_SendData( I2C2, (u8)(ReadAddr&0x00FF) ); //发送数据地址
  58.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) ); //检测EV8事件并清除标志

  59. #elif (Address_Lenth  == Address_16bit)
  60.     I2C_SendData( I2C2, (u8)(ReadAddr>>8) );
  61.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  62.     I2C_SendData( I2C2, (u8)(ReadAddr&0x00FF) );
  63.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  64. #endif

  65.     I2C_GenerateSTART( I2C2, ENABLE );

  66.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) );
  67.     I2C_Send7bitAddress( I2C2, 0XA0, I2C_Direction_Receiver );

  68.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) ); //检测EV6事件并清除标志
  69.     while( I2C_GetFlagStatus( I2C2, I2C_FLAG_RXNE ) ==  RESET )
  70.     I2C_AcknowledgeConfig( I2C2, DISABLE ); //发送非应答信号

  71.     temp = I2C_ReceiveData( I2C2 );   //接收数据
  72.     I2C_GenerateSTOP( I2C2, ENABLE ); //停止信号

  73.     return temp;
  74. }

  75. /*******************************************************************************
  76. * Function Name  : AT24CXX_WriteOneByte
  77. * Description    : Write one data to EEPROM.
  78. * Input          : WriteAddr: Write frist address.
  79. * Return         : DataToWrite: Write data.
  80. ********************************************************************************/
  81. void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
  82. {
  83.     while( I2C_GetFlagStatus( I2C2, I2C_FLAG_BUSY ) != RESET );
  84.     I2C_GenerateSTART( I2C2, ENABLE );

  85.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) );
  86.     I2C_Send7bitAddress( I2C2, 0XA0, I2C_Direction_Transmitter );

  87.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );

  88. #if (Address_Lenth  == Address_8bit)
  89.     I2C_SendData( I2C2, (u8)(WriteAddr&0x00FF) );
  90.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  91. #elif (Address_Lenth  == Address_16bit)
  92.     I2C_SendData( I2C2, (u8)(WriteAddr>>8) );
  93.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  94.     I2C_SendData( I2C2, (u8)(WriteAddr&0x00FF) );
  95.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  96. #endif

  97.     if( I2C_GetFlagStatus( I2C2, I2C_FLAG_TXE ) !=  RESET )
  98.     {
  99.         I2C_SendData( I2C2, DataToWrite );
  100.     }

  101.     while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
  102.     I2C_GenerateSTOP( I2C2, ENABLE );
  103. }

  104. /*******************************************************************************
  105. * Function Name  : AT24CXX_Read
  106. * Description    : Read multiple data from EEPROM.
  107. * Input          : ReadAddr: Read frist address. (AT24c02: 0~255)
  108. *                  pBuffer: Read data.
  109. *                  NumToRead: Data number.
  110. * Return         : None
  111. ********************************************************************************/
  112. void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
  113. {
  114.     while(NumToRead)
  115.     {
  116.         *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
  117.         NumToRead--;
  118.     }
  119. }

  120. /*******************************************************************************
  121. * Function Name  : AT24CXX_Write
  122. * Description    : Write multiple data to EEPROM.
  123. * Input          : WriteAddr: Write frist address. (AT24c02: 0~255)
  124. *                  pBuffer: Write data.
  125. *                  NumToWrite: Data number.
  126. * Return         : None
  127. ********************************************************************************/
  128. void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
  129. {
  130.     while(NumToWrite--)
  131.     {
  132.         AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
  133.         WriteAddr++;
  134.         pBuffer++;
  135.         Delay_Ms(2);
  136.     }
  137. }
iic.c文件主要是iic初始化配置及硬件iic读写配置函数。

main.c函数
  1. /*******************************************************************************
  2. * Function Name  : main
  3. * Description    : Main program.
  4. * Input          : None
  5. * Return         : None
  6. *******************************************************************************/
  7. int main(void)
  8. {
  9.     u8 data[SIZE];

  10.     Delay_Init();
  11.     USART_Printf_Init(115200);
  12.     printf("SystemClk:%d\r\n",SystemCoreClock);

  13.     AT24CXX_Init();

  14.     printf("Start Write 24Cxx....\r\n");
  15.     AT24CXX_Write(100,(u8*)TEXT_Buffer,SIZE);  //写入数据
  16.     printf("24Cxx Write Sucess!\r\n");

  17.     Delay_Ms(500);

  18.     printf("Start Read 24Cxx....\r\n");
  19.     AT24CXX_Read(100,data,SIZE);               //读取数据
  20.     printf("The Data Readed Is: \r\n");
  21.     printf("%s\r\n", data);                    //打印输出数据

  22.     while(1);
  23. }
main.c文件主要进行相关函数初始化以及flash数据的写入和读取。


4、下载验证
将编译好的程序下载到开发板并复位,串口打印情况具体如下:
图片2.png



13、硬件IIC.rar

473.31 KB, 下载次数: 118

lmn2005 发表于 2023-4-24 20:40 | 显示全部楼层
怎么只打印:SystemClk:72000000
Start Write 24Cxx....
0.jpg

momoto 发表于 2023-4-24 21:17 | 显示全部楼层
lmn2005 发表于 2023-4-24 20:40
怎么只打印:SystemClk:72000000
Start Write 24Cxx....

估计是陷在AT24CXX_WriteOneByte()这个函数中那几个while循环里了,在循环中打印下,看看具体是哪个,是不是获取状态标志位时写错了。
lmn2005 发表于 2023-4-24 21:45 | 显示全部楼层
不是循环地打印,而是重启后只打印这两行,然后就没有了。
momoto 发表于 2023-4-24 22:30 | 显示全部楼层
lmn2005 发表于 2023-4-24 21:45
不是循环地打印,而是重启后只打印这两行,然后就没有了。

我的意思是,你执行了printf("Start Write 24Cxx....\r\n")这一句,而没有执行printf("24Cxx Write Sucess!\r\n")这一句。
肯定是在这一句上AT24CXX_Write(100,(u8*)TEXT_Buffer,SIZE)出了问题。这句里面只有一个while循环出问题的可能性不大(你也可以在这个循环中随便打印点东西看看,排查下是不是这个循环)。
追进去的话就在AT24CXX_WriteOneByte()函数里有很多while,在这些里面去找问题了。
最简单的要不你就debug嘛。很快就找到了
lmn2005 发表于 2023-4-25 07:52 | 显示全部楼层
momoto 发表于 2023-4-24 22:30
我的意思是,你执行了printf("Start Write 24Cxx....\r\n")这一句,而没有执行printf("24Cxx Write Suces ...

自己发现问题了,不好意思,低级错误,板子上的24c没有通过杜邦线连接到单片机,看了原理图后有点印象,仔细再看,果真24c是独立的IIC通讯模块。
lmn2005 发表于 2023-4-25 07:55 | 显示全部楼层
例程中有中文注释,太给力了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

296

帖子

44

粉丝
快速回复 在线客服 返回列表 返回顶部

133

主题

296

帖子

44

粉丝
快速回复 在线客服 返回列表 返回顶部