[CW32F030系列] 【CW32F030CxTx StartKit测评】04.I2C主从机功能验证

[复制链接]
2561|22
 楼主| xld0932 发表于 2022-7-9 10:06 | 显示全部楼层 |阅读模式
本帖最后由 xld0932 于 2022-7-9 16:18 编辑

【CW32F030CxTx StartKit测评】04.I2C主机模式读写EEPROM、I2C从机模式多地址通讯


概述
本文来学习一下CW32F030系列MCU的硬件I2C通讯接口功能:通过I2C1主机模式实现对板载EEPROM(CW24C02A)的读写操作、通过I2C2从机模式实现多从机地址的通讯功能,使用外部的I2C主机设备进行测试。除此之外,本篇将会附带一些Letter-shell的调试功能实操,Letter-shell不会专门讲解,大家可以通过实操来了解Letter-shell的功能,当然有兴趣的可以自己研究其强大的功能,主要还是将Letter-shell当作在线调试工具来使用、方便调试实现功能。


EEPROM
CW32F030CxTx StartKit开发板上板载了一颗芯源的串行电可擦除只读存储器(EEPROM):CW24C02A,两线串行接口方式,通过I2C协议实现双向数据传输;其容量大小为2K位(256字节);支持1.7V至5.5V的宽范围工作电压,当工作在1.7V电压时I2C最大传输速率可达到400KHz,当工作在3V或者5V电压时I2C最大传输速率可达到1MHz;CW24C02A通过页写的方式写入数据,每页大小为8个字节,共有32个页面,且内部最大写周期不超过4ms;其本身的高可靠性,被广泛应用在智能化仪器仪表、家用电器、汽车电子、通讯设备、消费类电子等众多领域。


EEPROM原理图
CW24C02A作为I2C从设备,本身的器件硬件地址由芯片A0/A1/A2这三个引脚电平的高低状态决定的,如下原理图所示A0/A1/A2这三个引脚都连接到GND,所以CW24C02A的I2C器件地址为0xA0;原理图中CW24C02A的WP引脚提供硬件数据的写保护功能,当前设计也是连接到GND,指示当允许正常的读写数据,假若WP连接VCC时,芯片就会启动写保护功能,无法将数据正常写入到芯片内部存储空间进行存储了。需要注意的是,开发板上EEPROM电路是一个独立的模块,提供操作接口CN11,当我们需要实现EEPROM实验操作时,需要将CN11上的VDDE连接到VDD电源,将SCL与SDA连接到MCU的I2C端口引脚上。
1.png


CW32F030 I2C
CW32F030内部集成了2个I2C控制器(I2C1和I2C2),这两个接口的时钟源将挂载在APB总线上(PCLK),这个在设置I2C通讯速率的计算公式中会乃至哦……CW32F030 I2C接口能够按照设定的传输速率将需要发送的数据按照I2C规范串行发送到I2C总线上,并对通讯过程中的状态进行侦测,另外还支持多主机通讯中的总线冲突和仲裁处理功能。主要特性如下:
  • 支持主机发送/接收、从机发送/接收四种工作模式
  • 支持时钟延展(时钟同步)和多主机通讯冲突仲裁
  • 支持标准(100Kbps)、快速(400Kbps)、高速(1Mbps)三种工作速率
  • 支持7-bit寻址功能
  • 支持3个从机地址
  • 支持广播地址
  • 支持输入信号噪声过滤功能
  • 支持中断状态查询功能


I2C主机模式读写EEPROM存储器
在CW32F030在I2C作为主机设备操作EEPROM设备时,在官方库函数中提供了直接操作EEPROM的函数接口:
  1. void I2C_MasterWriteEepromData(I2C_TypeDef *I2Cx,uint8_t u8Addr,uint8_t *pu8Data,uint32_t u32Len)

  2. void I2C_MasterReadEepomData(I2C_TypeDef *I2Cx,uint8_t u8Addr,uint8_t *pu8Data,uint32_t u32Len)
