[开发资料] 基于芯源CW32F030 MCU的I2C通信与应用

[复制链接]
1635|16
 楼主| Clyde011 发表于 2024-10-10 08:22 | 显示全部楼层 |阅读模式

芯源微的CW32F030是一款基于Arm Cortex-M0内核的32位低功耗MCU,具备高性能和丰富的外设功能,广泛应用于物联网、智能家居、工业控制等领域。CW32F030支持包括I2C、SPI、UART等多种通信接口,其中I2C接口由于其简单、节省引脚的特性,广泛用于与传感器、存储器等外围设备的通信。本文将介绍如何使用CW32F030 MCU实现I2C通信,并通过代码示例展示如何与外部I2C设备进行数据交互。

1. 硬件准备
  • CW32F030开发板
  • I2C外设(如EEPROM、温度传感器等)
  • 若干杜邦线

2. 开发环境
  • Keil MDK5
  • CW32F030库文件和相关驱动

3. I2C通信原理I2C(Inter-Integrated Circuit)是一种用于短距离通信的串行总线,由飞利浦公司发明。它通过SDA(数据线)和SCL(时钟线)两根线进行数据传输,支持多个主从设备的通信。
I2C的主要特点:
  • 双向通信:同一条数据线可用于发送和接收数据。
  • 多主多从架构:支持多个主设备和从设备。
  • 简单的硬件设计:只需要两根信号线,节省了引脚资源。

4. I2C通信配置在CW32F030中,通过配置I2C控制寄存器来实现对I2C外设的控制,主要包括以下步骤:
  • 初始化I2C模块:配置I2C时钟、地址模式等参数。
  • 开始通信:生成I2C起始信号。
  • 发送数据:将数据写入I2C数据寄存器。
  • 停止通信:发送停止信号,结束数据传输。

5. 实例代码:I2C读写EEPROM下面的代码展示了如何使用CW32F030 MCU通过I2C接口与EEPROM进行通信,完成数据的读写操作。
  1. #include "cw32f030_i2c.h"  // 包含I2C驱动库

  2. #define EEPROM_ADDRESS 0x50  // EEPROM设备地址
  3. #define I2C_SPEED 100000     // I2C速度:100kHz

  4. // 初始化I2C
  5. void I2C_Init(void) {
  6.     I2C_InitTypeDef I2C_InitStruct;
  7.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);  // 使能I2C时钟
  8.     I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED;            // 设置I2C速度
  9.     I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;               // 设置为I2C模式
  10.     I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;       // 设置占空比
  11.     I2C_InitStruct.I2C_OwnAddress1 = 0x00;                // 主设备地址
  12.     I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;              // 使能应答
  13.     I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  // 7位地址
  14.     I2C_Init(I2C1, &I2C_InitStruct);                      // 初始化I2C
  15.     I2C_Cmd(I2C1, ENABLE);                                // 启用I2C
  16. }

  17. // I2C写入数据
  18. void I2C_WriteByte(uint8_t devAddr, uint8_t memAddr, uint8_t data) {
  19.     I2C_GenerateSTART(I2C1, ENABLE);                     // 生成起始信号
  20.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始条件
  21.     I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Transmitter); // 发送设备地址
  22.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  // 确认从机地址应答
  23.     I2C_SendData(I2C1, memAddr);                         // 发送EEPROM内存地址
  24.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 确认内存地址应答
  25.     I2C_SendData(I2C1, data);                            // 发送数据
  26.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 确认数据发送
  27.     I2C_GenerateSTOP(I2C1, ENABLE);                      // 生成停止信号
  28. }

  29. // I2C读取数据
  30. uint8_t I2C_ReadByte(uint8_t devAddr, uint8_t memAddr) {
  31.     uint8_t data;
  32.     I2C_GenerateSTART(I2C1, ENABLE);                     // 生成起始信号
  33.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始条件
  34.     I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Transmitter); // 发送设备地址
  35.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  // 确认从机地址应答
  36.     I2C_SendData(I2C1, memAddr);                         // 发送EEPROM内存地址
  37.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));  // 确认内存地址应答
  38.     I2C_GenerateSTART(I2C1, ENABLE);                     // 重新生成起始信号
  39.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));  // 等待起始条件
  40.     I2C_Send7bitAddress(I2C1, devAddr, I2C_Direction_Receiver);    // 发送设备地址,设置为接收模式
  41.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));  // 确认应答
  42.     data = I2C_ReceiveData(I2C1);                        // 接收数据
  43.     I2C_GenerateSTOP(I2C1, ENABLE);                      // 生成停止信号
  44.     return data;
  45. }

  46. // 主函数
  47. int main(void) {
  48.     uint8_t readData;

  49.     I2C_Init();  // 初始化I2C
  50.     I2C_WriteByte(EEPROM_ADDRESS, 0x00, 0x5A);  // 向EEPROM写入数据
  51.     readData = I2C_ReadByte(EEPROM_ADDRESS, 0x00);  // 从EEPROM读取数据
  52.    
  53.     while (1) {
  54.         // 循环读取数据或进行其他操作
  55.     }
  56. }

