【经验】MCU微课堂之中科芯CKS32F4xx系列产品IIC通信

2023-03-23 中科芯MCU公众号
MCU,CKS32F4xx,中科芯 MCU,CKS32F4xx,中科芯 MCU,CKS32F4xx,中科芯 MCU,CKS32F4xx,中科芯

中科芯CKS32F4xx系列MCU产品内部提供两个看门狗定时器单元,独立型看I2C通讯协议(Inter-Integrated Circuit)是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路间的通讯。本文中中科芯将为大家详细介绍CKS32F4xx系列产品的IIC通信。


CKS32F4xx系列产品IIC介绍

CKS32F4xx系列的I2C外设可用作通讯的主机及从机,支持100Kbit/s和 400Kbit/s的速率,支持7位、10位设备地址,支持DMA数据传输,并具有数据校验功能。它的I2C外设还支持SMBus2.0协议,SMBus协议与I2C类似,主要应用于笔记本电脑的电池管理中。IIC接口的结构框图如下图所示:



I2C的所有硬件架构都是根据上图中左侧SCL线和SDA线展开的(其中SMBA线用于SMBUS的警告信号,I2C通讯没有使用)。CKS32F4xx系列芯片有多个I2C 外设,它们的I2C通讯信号引出到不同的GPIO引脚上,使用时必须配置到这些指定的引脚,具体的引脚映射关系,请参考芯片数据手册。


SCL线的时钟信号,由I2C接口根据时钟控制寄存器(CCR)控制,控制的参数主要为时钟频率。配置I2C的CCR寄存器可修改通讯速率相关的参数,I2C通讯的“标准/快速”模式分别对应100/400Kbit/s的通讯速率。


I2C的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过SDA信号线发送出去;当从外部接收数据的时候,数据移位寄存器把 SDA信号线采样到的数据一位一位地存储到“数据寄存器”中。若使能了数据校验,接收到的数据会经过PCE计算器运算,运算结果存储在“PEC 寄存器”中。


当CKS32的I2C工作在从机模式的时候,接收到设备地址信号时,数据移位寄存器会把接收到的地址CKS32的自身的“I2C 地址寄存器”的值作比较,以便响应主机的寻址。CKS32的自身I2C地址可通过修改“自身地址寄存器”修改,支持同时使用两个I2C设备地址,两个地址分别存储在OAR1和OAR2中。


使用I2C外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1及SR2)”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。当CKS32的IIC作为通讯的主机端向外发送数据的过程为:

S:起始位

P:停止位

A:应答

EV5:SB=1

EV6:ADDR=1

EV8:TxE=1

EV8_2:TxE=1,BTF=1


主发送器发送流程及事件说明如下:

(1) 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对SR1寄存器的“SB”位置1,表示起始信号已经发送;

(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”及“EV8”,这时SR1寄存器的“ADDR”位及“TXE”位被置1,ADDR为1表示地址已经发送,TXE为1表示数据寄存器为空;

(3) 以上步骤正常执行并对ADDR位清零后,我们往I2C的“数据寄存器DR”写入要发送的数据,这时TXE位会被重置0,表示数据寄存器非空,I2C外设通过SDA信号线一位位把数据发送出去后,又会产生“EV8”事件,即TXE位被置 1,重复这个过程,就可以发送多个字节数据了;

(4) 当我们发送数据完成后,控制I2C设备产生一个停止信号(P),这个时候会产生EV2事件,SR1的TXE位及BTF位都被置1,表示通讯结束。

假如我们使能了I2C中断,以上所有事件产生时,都会产生I2C中断信号,进入同一个中断服务函数,到I2C中断服务程序后,再通过检查寄存器位来了解是哪一个事件。


CKS32的IIC作为通讯的主机端从外部接收数据的过程为:


S:起始位

P:停止位

A:应答

NA:非应答

EV5:SB=1

EV6:ADDR=1

EV7:RxNE=1

EV7_1:RxNE=1


主接收器接收流程及事件说明如下:

(1) 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“EV5”,并会对SR1寄存器的“SB”位置1,表示起始信号已经发送;

(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”这时SR1寄存器的“ADDR”位被置1,表示地址已经发送。

(3) 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产生“EV7”事件,SR1寄存器的RXNE被置1,表示接收数据寄存器非空,我们读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控制I2C发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收数据,若非应答,则停止传输;

(4) 发送非应答信号后,产生停止信号(P),结束传输。


CKS32F4xx系列产品IIC的配置

接下来我们讲解如何利用CKS32F4xx系列固件库来完成对IIC的配置使用。跟其它外设一样,CKS32标准库提供了I2C初始化结构体及初始化函数来配置 I2C外设。了解初始化结构体后我们就能对I2C外设运用自如了,代码如下:

  1. typedef struct

  2. {

  3. uint32_t I2C_ClockSpeed;

  4. uint16_t I2C_Mode;

  5. uint16_t I2C_DutyCycle;

  6. uint16_t I2C_OwnAddress1;

  7. uint16_t I2C_Ack;

  8. uint16_t I2C_AcknowledgedAddress;

  9. }I2C_InitTypeDef;


结构体中各个成员变量的介绍及初始化时可被赋的值如下:

1) I2C_ClockSpeed:本成员设置的是I2C的传输速率,在调用初始化函数时,函数会根据我们输入的数值经过运算后把时钟因子写入到I2C的时钟控制寄存器CCR。而我们写入的这个参数值不得高于400Kbit/s。

2) I2C_Mode:本成员是选择I2C的使用方式,可选的参数值如下:

  1. I2C_Mode_I2C                         //I2C模式

  2. I2C_Mode_SMBusDevice        // SMBus从模式

  3. I2C_Mode_SMBusHost         // SMBus主模式