我们只需要调用这两个函数接口,传递相应的参数就可以完成对EEPROM的读写操作了,而对于EEPROM器件地址的定义我们可以在cw32f030_i2c.h这个头文件中对I2C_SLAVEADDRESS这个宏定义的数值直接修改即可,实现代码如下:
  1. void EEPROM_Init(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     I2C_InitTypeDef  I2C2_InitStructure;

  5.     RCC_AHBPeriphClk_Enable( RCC_AHB_PERIPH_GPIOB, ENABLE);
  6.     RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_I2C2, ENABLE);

  7.     PB10_AFx_I2C2SCL();
  8.     PB11_AFx_I2C2SDA();

  9.     GPIO_InitStructure.Pins  = GPIO_PIN_10 | GPIO_PIN_11;
  10.     GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_OD;
  11.     GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
  12.     GPIO_Init(CW_GPIOB, &GPIO_InitStructure);

  13.     I2C2_DeInit();

  14.     I2C2_InitStructure.I2C_BaudEn = ENABLE;
  15.     I2C2_InitStructure.I2C_Baud   = RCC_Sysctrl_GetPClkFreq() / 1000000 - 1;
  16.     I2C2_InitStructure.I2C_FLT    = DISABLE;
  17.     I2C2_InitStructure.I2C_AA     = DISABLE;
  18.     I2C_Master_Init(CW_I2C2, &I2C2_InitStructure);

  19.     I2C_Cmd(CW_I2C2, ENABLE);
  20. }

  21. void EEPROM_SHELL_Handler(uint8_t Mode, uint8_t Page)
  22. {
  23.     uint8_t wBuffer[EEPROM_PAGE_SIZE];
  24.     uint8_t rBuffer[EEPROM_PAGE_SIZE];

  25.     memset(wBuffer, 0, sizeof(wBuffer));
  26.     memset(rBuffer, 0, sizeof(rBuffer));

  27.     if(Page < EEPROM_PAGE_NUMBER)
  28.     {
  29.         if(Mode == 1)   /* Write */
  30.         {
  31.             srand(GetTick());

  32.             for(uint8_t i = 0; i < sizeof(wBuffer); i++)
  33.             {
  34.                 wBuffer[i] = rand() % 256;
  35.             }

  36.             printf("\r\nEEPROM Write...");

  37.             for(uint8_t i = 0; i < sizeof(wBuffer); i++)
  38.             {
  39.                 if((i % 16) == 0) printf("\r\n");
  40.                 printf("0x%02x ",    wBuffer[i]);
  41.             }

  42.             printf("\r\nPage    : %d", Page);
  43.             printf("\r\nAddress : %d", Page * EEPROM_PAGE_SIZE);
  44.             printf("\r\nLength  : %d", sizeof(wBuffer));

  45.             I2C_MasterWriteEepromData(CW_I2C2, Page * EEPROM_PAGE_SIZE, wBuffer, sizeof(wBuffer));

  46.             printf("\r\nEEPROM Write OK");
  47.             printf("\r\n");
  48.         }
  49.         else            /* Read  */
  50.         {
  51.             printf("\r\nEEPROM Read....");

  52.             printf("\r\nPage    : %d", Page);
  53.             printf("\r\nAddress : %d", Page * EEPROM_PAGE_SIZE);
  54.             printf("\r\nLength  : %d", sizeof(rBuffer));

  55.             I2C_MasterReadEepomData(CW_I2C2, Page * EEPROM_PAGE_SIZE, rBuffer, sizeof(rBuffer));

  56.             for(uint8_t i = 0; i < sizeof(rBuffer); i++)
  57.             {
  58.                 if((i % 16) == 0) printf("\r\n");
  59.                 printf("0x%02x ",    rBuffer[i]);
  60.             }

  61.             printf("\r\n");
  62.         }
  63.     }
  64.     else
  65.     {
  66.         printf("\r\nInvalid EEPROM Page!\r\n");
  67.     }
  68. }
  69. SHELL_EXPORT_CMD(
  70. SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN|SHELL_CMD_PARAM_NUM(2),
  71. EEPROM, EEPROM_SHELL_Handler, EEPROM Write And Read);