6. 代码解析
  • I2C_Init函数初始化I2C外设,配置时钟、模式和地址,并启用I2C。
  • I2C_WriteByte函数用于向EEPROM的特定地址写入数据。通过I2C起始信号开始通信,发送设备地址、内存地址以及数据,最后生成停止信号。
  • I2C_ReadByte函数用于从EEPROM的特定地址读取数据,过程类似于写入数据,但设置为接收模式,并读取数据后生成停止信号。
  • 主函数调用I2C的初始化函数,并演示了向EEPROM写入和读取数据的过程。

7. 实际应用I2C通信常用于读取传感器数据、存储器的读写等场景。在CW32F030中,I2C控制器具有良好的兼容性和稳定性,能够轻松与市面上的I2C设备进行通信。通过本示例代码,开发者可以快速上手使用CW32F030的I2C功能,完成与外设的连接和数据交互。

8. 常见问题
  • 波特率设置错误:不同I2C设备对波特率有要求,通常使用100kHz或400kHz。
  • 引脚配置错误:I2C的SDA和SCL引脚需要正确连接,注意上拉电阻的配置。
  • 从设备未应答:可能是设备地址错误或设备未上电,需检查设备的连接情况。

9. 结论通过本篇文章的讲解与代码示例,大家可以轻松实现CW32F030 MCU的I2C通信功能。I2C作为嵌入式系统中重要的通信接口,广泛应用于与外部传感器、存储器等设备的连接与数据交换。掌握I2C的使用不仅有助于提升开发效率,也为解决更多复杂的系统问题提供了基础。


公羊子丹 发表于 2024-10-10 08:23 | 显示全部楼层
这个I2C代码太实用了,终于搞明白了和EEPROM通信!
周半梅 发表于 2024-10-10 08:23 | 显示全部楼层
正好手上有个CW32F030的板子,按照这个例子调试了一下,成功了!
帛灿灿 发表于 2024-10-10 08:23 | 显示全部楼层
请问有没有写大容量EEPROM的例子?
童雨竹 发表于 2024-10-10 08:24 | 显示全部楼层
哇!I2C原来这么简单,以前一直以为很复杂。
Wordsworth 发表于 2024-10-10 08:24 | 显示全部楼层
这个EEPROM写读的代码很棒,能不能分享一个用I2C读取传感器数据的?
万图 发表于 2024-10-10 08:24 | 显示全部楼层
大佬,这个波特率调成400kHz怎么改?100kHz好像有点慢。
Bblythe 发表于 2024-10-10 08:24 | 显示全部楼层
我之前I2C总是读不出数据,看了这个才发现是地址搞错了。
Pulitzer 发表于 2024-10-10 08:25 | 显示全部楼层
代码写得太好了,刚好用来读写外接存储器。
Uriah 发表于 2024-10-10 08:25 | 显示全部楼层
有没有人知道怎么用这个MCU连接OLED显示屏的?
CW32TechSupport 发表于 2024-10-10 10:00 | 显示全部楼层
Uriah 发表于 2024-10-10 08:25
有没有人知道怎么用这个MCU连接OLED显示屏的?

