找回密码
 立即注册
查看: 425|回复: 10

请问在AI8G1K08中,主频是6M时,传输I2C一直会卡着

[复制链接]

6

主题

26

回帖

137

积分

注册会员

积分
137
发表于 2024-11-21 13:40:11 | 显示全部楼层 |阅读模式
本帖最后由 DebugLab 于 2024-11-21 13:50 编辑

我使用软件I2C可以,但是查硬件I2C一直没找到问题,这里咨询一下,谢谢大家


按顺序核心代码如下:
  1.     P3PU = 0x0d;     // P30(RxD),P32(SCL),P33(SDA)上拉
  2.     P3M0 = 0x0f;     // 设置P30,P31(TxD)准双向,P32,P33开漏输出
  3.     P3M1 = 0x03;     // 设置P30,P31(TxD)准双向,P32,P33开漏输出
复制代码
下面是我抄的官方库并进行函数名修改,其他什么也没动:
  1. uint8_t i2cGetMsBusyStatus(void) {
  2.     return (I2CMSST & 0x80);
  3. }
  4. void i2cWait() {
  5.     while (!(I2CMSST & 0x40));
  6.     I2CMSST &= ~0x40;
  7. }
  8. void i2cStart() {
  9.     I2CMSCR = 0x01;  // 发送START命令
  10.     i2cWait();
  11. }
  12. void i2cSendData(char dat) {
  13.     I2CTXD = dat;    // 写数据到数据缓冲区
  14.     I2CMSCR = 0x02;  // 发送SEND命令
  15.     i2cWait();
  16. }
  17. void i2cRecvACK() {
  18.     I2CMSCR = 0x03;  // 发送读ACK命令
  19.     i2cWait();
  20. }
  21. char i2cRecvData() {
  22.     I2CMSCR = 0x04;  // 发送RECV命令
  23.     i2cWait();
  24.     return I2CRXD;
  25. }
  26. void i2cSendACK() {
  27.     I2CMSST = 0x00;  // 设置ACK信号
  28.     I2CMSCR = 0x05;  // 发送ACK命令
  29.     i2cWait();
  30. }
  31. void i2cSendNAK() {
  32.     I2CMSST = 0x01;  // 设置NAK信号
  33.     I2CMSCR = 0x05;  // 发送ACK命令
  34.     i2cWait();
  35. }
  36. void i2cStop() {
  37.     I2CMSCR = 0x06;  // 发送STOP命令
  38.     i2cWait();
  39. }
  40. void i2cSendCmdData(uint8_t cmd, uint8_t dat) {
  41.     I2CTXD = dat;   // 写数据到数据缓冲区
  42.     I2CMSCR = cmd;  // 设置命令
  43.     i2cWait();
  44. }
  45. void i2cWriteNbyte(uint8_t dev_addr, uint8_t mem_addr, uint8_t *p, uint8_t number) {
  46.     i2cStart();             // 发送起始命令
  47.     i2cSendData(dev_addr);  // 发送设备地址+写命令
  48.     i2cRecvACK();
  49.     i2cSendData(mem_addr);  // 发送存储地址
  50.     i2cRecvACK();
  51.     do {
  52.         i2cSendData(*p++);
  53.         i2cRecvACK();
  54.     } while (--number);
  55.     i2cStop();  // 发送停止命令
  56. }
  57. void i2cReadNbyte(uint8_t dev_addr, uint8_t mem_addr, uint8_t *p, uint8_t number) {
  58.     i2cStart();             // 发送起始命令
  59.     i2cSendData(dev_addr);  // 发送设备地址+写命令
  60.     i2cRecvACK();
  61.     i2cSendData(mem_addr);  // 发送存储地址
  62.     i2cRecvACK();
  63.     i2cStart();                 // 发送起始命令
  64.     i2cSendData(dev_addr | 1);  // 发送设备地址+读命令
  65.     i2cRecvACK();
  66.     do {
  67.         *p = i2cRecvData();
  68.         p++;
  69.         if (number != 1) i2cSendACK();  // send ACK
  70.     } while (--number);
  71.     i2cSendNAK();  // send no ACK
  72.     i2cStop();     // 发送停止命令
  73. }