硬件连接图
2.jpg


在线调试
在PC端口使用MobaXterm终端调试软件,打开对应的串口,正确设置串口通讯参数;输入EEPROM命令,这个命令带有两个参数:第一个参数0表示读取EEPROM数据,1表示将数据写入到EEPROM;第二个参数表示EEPROM PAGE编号,此编号范围为0到31。运行结果如下图:
4.png

实测通讯速率
3.bmp


I2C从机模式多地址通讯
CW32F030 I2C工作在从机模式时,同时支持3个从设备地址,这三个从设备地址可以通过cw32f030_i2c.h这个头文件中OwnSlaveAddress0/OwnSlaveAddress1/OwnSlaveAddress2这3个宏进行修改,我们使用查询的方式配合外部的I2C主机来进行测试,从机代码实现如下:
  1. void sEEPROM_Init(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     I2C_InitTypeDef  I2C1_InitStructure;

  5.     RCC_AHBPeriphClk_Enable( RCC_AHB_PERIPH_GPIOB, ENABLE);
  6.     RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_I2C1, ENABLE);

  7.     PB06_AFx_I2C1SCL();
  8.     PB07_AFx_I2C1SDA();

  9.     GPIO_InitStructure.Pins  = GPIO_PIN_6 | GPIO_PIN_7;
  10.     GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_OD;
  11.     GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
  12.     GPIO_Init(CW_GPIOB, &GPIO_InitStructure);

  13.     I2C1_DeInit();

  14.     I2C1_InitStructure.I2C_OwnSlaveAddr0 = OwnSlaveAddress0;
  15.     I2C1_InitStructure.I2C_OwnSlaveAddr1 = OwnSlaveAddress1;
  16.     I2C1_InitStructure.I2C_OwnSlaveAddr2 = OwnSlaveAddress2;
  17.     I2C1_InitStructure.I2C_OwnGc         = DISABLE;
  18.     I2C1_InitStructure.I2C_FLT           = DISABLE;
  19.     I2C1_InitStructure.I2C_AA            = DISABLE;
  20.     I2C_Slave_Init(CW_I2C1, &I2C1_InitStructure);

  21.     I2C_Cmd(CW_I2C1, ENABLE);

  22.     I2C_AcknowledgeConfig(CW_I2C1, ENABLE);
  23. }

  24. void sEEPROM_SHELL_Handler(uint8_t Times)
  25. {
  26.     uint8_t  Buffer[100];
  27.     uint32_t rLength = 0, wLength;

  28.     while(Times--)
  29.     {
  30.         printf("\r\nWait I2C Master Write Data...\r\n");

  31.         /* 等待主机写入数据 */
  32.         I2C_SlaveRecDataFromMaster(CW_I2C1, Buffer, &rLength);

  33.         printf("\r\nI2C Receive :");

  34.         for(uint8_t i = 0; i < rLength; i++)
  35.         {
  36.             if((i % 16) == 0) printf("\r\n");
  37.             printf("0x%02x ", Buffer[i]);
  38.         }

  39.         printf("\r\n");
  40.         printf("\r\nWait I2C Master Read Data...\r\n");

  41.         /* 等待主机读取数据 */
  42.         I2C_SlaveSendDataToMaster(CW_I2C1, Buffer, &wLength);

  43.         printf("\r\nI2C Master Read %d Bytes!\r\n", wLength);
  44.     }
  45. }
  46. SHELL_EXPORT_CMD(
  47. SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN|SHELL_CMD_PARAM_NUM(1),
  48. SEEPROM, sEEPROM_SHELL_Handler, sEEPROM Write And Read);