3) I2C_DutyCycle: 本成员设置的是I2C的SCL线时钟的占空比。该配置有两个选择,分别为低电平时间比高电平时间为2:1(I2C_DutyCycle_2)和16:9 (I2C_DutyCycle_16_9)。其实这两个模式的比例差别并不大,一般任意选一个就可以了。

  1. I2C_DutyCycle_16_9

  2. I2C_DutyCycle_2


4) I2C_OwnAddress1: 本成员配置的是CKS32的I2C设备自己的地址,每个连接到I2C总线上的设备都要有一个自己的地址,作为主机也不例外。地址可设置为7位或10位(受下面I2C_AcknowledgeAddress成员决定),只要该地址是 I2C总线上唯一的即可。


5) I2C_Ack: 本成员是关于I2C应答设置,设置为使能则可以发送响应信号。该成员值一般配置为允许应答,这是绝大多数遵循I2C标准的设备的通讯要求,改为禁止应答往往会导致通讯错误。

  1. I2C_Ack_Enable              //允许应答

  2. I2C_Ack_Disable            //禁止应答


6) I2C_AcknowledgedAddress: 本成员选择I2C的寻址模式是7位还是10 位地址。这需要根据实际连接到I2C总线上设备的地址进行选择,这个成员的配置也影响到I2C_OwnAddress1成员,只有这里设置成10位模式时,I2C_OwnAddress1才支持10位地址。

  1. I2C_AcknowledgedAddress_7bit         //7位寻址

  2. I2C_AcknowledgedAddress_10bit      //10位寻址


配置完这些结构体成员值,调用库函数I2C_Init即可把结构体的配置写入到寄存器中。


CKS32F4xx读写EEPROM实验

本小节以EEPROM的读写实验为大家讲解CKS32F4xx的I2C使用方法。实验中CKS32F4xx的I2C外设采用主模式,分别用作主发送器和主接收器,通过查询事件的方式来确保正常通讯。实验中用的EEPROM芯片(型号:AT24C02) 的SCL及SDA引脚连接到了CKS32F4xx对应的 I2C引脚中(PF1和PF0),结合上拉电阻,构成了I2C通讯总线,它们通过I2C总线交互。EEPROM 芯片的设备地址一共有7位,其中高4位固定为:1010b,低3位则由A0/A1/A2 信号线的电平决定,在本实验中I2C设备的写地址为0xA0,I2C设备的读地址为0xA1。

  1. 编程要点

(1) 配置通讯使用的目标引脚为开漏模式;

(2) 使能I2C外设的时钟;

(3) 配置I2C外设的模式、地址、速率等参数并使能I2C外设;

(4) 编写基本I2C按字节收发的函数;

(5) 编写读写 EEPROM 存储内容的函数;

(6) 编写测试程序,对读写数据进行校验。


2.代码分析

代码清单1:I2C GPIO口初始化配置:

主要是完成对I2C引脚的初始化,把引脚初始化成复用开漏模式。

  1. static void I2C_GPIO_Config(void)

  2. {

  3. GPIO_InitTypeDef GPIO_InitStructure;

  4. EEPROM_I2C_CLK_INIT(EEPROM_I2C_CLK, ENABLE);

  5. RCC_AHB1PeriphClockCmd(EEPROM_I2C_SCL_GPIO_CLK | EEPROM_I2C_SDA_GPIO_CLK, ENABLE);

  6. GPIO_PinAFConfig(EEPROM_I2C_SCL_GPIO_PORT, EEPROM_I2C_SCL_SOURCE, EEPROM_I2C_SCL_AF);

  7. GPIO_PinAFConfig(EEPROM_I2C_SDA_GPIO_PORT, EEPROM_I2C_SDA_SOURCE, EEPROM_I2C_SDA_AF);

  8. GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;

  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  11. GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

  12. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  13. GPIO_Init(EEPROM_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

  14. GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;

  15. GPIO_Init(EEPROM_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);


代码清单2:I2C模式配置函数

根据CKS32F4xx系列产品IIC的配置所讲的对I2C进行配置,它把I2C外设通讯时钟SCL的低/高电平比设置为2,使能响应功能,使用7位地址 I2C_OWN_ADDRESS7以及速率配置为400Kbit/s。最后调用库函数I2C_Init把这些配置写入寄存器,并调用I2C_Cmd函数使能外设。


  1. static void I2C_Mode_Configu(void)

  2. {

  3. I2C_InitTypeDef I2C_InitStructure;

  4. I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

  5. I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

  6. I2C_InitStructure.I2C_OwnAddress1 =I2C_OWN_ADDRESS7;

  7. I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;

  8. I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

  9. I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;

  10. I2C_Init(EEPROM_I2C, &I2C_InitStructure);

  11. I2C_Cmd(EEPROM_I2C, ENABLE);

  12. I2C_AcknowledgeConfig(EEPROM_I2C, ENABLE);

  13. }


代码清单3:EEPROM单字节写入函数

  1. uint32_t I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)

  2. {

  3. I2C_GenerateSTART(EEPROM_I2C, ENABLE);

  4. I2CTimeout = I2CT_FLAG_TIMEOUT;

  5. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT))

  6. {

  7. if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(0);

  8. }

  9. I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);

  10. I2CTimeout = I2CT_FLAG_TIMEOUT;

  11. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  12. {

  13. if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(1);

  14. }

  15. I2C_SendData(EEPROM_I2C, WriteAddr);

  16. I2CTimeout = I2CT_FLAG_TIMEOUT;

  17. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  18. {

  19. if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(2);

  20. }

  21. I2C_SendData(EEPROM_I2C, *pBuffer);

  22. I2CTimeout = I2CT_FLAG_TIMEOUT;

  23. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  24. {

  25. if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);

  26. }

  27. I2C_GenerateSTOP(EEPROM_I2C, ENABLE);

  28. return 1;

  29. }


首先是I2C_TIMEOUT_UserCallback函数,这个函数的功能就是向串口打印调试信息。在I2C通讯的很多过程,都需要检测事件,当检测到某事件后才能继续下一步的操作,但有时通讯错误或者I2C总线被占用,我们不能无休止地等待下去,所以我们设定每个事件检测都有等待的时间上限,若超过这个时间,我们就调用I2C_TIMEOUT_UserCallback函数输出调试信息,并终止I2C通讯。


I2C_EE_ByteWrite函数,这个函数实现了前面讲的I2C主发送器通讯流程。

(1) 使用库函数I2C_GenerateSTART产生I2C起始信号,其中的EEPROM_I2C宏是I2C2;

(2) 对I2CTimeout变量赋值为宏I2CT_FLAG_TIMEOUT,这个I2CTimeout变量在下面的while循环中每次循环减 1,该循环通过调用库函数I2C_CheckEvent检测事件EV5,若检测到事件,则进入通讯的下一阶段,若未检测到事件则停留在此处一直检测,当检I2CT_FLAG_TIMEOUT 次都还没等待到事件则认为通讯失败,调用前面的I2C_TIMEOUT_UserCallbac输出调试信息,并退出通讯;

(3) 调用库函数I2C_Send7bitAddress发送EEPROM的设备地址,并把数据传输方向设置为I2C_Direction_Transmitter(即发送方向),这个数据传输方向就是通过设置I2C通讯中紧跟地址后面的R/W位实现的。发送地址后以同样的方式检测EV6标志;

(4) 调用库函I2C_SendDat向EEPROM发送要写入的内部地址,该地址是 I2C_EE_ByteWrite 函数的输入参数,发送完毕后等待EV8事件。要注意这个内部地址跟上面EEPROM 地址不一 样,上面的是指I2C总线设备的独立地址,而此处的内部地址是EEPROM内数据组织的地址,也可理解为EEPROM内存的地址或 I2C设备的寄存器地址;

(5) 调用库函数I2C_SendData向EEPROM发送要写入的数据,该数据是 I2C_EE_ByteWrite函数的输入参数,发送完毕后等待EV8事件;

(6) 一个I2C通讯过程完毕,调用I2C_GenerateSTOP发送停止信号。