复制代码
之后我在初始化的基础上调用了i2cReadNbyte或i2cWriteNbyte会导致系统卡死,不知道什么原因。


回复

使用道具 举报 送花

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

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-11-21 13:51:10 | 显示全部楼层
EAXFR呢
DebugLab
回复

使用道具 举报 送花

6

主题

26

回帖

137

积分

注册会员

积分
137
发表于 2024-11-21 14:56:03 | 显示全部楼层
我现在增加了这个寄存器,发现依然有问题:
    P_SW2 |= 0x80;  // 开启访问xsfr扩展寄存器
    /* 配置GPIO初始化 */
    P3PU = 0x0d;  // P30(RxD),P32(SCL),P33(SDA)上拉
    P3M0 = 0x0f;  // 设置P30,P31(TxD)准双向,P32,P33开漏输出
    P3M1 = 0x03;  // 设置P30,P31(TxD)准双向,P32,P33开漏输出

    P_SW2 |= 0x30;  // I2C: I2CSCL(P3.2), I2CSDA(P3.3)
    I2CCFG |= 0x40; /* 1: 设为主机        */
    I2CMSST = 0x00; /* 清除I2C主机状态寄存器 */
    /* 在使用6M主频时,如果该Speed设为2时,速率为375K频率,无法为400K频率 */
    I2CCFG = (I2CCFG & ~0x3f) | (2 & 0x3f);
    I2CMSAUX &= ~0x01;  // 禁止自动发送
    I2CMSCR &= ~0x80;   // 关闭中断模式
    I2CCFG |= 0x80;     // 使能I2C功能
这样初始化依然会死机。
回复 支持 反对

使用道具 举报 送花

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

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-11-21 15:14:12 | 显示全部楼层

测试通过的程序:
Ai8G1K08A硬件I2C-OLED-12832-SSD1316.zip (10.83 KB, 下载次数: 44)

点评

下载时设置时钟为11.0592M,硬件I2C超频到921.6K,可按你需要修改  详情 回复 发表于 2024-11-21 15:16
DebugLab
回复 支持 反对

使用道具 举报 送花

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

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-11-21 15:16:27 | 显示全部楼层
Debu*** 发表于 2024-11-21 15:14
测试通过的程序:

下载时设置时钟为11.0592M,硬件I2C超频到921.6K,可按你需要修改
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:238
  • 最近打卡:2025-05-01 13:11:43

22

主题

283

回帖

901

积分

高级会员

积分
901
发表于 2024-11-21 15:17:42 来自手机 | 显示全部楼层
wsr2580 发表于 2024-11-21 14:56
我现在增加了这个寄存器,发现依然有问题:
    P_SW2 |= 0x80;  // 开启访问xsfr扩展寄存器
    /* 配置GP ...


/ 8
IMG_20241121_151601.jpg
REMOVEUNUSED
回复 支持 反对

使用道具 举报 送花

6

主题

26

回帖

137

积分

注册会员

积分
137
发表于 2024-11-21 20:43:30 | 显示全部楼层

您好,我按您推荐的设置,现在不会死机了,但发现居然会影响其他GPIO的中断,感觉到很奇怪。
我把核心的代码给您看看,您参考一下:
    // 开启访问xsfr扩展寄存器
    P_SW2 |= 0x80;
    /* 配置GPIO初始化 */
    P3PU = 0x0d;  // P30(RxD),P32(SCL),P33(SDA)上拉
    /* 设置P30,P31(TxD)准双向,P32,P33开漏输出,其余高阻 */
    P3M0 = 0x0c;  // 设置P30,P31(TxD)准双向,P32,P33开漏输出
    P3M1 = 0xfc;  // 设置P30,P31(TxD)准双向,P32,P33开漏输出
    P5PU = 0x20;  // P55(KEY)上拉


    P_SW2 |= 0x30;  // I2C: I2CSCL(P3.2), I2CSDA(P3.3)
    I2CCFG |= 0x40; /* 1: 设为主机        */
    I2CMSST = 0x00; /* 清除I2C主机状态寄存器 */
    /* 在使用6M主频时,如果该Speed设为8时,速率为频率;无法为400K频率 */
    I2CCFG = (I2CCFG & ~0x3f) | (8 & 0x3f);
    I2CMSAUX &= ~0x01;  // 禁止自动发送
    I2CMSCR &= ~0x80;   // 关闭中断模式
    I2CCFG |= 0x80;     // 使能I2C功能