硬件连接
5.jpg

在线调试
首先在MobaXterm终端软件上输入sEEPROM的SHELL命令,我们可以理解为I2C从机当作是模拟EEPROM设备;后面跟着一个参数,意思是读写操作需要循环几次完成;因为I2C从机设备支持3个地址,我们为了把地址都测试一遍,我们这边输入的SHELL命令为sEEPROM 3,在输入完命令后,MCU就进入到等待I2C主机操作的状态了。

我们打开Toomoss的上位机软件,选择USB2I2C功能,如下界面所示;因为我们是直接将调试工具与MCU引脚连接在一起的,所以建议将内部上拉使能,这样可以保证高通讯速率下的波形正常、稳定;然后在从机地址栏依次输入0x50、0x58、0x60,点击下方的写数据和读数据来测试通讯结果,如下图所示:
7.png 6.png


附件
程序源代码:
Template.zip (5.09 MB, 下载次数: 20) (仅I2C主机模式)
Template.zip (5.09 MB, 下载次数: 22) (I2C主从机模式)
CW24C02A: CW24C02A.pdf (1.06 MB, 下载次数: 9)

海滨消消 发表于 2022-7-13 15:57 来自手机 | 显示全部楼层
最近论坛里测评贴很多了
huquanz711 发表于 2022-7-13 18:19 来自手机 | 显示全部楼层
letter shell看起来不错啊
NOo02 发表于 2022-7-13 19:10 | 显示全部楼层
楼主这个读IIC的上位机软件怎么下载啊,给个链接
 楼主| xld0932 发表于 2022-7-13 20:44 | 显示全部楼层
NOo02 发表于 2022-7-13 19:10
楼主这个读IIC的上位机软件怎么下载啊,给个链接

图莫斯官方上有下载,需要有配套的工具的
www5911839 发表于 2022-7-13 23:56 | 显示全部楼层
感谢大佬分享,授人以渔,非常感谢
minzisc 发表于 2022-10-10 20:56 | 显示全部楼层
两个不同的芯片之间用IIC通信,如何实现?
claretttt 发表于 2022-10-10 21:06 | 显示全部楼层
I2C的主从模式怎么切换              
yeates333 发表于 2022-10-10 21:23 | 显示全部楼层
软件模拟IIC主从机可以产生中断吗
loutin 发表于 2022-10-10 21:49 | 显示全部楼层
iic总线实现双机通信               
jackcat 发表于 2022-10-11 21:41 | 显示全部楼层

I2C设备主机与从机地址设置   
mattlincoln 发表于 2022-11-1 10:03 | 显示全部楼层
如何使用dma mode进行i2c传输
robincotton 发表于 2022-11-1 10:23 | 显示全部楼层
i2c协议的问题,请问主机如果读从机的数据,怎么知道从机是否响应  
eefas 发表于 2022-11-1 11:00 | 显示全部楼层
I2C的从模式与主模式的区别是什么?
uiint 发表于 2022-11-1 11:35 | 显示全部楼层
I2C总线的应答信号是从器件发出的么?
primojones 发表于 2022-11-1 15:12 | 显示全部楼层
对于没有IIC接口的CPU,如何连接IIC设备?
eefas 发表于 2022-11-1 15:59 | 显示全部楼层
一个MCU有两组I2C,那这个MCU可以做主机的同时也可以做从机吗
claretttt 发表于 2022-11-1 16:49 | 显示全部楼层
I2c总线一般拿来实现什么功能?
maudlu 发表于 2022-11-1 17:56 | 显示全部楼层
如何检测i2c的开始条件和结束条件
robertesth 发表于 2022-11-1 18:47 | 显示全部楼层
i2c总线中从机地址怎么设置  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:King.Xu

77

主题

3023

帖子

38

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