代码清单4:EEPROM多字节快速写入函数

  1. void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)

  2. {

  3. u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

  4. Addr = WriteAddr % I2C_PageSize;

  5. count = I2C_PageSize - Addr;

  6. NumOfPage = NumByteToWrite / I2C_PageSize;

  7. NumOfSingle = NumByteToWrite % I2C_PageSize;

  8. if(Addr == 0)

  9. {

  10. if(NumOfPage == 0)

  11. {

  12. I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  13. I2C_EE_WaitEepromStandbyState();

  14. }

  15. else

  16. {

  17. while(NumOfPage--)

  18. {

  19. I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);

  20. I2C_EE_WaitEepromStandbyState();

  21. WriteAddr += I2C_PageSize;

  22. pBuffer += I2C_PageSize;

  23. }

  24. if(NumOfSingle!=0)

  25. {

  26. I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  27. I2C_EE_WaitEepromStandbyState();

  28. }

  29. }

  30. }

  31. else

  32. {

  33. if(NumOfPage== 0)

  34. {

  35. I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  36. I2C_EE_WaitEepromStandbyState();

  37. }

  38. else

  39. {

  40. NumByteToWrite -= count;

  41. NumOfPage = NumByteToWrite / I2C_PageSize;

  42. NumOfSingle = NumByteToWrite % I2C_PageSize;


  43. if(count != 0)

  44. {

  45. I2C_EE_PageWrite(pBuffer, WriteAddr, count);

  46. I2C_EE_WaitEepromStandbyState();

  47. WriteAddr += count;

  48. pBuffer += count;

  49. }

  50. while(NumOfPage--)

  51. {

  52. I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);

  53. I2C_EE_WaitEepromStandbyState();

  54. WriteAddr += I2C_PageSize;

  55. pBuffer += I2C_PageSize;

  56. }

  57. if(NumOfSingle != 0)

  58. {

  59. I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);

  60. I2C_EE_WaitEepromStandbyState();

  61. }

  62. }

  63. }

  64. }


这段代码是快速的向EEPROM写入多个字节。pBuffer是缓冲区的指针,WriteAddr是写入的地址,NumByteToWrite是要写入的字节数。代码的主旨就是对输入的数据进行分页(AT24C02每页8个字节)。通过“整除”计算出要写入的数据NumByteToWrite能写满多少“完整的页”,计算得到的值存储在 NumOfPage中,但有时数据不是刚好能写满完整页的,会多一点出来,通过“求余”计算得出“不满一页的数据个数”就存储在NumOfSingle中。


除了基本的分页传输,还要考虑首地址的问题。若首地址不是刚好对齐到页的首地址,会需要一个count值,用于存储从该首地址开始写满该地址所在的页,还能写多少个数据。实际传输时,先把这部分count个数据先写入,填满该页,然后把剩余的数据(NumByteToWrite-count),再重复上述求出NumOPage及 NumOfSingle的过程,按页传输到EEPROM。


代码清单5:EEPROM读取数据函数

  1. uint32_t I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)

  2. {

  3. I2CTimeout = I2CT_LONG_TIMEOUT;

  4. while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY))

  5. {

  6. if((I2CTimeout--) == 0)

  7. return I2C_TIMEOUT_UserCallback(9);

  8. }

  9. I2C_GenerateSTART(EEPROM_I2C, ENABLE);

  10. I2CTimeout = I2CT_FLAG_TIMEOUT;

  11. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT))

  12. {

  13. if((I2CTimeout--) == 0)

  14. return I2C_TIMEOUT_UserCallback(10);

  15. }

  16. I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);

  17. I2CTimeout = I2CT_FLAG_TIMEOUT;

  18. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))

  19. {

  20. if((I2CTimeout--) == 0)

  21. return I2C_TIMEOUT_UserCallback(11);

  22. }

  23. I2C_Cmd(EEPROM_I2C, ENABLE);

  24. I2C_SendData(EEPROM_I2C, ReadAddr);

  25. I2CTimeout = I2CT_FLAG_TIMEOUT;

  26. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))

  27. {

  28. if((I2CTimeout--) == 0)

  29. return I2C_TIMEOUT_UserCallback(12);

  30. }

  31. I2C_GenerateSTART(EEPROM_I2C, ENABLE);

  32. I2CTimeout = I2CT_FLAG_TIMEOUT;

  33. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT))

  34. {

  35. if((I2CTimeout--) == 0)

  36. return I2C_TIMEOUT_UserCallback(13);

  37. }

  38. I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Receiver);

  39. I2CTimeout = I2CT_FLAG_TIMEOUT;

  40. while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))

  41. {

  42. if((I2CTimeout--) == 0)

  43. return I2C_TIMEOUT_UserCallback(14);

  44. }

  45. while(NumByteToRead)

  46. {

  47. if(NumByteToRead == 1)

  48. {

  49. I2C_AcknowledgeConfig(EEPROM_I2C, DISABLE);

  50. I2C_GenerateSTOP(EEPROM_I2C, ENABLE);

  51. }

  52. I2CTimeout = I2CT_LONG_TIMEOUT;

  53. while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)

  54. {

  55. if((I2CTimeout--) == 0)

  56. return I2C_TIMEOUT_UserCallback(3);

  57. }

  58. {

  59. *pBuffer = I2C_ReceiveData(EEPROM_I2C);

  60. pBuffer++;

  61. NumByteToRead--;

  62. }

  63. }

  64. I2C_AcknowledgeConfig(EEPROM_I2C, ENABLE);

  65. return 1;

  66. }


