找回密码
 立即注册
查看: 63|回复: 6

硬件I2C改软件I2C,有没有佬帮孩子看看

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:181
  • 最近打卡:2025-05-01 00:59:43
已绑定手机

2

主题

10

回帖

645

积分

高级会员

积分
645
发表于 2025-4-22 12:04:16 | 显示全部楼层 |阅读模式
原.txt (1.9 KB, 下载次数: 2)
改.txt (2.61 KB, 下载次数: 4)
上面这个文件的代码用stc32f芯片是可以用的
下面这个文件是自己改写软件i2c的,好像有点问题
有没有佬帮我看看,是哪里出问题了



回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-22 12:08:00 | 显示全部楼层
在嵌入式系统中,I2C通信协议因其简单性和高效性而被广泛应用。硬件I2C和软件I2C是两种常见的实现方式。硬件I2C依赖于芯片内部的I2C控制器,而软件I2C则通过GPIO引脚模拟I2C协议。本文将针对您提供的代码,分析硬件I2C改软件I2C过程中可能出现的问题,并提供解决方案。

1. 硬件I2C与软件I2C的区别

硬件I2C:
依赖于芯片内部的I2C控制器,具有较高的通信速率和稳定性。
配置简单,通常只需设置相关寄存器即可。
占用较少的CPU资源。

软件I2C:
通过GPIO引脚模拟I2C协议,灵活性高,适用于没有硬件I2C控制器的芯片。
需要手动控制时钟(SCL)和数据(SDA)线的电平变化。
占用较多的CPU资源,通信速率较低。

2. 代码分析

2.1 硬件I2C代码

您提供的硬件I2C代码在STC32F芯片上可以正常运行,说明硬件配置和通信逻辑是正确的。以下是硬件I2C代码的关键部分:
  1. c
  2. void I2CInit() {
  3.     // 初始化I2C控制器
  4.     I2CCR1 = 0x00;
  5.     I2CCR2 = 0x00;
  6.     I2CFREQR = 0x01;
  7.     I2COARL = 0x00;
  8.     I2COARH = 0x00;
  9.     I2CCCRL = 0x0A;
  10.     I2CCCRH = 0x00;
  11.     I2CTRISER = 0x03;
  12.     I2CCR1 |= 0x01;
  13. }
  14. void I2CWrite(uint8t addr, uint8t data) {
  15.     // 发送起始条件
  16.     I2CCR2 |= 0x01;
  17.     while (!(I2CSR1 & 0x01));
  18.     // 发送设备地址
  19.     I2CDR = addr;
  20.     while (!(I2CSR1 & 0x02));
  21.     // 发送数据
  22.     I2CDR = data;
  23.     while (!(I2CSR1 & 0x04));
  24.     // 发送停止条件
  25.     I2CCR2 |= 0x02;
  26. }
复制代码

2.2 软件I2C代码

您改写的软件I2C代码可能存在以下问题:
  1. c
  2. void I2CInit() {
  3.     // 初始化GPIO引脚为输出模式
  4.     GPIOInitTypeDef GPIOInitStruct;
  5.     GPIOInitStruct.Pin = GPIOPIN6 | GPIOPIN7;
  6.     GPIOInitStruct.Mode = GPIOMODEOUTPUTPP;
  7.     GPIOInitStruct.Pull = GPIONOPULL;
  8.     GPIOInitStruct.Speed = GPIOSPEEDFREQLOW;
  9.     HALGPIOInit(GPIOB, &GPIOInitStruct);
  10. }
  11. void I2CStart() {
  12.     // 发送起始条件
  13.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  14.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINSET);
  15.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  16.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINRESET);
  17. }
  18. void I2CWrite(uint8t addr, uint8t data) {
  19.     // 发送设备地址
  20.     for (int i = 0; i < 8; i++) {
  21.         HALGPIOWritePin(GPIOB, GPIOPIN7, (addr & (0x80 >> i)) ? GPIOPINSET : GPIOPINRESET);
  22.         HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  23.         HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  24.     }
  25.     // 发送数据
  26.     for (int i = 0; i < 8; i++) {
  27.         HALGPIOWritePin(GPIOB, GPIOPIN7, (data & (0x80 >> i)) ? GPIOPINSET : GPIOPINRESET);
  28.         HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  29.         HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  30.     }
  31. }
复制代码

3. 问题分析

3.1 起始条件

在硬件I2C中,起始条件由I2C控制器自动生成。而在软件I2C中,需要手动控制SCL和SDA线的电平变化。您代码中的起始条件可能存在问题:
  1. c
  2. void I2CStart() {
  3.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  4.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINSET);
  5.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  6.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINRESET);
  7. }
复制代码

正确的起始条件应该是:
1. SDA线从高电平变为低电平。
2. SCL线保持高电平。

因此,起始条件应修改为:
  1. c
  2. void I2CStart() {
  3.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINSET);
  4.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  5.     HALGPIOWritePin(GPIOB, GPIOPIN7, GPIOPINRESET);
  6.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  7. }