请参考如下链接:
https://bbs.21ic.com/icview-3244752-1-1.html
【CW32F030CxTx StartKit测评】3.硬件I2C驱动OLED
szt1993 发表于 2024-10-12 10:38 | 显示全部楼层
非常不错的IIC案例分享
szt1993 发表于 2024-10-12 10:40 | 显示全部楼层
CW32TechSupport 发表于 2024-10-10 10:00
请参考如下链接:
https://bbs.21ic.com/icview-3244752-1-1.html
【CW32F030CxTx StartKit测评】3.硬件I ...

感谢分享,学习一下
星辰大海不退缩 发表于 2024-10-12 11:19 | 显示全部楼层
非常好的案例研究一下
reille 发表于 2025-8-5 18:19 | 显示全部楼层
官方SDK的I2C驱动接口写的真垃圾
1. 看下发送数据的接口,死循环没有超时机制: while (0 == I2C_GetIrq(I2Cx)){;}
2. 从机地址,居然定义在SDK里面
  1. /**
  2. ******************************************************************************
  3. * [url=home.php?mod=space&uid=247401]@brief[/url]  主机发送函数,适用MCU之间进行主从通信
  4. *
  5. * @param I2Cx           : I2C1  I2C2
  6. * @param pu8Data        : 发送数据存放地址
  7. * @param u32Len         : 发送数据长度
  8. *
  9. ******************************************************************************/
  10. void I2C_MasterSendDataToSlave(I2C_TypeDef *I2Cx, uint8_t *pu8Data, uint32_t u32Len)
  11. {
  12.     uint8_t u8i = 0;
  13.     uint8_t u8State;
  14.    
  15.     I2C_ClearIrq(I2Cx);
  16.     I2C_GenerateSTART(I2Cx, ENABLE);
  17.    
  18.     while (1)
  19.     {
  20.      
  21.         while (0 == I2C_GetIrq(I2Cx))
  22.         {;}
  23.         u8State = I2C_GetState(I2Cx);
  24.         
  25.         switch (u8State)
  26.         {
  27.             case 0x08:   //发送完START信号
  28.             case 0x10:   //已发送重复起始信号
  29.                 I2C_GenerateSTART(I2Cx, DISABLE);
  30.                 I2C_Send7bitAddress(I2Cx, I2C_SLAVEADDRESS, 0X00); //从设备地址+W发送
  31.                 break;
  32.             case 0x18:   //发送完SLA+W信号
  33.                 I2C_SendData(I2Cx, pu8Data[u8i++]);
  34.                 break;            
  35.             case 0x28:   //发送完1字节数据
  36.                 if (u8i >= u32Len)
  37.                 {
  38.                     I2C_GenerateSTOP(I2Cx, ENABLE);
  39.                     I2C_ClearIrq(I2Cx);
  40.                     return;                    
  41.                 }
  42.                 I2C_SendData(I2Cx, pu8Data[u8i++]);               
  43.                 break;
  44.             case 0x20:   //发送完SLA+W后从机返回NACK
  45.             case 0x38:   //主机在发送 SLA+W 阶段或者发送数据阶段丢失仲裁  或者  主机在发送 SLA+R 阶段或者回应 NACK 阶段丢失仲裁
  46.             case 0x30:   //发送完一个数据字节后从机返回NACK               
  47.             default:
  48.                 I2C_GenerateSTOP(I2Cx, ENABLE);
  49.                 I2C_ClearIrq(I2Cx);
  50.                 return;
  51.         }        
  52.         I2C_ClearIrq(I2Cx);        
  53.     }
  54. }
迷雾隐者 发表于 2025-8-6 15:01 | 显示全部楼层
这篇文章详细介绍了CW32F030 MCU的I2C通信原理和应用,对于我们这些嵌入式开发者来说非常有帮助。
治愈糖果屋 发表于 2025-8-8 21:23 | 显示全部楼层
这篇文章详细介绍了如何使用CW32F030 MCU实现I2C通信,对于我们这些嵌入式开发者来说非常有帮助。代码示例也很清晰,可以直接应用到项目中。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

159

主题

5916

帖子

0

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