从EEPROM读取数据是一个复合的I2C时序,它实际上包含一个写过程和一个读过程。第一个通讯过程中,使用I2C发送设备地址寻址 (写方向),接着发送要读取的“内存地址”, 代码的流程和前面讲的CKS32的IIC作为通讯的主机端向外发送数据的过程是一致的;第二个通讯过程中,再次使用I2C发送设备地址寻址,但这个时候的数据方向是读方向;在这个过程之后,EEPROM 会向主机返回从读“内存地址”开始的数据,一个字节一个字节地传输,只要主机的响应为“应答信号”,它就会一直传输下去,主机想结束传输时,就发送“非应 答信号”,并以“停止信号”结束通讯,作为从机的 EEPROM 也会停止传输。代码的流程和前面讲的CKS32的IIC作为通讯的主机端从外面接收数据的过程是一致的。


  1. uint8_t I2C_Test(void)

  2. {

  3. u16 i;

  4. EEPROM_INFO("写入的数据");

  5. for ( i=0; i<=10; i++ )

  6. {

  7. I2c_Buf_Write[i] = i;

  8. printf("0x%02X ", I2c_Buf_Write[i]);

  9. }

  10. I2C_EE_BufferWrite( I2c_Buf_Write, EEP_Firstpage, 11);

  11. EEPROM_INFO("写成功");

  12. EEPROM_INFO("读出的数据");

  13. I2C_EE_BufferRead(I2c_Buf_Read, EEP_Firstpage, 11);

  14. for (i=0; i<11; i++)

  15. {

  16. if(I2c_Buf_Read[i] != I2c_Buf_Write[i])

  17. {

  18. printf("0x%02X ", I2c_Buf_Read[i]);

  19. EEPROM_ERROR("错误:I2C EEPROM写入与读出的数据不一致");

  20. return 0;

  21. }

  22. printf("0x%02X ", I2c_Buf_Read[i]);

  23. }

  24. EEPROM_INFO("I2C(AT24C02)读写测试成功");

  25. return 1;

  26. }


代码中先填充一个数组,数组的内容为 0,1,2 至 10,接着利用前面讲到的函数I2C_EE_BufferWrite把这个数组的内容写入到EEPROM中。写入完毕后再利用前面讲到的函数I2C_EE_BufferRead从EEPROM的地址中读取数据, 把读取到的数据与写入的数据进行校验,若一致说明读写正常,并打印输出数据。否则读写过程有问题或者EEPROM芯片不正常,打印相应的错误信息。

  1. int main(void)

  2. {

  3. GPIO_Configuration();

  4. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2

  5. USART_Configuration();

  6. I2C_EE_Init();

  7. printf("start\r\n");

  8. I2C_Test();

  9. while (1)

  10. {

  11. }

  12. }


主函数代码比较简单,主要是完成GPIO初始化、串口初始化和I2C的初始化,初始化完成之后会执行一次I2C_Test函数,在串口调试助手上会打印输出一些信息。

授权代理商:世强先进(深圳)科技股份有限公司
技术资料,数据手册,3D模型库,原理图,PCB封装文件,选型指南来源平台:世强硬创平台www.sekorm.com
现货商城,价格查询,交期查询,订货,现货采购,在线购买,样品申请渠道:世强硬创平台电子商城www.sekorm.com/supply/
概念,方案,设计,选型,BOM优化,FAE技术支持,样品,加工定制,测试,量产供应服务提供:世强硬创平台www.sekorm.com
集成电路,电子元件,电子材料,电气自动化,电机,仪器全品类供应:世强硬创平台www.sekorm.com
  • +1 赞 0
  • 收藏
  • 评论 0

本文由拾一转载自中科芯MCU公众号,原文标题为:MCU微课堂 | CKS32F4xx系列产品IIC通信,本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

评论

   |   

提交评论