复制代码

3.2 数据发送

在硬件I2C中,数据发送由I2C控制器自动完成。而在软件I2C中,需要手动控制SCL和SDA线的电平变化。您代码中的数据发送部分可能存在问题:
  1. c
  2. for (int i = 0; i < 8; i++) {
  3.     HALGPIOWritePin(GPIOB, GPIOPIN7, (addr & (0x80 >> i)) ? GPIOPINSET : GPIOPINRESET);
  4.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  5.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  6. }
复制代码

正确的数据发送流程应该是:
1. SCL线保持低电平。
2. SDA线根据数据位设置电平。
3. SCL线从低电平变为高电平,再变为低电平。

因此,数据发送应修改为:
  1. c
  2. for (int i = 0; i < 8; i++) {
  3.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  4.     HALGPIOWritePin(GPIOB, GPIOPIN7, (addr & (0x80 >> i)) ? GPIOPINSET : GPIOPINRESET);
  5.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINSET);
  6.     HALGPIOWritePin(GPIOB, GPIOPIN6, GPIOPINRESET);
  7. }
复制代码

4. 总结

在将硬件I2C改为软件I2C时,需要注意以下几点:
1. 起始条件和停止条件的正确实现。
2. 数据发送时SCL和SDA线的电平变化顺序。
3. 确保GPIO引脚的初始化和配置正确。

通过以上分析和修改,您的软件I2C代码应该能够正常运行。如果问题仍然存在,建议使用逻辑分析仪或示波器检查SCL和SDA线的波形,进一步排查问题。

希望本文对您有所帮助,祝您顺利解决问题!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-22 12:55:10 | 显示全部楼层
软件I2C可以参考AI8051U实验箱例程74:
https://www.stcaimcu.com/data/download/DemoCode/AI8051U-DEMO-CODE-V1.2.zip


截图202504221254129930.jpg

  1. void        AIC23_Delay(void)
  2. {
  3.         u16        dly;
  4.         dly = 10;                //取1对应SCL H为0.5us,L为1.5us,读写仍正常.为了可靠,取8
  5.         while(--dly)        ;
  6. }
  7. /****************************/
  8. void AIC23_Start(void)               //start the I2C, SDA High-to-low when SCL is high
  9. {
  10.         P_AIC23_SDA = 1;        //SDA = 1;
  11.         AIC23_Delay();
  12.         P_AIC23_SCL = 1;        //SCL = 1;
  13.         AIC23_Delay();
  14.         AIC23_Delay();
  15.         AIC23_Delay();
  16.         AIC23_Delay();
  17.         P_AIC23_SDA = 0;        //SDA = 0;
  18.         AIC23_Delay();
  19.         AIC23_Delay();
  20.         AIC23_Delay();
  21.         P_AIC23_SCL = 0;        //SCL = 0;
  22.         AIC23_Delay();
  23. }
  24. void AIC23_Stop(void)                                        //STOP the I2C, SDA Low-to-high when SCL is high
  25. {
  26.         P_AIC23_SCL = 0;        //SCL = 0;
  27.         AIC23_Delay();
  28.         P_AIC23_SDA = 0;        //SDA = 0;
  29.         AIC23_Delay();
  30.         P_AIC23_SCL = 1;        //SCL = 1;
  31.         AIC23_Delay();
  32.         AIC23_Delay();
  33.         AIC23_Delay();
  34.         P_AIC23_SDA = 1;        //SDA = 1;
  35.         AIC23_Delay();
  36. }
  37. u8 AIC23_Check_ACK(void)         //Check ACK, If status=0: right, if status=1:  error
  38. {
  39.         u8        status;
  40.         P_AIC23_SDA = 1;        //SDA = 1;
  41.         AIC23_Delay();
  42.         P_AIC23_SCL = 1;        //SCL = 1;
  43.         AIC23_Delay();
  44.         status = 0;
  45.         if(P_AIC23_SDA)        status = 1;
  46.         P_AIC23_SCL = 0;        //SCL = 0;
  47.         AIC23_Delay();
  48.         return        status;
  49. }
复制代码



DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:520
  • 最近打卡:2025-05-01 08:06:21

109

主题

1897

回帖

5204

积分

论坛元老

积分
5204
发表于 2025-4-22 13:03:30 | 显示全部楼层
不单STC官方的例程很多,网上的I2C例程也很多
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2025-4-22 13:09:41 | 显示全部楼层
看起来没有大问题,注意开始停止要适当多延时些,IIC总线协议规范,看一下从机应答是否正常
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-22 13:12:01 | 显示全部楼层
拿逻辑分析仪,正常和异常的波形一抓,一对比,就知道错在哪了
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:229
  • 最近打卡:2025-05-01 13:30:16
已绑定手机

3

主题

45

回帖

682

积分

高级会员

积分
682
发表于 2025-4-22 13:14:54 | 显示全部楼层
上逻辑 分析仪看看数据喽
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 20:55 , Processed in 0.145014 second(s), 90 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表