下面是具体的API程序:
uint8_t i2cGetMsBusyStatus(void) {
    return (I2CMSST & 0x80);
}

void i2cWait() {
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

void i2cStart() {
    I2CMSCR = 0x01;  // 发送START命令
    i2cWait();
}

void i2cSendData(char dat) {
    I2CTXD = dat;    // 写数据到数据缓冲区
    I2CMSCR = 0x02;  // 发送SEND命令
    i2cWait();
}

void i2cRecvACK() {
    I2CMSCR = 0x03;  // 发送读ACK命令
    i2cWait();
}

char i2cRecvData() {
    I2CMSCR = 0x04;  // 发送RECV命令
    i2cWait();
    return I2CRXD;
}

void i2cSendACK() {
    I2CMSST = 0x00;  // 设置ACK信号
    I2CMSCR = 0x05;  // 发送ACK命令
    i2cWait();
}

void i2cSendNAK() {
    I2CMSST = 0x01;  // 设置NAK信号
    I2CMSCR = 0x05;  // 发送ACK命令
    i2cWait();
}

void i2cStop() {
    I2CMSCR = 0x06;  // 发送STOP命令
    i2cWait();
}

void i2cSendCmdData(uint8_t cmd, uint8_t dat) {
    I2CTXD = dat;   // 写数据到数据缓冲区
    I2CMSCR = cmd;  // 设置命令
    i2cWait();
}

void i2cWriteNbyte(uint8_t dev_addr, uint8_t mem_addr, uint8_t *p, uint8_t number) {
    i2cStart();             // 发送起始命令
    i2cSendData(dev_addr);  // 发送设备地址+写命令
    i2cRecvACK();
    i2cSendData(mem_addr);  // 发送存储地址
    i2cRecvACK();
    do {
        i2cSendData(*p++);
        i2cRecvACK();
    } while (--number);
    i2cStop();  // 发送停止命令
}

void i2cReadNbyte(uint8_t dev_addr, uint8_t mem_addr, uint8_t *p, uint8_t number) {
    i2cStart();             // 发送起始命令
    i2cSendData(dev_addr);  // 发送设备地址+写命令
    i2cRecvACK();
    i2cSendData(mem_addr);  // 发送存储地址
    i2cRecvACK();
    i2cStart();                 // 发送起始命令
    i2cSendData(dev_addr | 1);  // 发送设备地址+读命令
    i2cRecvACK();
    do {
        *p = i2cRecvData();
        p++;
        if (number != 1) i2cSendACK();  // send ACK
    } while (--number);
    i2cSendNAK();  // send no ACK
    i2cStop();     // 发送停止命令
}
回复 支持 反对

使用道具 举报 送花

6

主题

26

回帖

137

积分

注册会员

积分
137
发表于 2024-11-21 20:46:41 | 显示全部楼层
Debu*** 发表于 2024-11-21 15:14
测试通过的程序:

您这个使用的是中断模式,我这里是想要轮询模式,不过我先烧录您的功能试试,谢谢

点评

中断方式和查询方式的体验是差不多的。  详情 回复 发表于 2024-11-21 21:39
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-11-21 21:39:57 | 显示全部楼层
wsr2*** 发表于 2024-11-21 20:46
您这个使用的是中断模式,我这里是想要轮询模式,不过我先烧录您的功能试试,谢谢 ...

中断方式和查询方式的体验是差不多的。
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

6

主题

26

回帖

137

积分

注册会员

积分
137
发表于 2024-11-22 09:01:47 | 显示全部楼层
晓*** 发表于 2024-11-21 21:39
中断方式和查询方式的体验是差不多的。

您这个中断方式实测修改为6M可以,但是我不知道我的查询方式为什么和您的按理是一样的,但是却有异常
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:15 , Processed in 0.489987 second(s), 116 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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