全部评论(0

暂无评论

相关推荐

【经验】中科芯CKS32F1系列MCU替代其他厂牌产品兼容性问题处理注意事项

中科芯基于ARM Cortex-M3的CKS32F1系列MCU功耗较国外品牌低20%,有多种低功耗模式。多重、多样化保护机制,自定义分级读写保护更是提高了产品的安全性。但是在与其他品牌产品进行替换时会遇到一些兼容性问题,在此将常见的问题和解决办法进行说明。

设计经验    发布时间 : 2020-03-08

中科芯CKS32K148系列MCU SCG寄存器配置以及相关示例(二)

在前文中,已经对中科芯CKS32K148 MCU SCG时钟进行了整体介绍,下面以RUN模式下配置SPLL为系统时钟源为例,对时钟配置的具体方法进行讲解。

设计经验    发布时间 : 2024-10-31

解析中科芯CKS32F107xx系列MCU的GPIO配置

本文中中科芯来给大家介绍CKS32F107xx系列MCU的GPIO配置,希望对各位工程师有所帮助。GPIO是通用输入输出端口的简称,也是CKS32可控制的引脚,CKS32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。

设计经验    发布时间 : 2024-06-12

中科芯(CETC)32位MCU选型指南

目录- 公司简介    MCU    MCU型号定义&封装参考    MCU开发工具    LoRa/ NB-IoT    LoRa/ NB-IoT产品简介    MCU应用案例   

型号- CKS32F103V8T6,CKS32F031K6U6,CKS32F102C6T6,CKS32F417ZET6,CKS32F105VDT6,CKS32F107,SX1262,CKS32F105,CKS32F102R4T6,CKS32F103,CKS32F101,CKS32F102,CKS32F101R6T6,CKS32F103C4T6,CKS32F051K6U6,CKS32F101ZCT6,CKS32F030F6P6,CKS32F101VET6,CKS32F417VGT6,SX1280,CKS32L063C8T6,CKS32F031F4P6,CKS32F101C8T6,CKS32F107V8T6,SX1278,CKS32F103RCT6,CKS32F107RBT6,CKS32F051K6T6,CKS32F405ZGT6,TP20L607,CKS32F103ZET6,CKS32L052R6T6,CKS32L052C8T6,CKS32F105VCT6,CKS32F107系列,CKS32F105RET6,CKS32L051系列,CKS32L051R8T6,CKS32L053C6T6,CKS32F101ZDT6,CRF-62,CKS32F072R6T6,CKS32F051系列,CKS32F103RDT6,CKS32F072C8T6,CKS32F103VBT6,CKS32F030K6T6,CKS32F042K8T6,CKS32F407VET6,CKS32F103R4T6,CKS32F415系列,CKS32F103ZDT6,CKS32F102C8T6,CKS32F417ZGT6,CKS32F042系列,CKS32F105VBT6,CKS32F030R8T6,CKS32F102R6T6,CKS32F105RDT6,CRF62-LKWAN-CY,CKS32F103C6T6,CKS32L052系列,CKS32F030K6U6,CKS32F102系列,CKS32F101R8T6,CKS32F030F4P6,CKS32F101ZET6,CKS32L063R8T6,CKS32F101CBT6,CKS32F031系列,CKS32F107R8T6,CKS32F031G6U6,CKS32F103RET6,CKS32L051K6T6,CRF1278系列,CKS32F415RGT6,CKS32L063系列,CKS32F103VCT6,CKS32F051C8T6,CKS32F103ZCT6,CKS32F417IET6,CKS32L052R8T6,CKS32F105RCT6,CKS32L053系列,CRF1278,CKS32F051R8T6,CKS32F101系列,CKS32L053C8T6,CKS32F072CBT6,CKS32F105V8T6,CKS32F407ZET6,CKS32F101RBT6,CKS,CKS32F030系列,CKS32F072R8T6,CRF62-L2,CRF62-L5,CKS32F042C6T6,CKS32F103VDT6,CKS32L053R6T6,CKS32F107VET6,CKS32F407VGT6,CKS32F103R6T6,CKS32F417系列,CKS32F030C8T6,CKS32F102R8T6,CKS32F105RBT6,CKS32F031C6T6,CKS32F103C8T6,CKS32F102CBT6,CKS32F405系列,CKS32F101RCT6,CKS32L052K6T6,CKS32F415VGT6,CKS32F031G4U6,CKS32F103VET6,CKS32F107VDT6,CKS32F051,CKS32F051C6T6,CKS32L051K8T6,CKS32F417IGT6,CRF-62系列,CRF62-WAN,CKS32,CKS32F103系列,CKS32F072RBT6,CKS32F042,CKS32F407IET6,CKS32F405RGT6,CRF1280-12S,CKS32F107RET6,CKS32F407ZGT6,CKS32F101VBT6,CKS32F102RBT6,CKS32F101RDT6,CKS32L053R8T6,CKS32F031,CKS32F103R8T6,CKS32F042C8T6,CKS32F107VCT6,CKS32F030,CRF1278-L3,CRF1278-L1,CKS32F030C6T6,XY1100,CRF1278-L4,CKS32F103CBT6,CKS32F030K6,CKS32F102C4T6,ASR6601,CKS32F101R4T6,CKS32F105R8T6,CKS32F051K8U6,CKS32F407系列,CKS32F107RDT6,CKS32F101VCT6,CKS32F415ZGT6,CKS32F101RET6,CKS32L052K8T6,CKS32F417,CKS32F417VET6,CKS32F101C6T6,CKS32F415,CKS32F031F6P6,CKS32F107VBT6,CKS32L051C6T6,CKS32F051K8T6,TP20H607,CKS32L051C8T6,CKS32F042K6T6,CKS32L052C6T6,ASR6505,CKS32F105VET6,CKS32F407,CKS32F405,ASR6501,ASR6502,CKS32X...,CKS32F105系列,CKS32L051R6T6,CKS32L063,CKS32F407IGT6,CKS32F405VGT6,CKS32F072,CKS32F101VDT6,CKS32F072系列,CKS32F031K6T6,CKS32F103RBT6,CKS32F072C6T6,CRF1100-N1,CKS32L052,CKS32F107RCT6,CKS32L051,CKS32L053

选型指南  -  中科芯  - 2022/4/24 PDF 中文 下载

Top Chinese 8/32-bit MCU Manufacturers with ARM Cortex-M0, M0+, M3, M4 and Stable Supply

In the face of rising semiconductor raw material prices and a continued shortage of production capacity, Sekorm has joined Civil Technology, Arteli, Chipsea, China Microelectronics, Fudan Microelectronics, Aerospace Shun, and other mainstream MCU manufacturers to provide stable MCU supply guarantees

活动    发布时间 : 2022-06-21

中科芯(CETC)CKS32F030C8/C6/K6/F4 32位MCU数据手册

描述- 本资料给出了中科芯CKS32F030 xx 微控制器产品的器件特性

型号- CKS32F030XX,CKS32F030C6,CKS32F030R8T6XXX,CKS32F030C8,CKS32,CKS32F030K6,CKS32F030F4

数据手册  -  中科芯  - v1.0  - 2018年4月9日 PDF 中文 下载

中科芯CKS32K148系列MCU SCG(系统时钟发生器)模块应用指南(一)

系统时钟发生器(SCG)是MCU中的重要模块,它能够为芯片提供多个灵活的时钟源,并支持各种时钟输出选项,实现对芯片内部各个模块的时钟供应。CKS32K148的时钟生成电路提供了各种时钟分频器和选择器,允许不同的模块以该模块特定的频率运行,而时钟生成逻辑实现了可以独立关闭的模块特定时钟门控,从而能够优化芯片性能以满足低功耗的需求。本文将围绕CKS32K148的SCG模块展开介绍。

技术探讨    发布时间 : 2024-09-27

【选型】中科芯(CETC)CKS32通用32位MCU快速选型指南

目录- CKS32F030超值型-48Mhz/CKS32F031入门型-48Mhz    CKS32F051入门型-48Mhz/CKS32F103系列-72MHz   

型号- CKS32F051K8T6,CKS32F051K6T6,CKS32F030C6T6,CKS32F030C8T6,CKS32F031K6U6,CKS32F103CBT6,CKS32F030R8T6,CKS32F031C6T6,CKS32F103,CKS32,CKS32F030K6U6,CKS32F051R8T6,CKS32F103C8T6,CKS32F103TBU6,CKS32F103T8U6,CKS32F030F4P6,CKS32F051K8U6,CKS32F051K6U6,CKS32F030F6P6,CKS32F031K6T6,CKS32F031F4P6,CKS32F103RBT6,CKS32F103VBT6,CKS32F030K6T6,CKS32F031F6P6,CKS32F031,CKS32F051C8T6,CKS32F103R8T6,CKS32F051,CKS32F030

选型指南  -  中科芯 PDF 中文 下载

解析中科芯CKS32F107xx MCU的DAC模块

DAC即数模转换器,它可以将数字信号转换为模拟信号。在常见的数字信号系统中,传感器信号被ADC模块把电压模拟信号转换成易于计算机存储、处理的数字信号,由计算机处理完成后,再由DAC模块转化输出电压模拟信号来驱动某些执行器件。本文将为您解析CKS32F107xx MCU的DAC特点和结构。

设计经验    发布时间 : 2024-08-28

【产品】国产32位MCU、从M0到M4内核8大系列产品和STM32软硬件全兼容 | 视频

在2021年4年27日主控器件及存储专场|世强硬创新产品研讨会中,中科芯分享了其32位通用MCU,从M0到M4内核8大系列产品,同STM32软硬件全兼容,并且讲解了在工业、物联网、通信领域的应用。

新产品    发布时间 : 2021-04-29

【经验】中科芯CKS32F4xx系列MCU DAC功能应用指南

DAC模块作为中科芯CKS32F4xx系列MCU的一个常用外设,可以将数字信号转换成模拟信号,最高分辨率可达12位,且两个独立DAC输出通道转换互不影响,各个通道均能使用DMA功能,可由软硬件触发。因此,为了实现DAC输出正弦波,拟采用一定的时间向DAC的数据寄存器写入数据,随后进行数模转换输出不同的电压,最后在时间轴上显示出波形。

设计经验    发布时间 : 2023-08-19

中科芯CKS32F107xx系列MCU内部温度传感器ADC采集应用指南

中科芯推出的CKS32F107xx系列MCU有一个内部的温度传感器,可以用来测量MCU及周围的温度(TA)。该温度传感器在内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值。

设计经验    发布时间 : 2024-08-13

中科芯CKS32F4xx系列MCU Flash模拟EEPROM的操作应用指南

中科芯CKS32F4xx系列芯片内部嵌入一个FLASH,若FLASH存储了用户的应用程序后仍留有空间,剩余空间可被当作EEPROM使用,这比访问外部FLASH速度优势更为明显。在本章节中,将会向大家简要介绍内部FLASH,并通过一个例程来演示FLASH模拟EEPROM的操作。

设计经验    发布时间 : 2024-02-22

【经验】中科芯CKS32F4xx系列MCU SPI通信配置及读写SPI FLASH指南

中科芯CKS32F4xx系列MCU的SPI外设可用作通讯的主机及从机,支持最高的SCK时钟频率为fpclk/2,完全支持SPI协议的4种模式。本文介绍利用CKS32F4xx系列固件库来完成对SPI的配置使用及SPI FLASH实验。

设计经验    发布时间 : 2023-04-24

中科芯MCU诚邀新老朋友莅临上海慕尼黑电子展交流指导

中科芯MCU诚邀新老朋友2024年7月8日-10日莅临上海慕尼黑电子展交流指导!望与客户朋友们洽谈合作、携手共赢!

原厂动态    发布时间 : 2024-07-08

展开更多

电子商城

查看更多

品牌:中科芯

品类:32位微控制器

价格:¥5.3000

现货: 270

品牌:中科芯

品类:32位MCU

价格:¥5.2000

现货: 265

品牌:中科芯

品类:32位MCU

价格:¥21.0000

现货: 100

品牌:中科芯

品类:32位微控制器

价格:¥8.0000

现货: 90

品牌:中科芯

品类:32位微控制器

价格:¥18.0000

现货: 65

品牌:中科芯

品类:开发板

价格:¥200.0000

现货: 6

品牌:中科芯

品类:开发板

价格:¥200.0000

现货: 6

品牌:中科芯

品类:开发板

价格:¥200.0000

现货: 6

品牌:中科芯

品类:开发板

价格:¥200.0000

现货: 6

品牌:中科芯

品类:开发板

价格:¥200.0000

现货: 6

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

现货市场

查看更多

品牌:RENESAS

品类:16-BIT MCU

价格:¥5.5190

现货:910,635

品牌:RENESAS

品类:MCU

价格:¥5.1500

现货:200,000

品牌:恒烁

品类:MCU

价格:¥1.0800

现货:154,600

品牌:Advanced Digital Chips

品类:MCU

价格:¥6.6000

现货:100,000

品牌:RENESAS

品类:MCU

价格:¥5.8041

现货:86,925

品牌:RENESAS

品类:32-BIT GENERAL MCU

价格:¥7.3800

现货:76,715

品牌:RENESAS

品类:32-BIT GENERAL MCU

价格:¥15.3000

现货:75,000

品牌:Advanced Digital Chips

品类:MCU

价格:¥9.0000

现货:64,841

品牌:ST

品类:MCU

价格:¥15.5600

现货:58,800

品牌:RENESAS

品类:32-BIT GENERAL MCU

价格:¥257.6400

现货:58,799

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

服务

查看更多

TFT LCD液晶显示屏/模组定制

可定制显示屏的尺寸0.96”~15.6”,分辨率80*160~3840*2160,TN/IPS视角,支持RGB、MCU、SPI、MIPI、LVDS、HDMI接口,配套定制玻璃、背光、FPCA/PCBA。

最小起订量: 1000 提交需求>

MCU烧录/Flash烧录/CPLD烧录

可烧录IC封装SOP/MSOP/SSOP/TSOP/TSSOP/PLCC/QFP/QFN/MLP/MLF/BGA/CSP/SOT/DFN;IC包装Tray/Tube/Tape;IC厂商不限,交期1-3天。支持IC测试(FT/SLT),管装、托盘装、卷带装包装转换,IC打印标记加工。

最小起订量: 1pcs 提交需求>

查看更多

授权代理品牌:接插件及结构件

查看更多

授权代理品牌:部件、组件及配件

查看更多

授权代理品牌:电源及模块

查看更多

授权代理品牌:电子材料

查看更多

授权代理品牌:仪器仪表及测试配组件

查看更多

授权代理品牌:电工工具及材料

查看更多

授权代理品牌:机械电子元件

查看更多

授权代理品牌:加工与定制

世强和原厂的技术专家将在一个工作日内解答,帮助您快速完成研发及采购。
我要提问

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

研发客服
商务客服
服务热线

联系我们

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

投诉与建议

E-mail:claim@sekorm.com

商务合作

E-mail:contact@sekorm.com

收藏
收藏当前页面