wsr2580 发表于 2024-11-21 13:40:11

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

本帖最后由 DebugLab 于 2024-11-21 13:50 编辑

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


按顺序核心代码如下:
    P3PU = 0x0d;   // P30(RxD),P32(SCL),P33(SDA)上拉
    P3M0 = 0x0f;   // 设置P30,P31(TxD)准双向,P32,P33开漏输出
    P3M1 = 0x03;   // 设置P30,P31(TxD)准双向,P32,P33开漏输出下面是我抄的官方库并进行函数名修改,其他什么也没动:

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();   // 发送停止命令
}
之后我在初始化的基础上调用了i2cReadNbyte或i2cWriteNbyte会导致系统卡死,不知道什么原因。


DebugLab 发表于 2024-11-21 13:51:10

EAXFR呢

wsr2580 发表于 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功能
这样初始化依然会死机。

DebugLab 发表于 2024-11-21 15:14:12


测试通过的程序:

DebugLab 发表于 2024-11-21 15:16:27

DebugLab 发表于 2024-11-21 15:14
测试通过的程序:

下载时设置时钟为11.0592M,硬件I2C超频到921.6K,可按你需要修改

邮箱 发表于 2024-11-21 15:17:42

wsr2580 发表于 2024-11-21 14:56
我现在增加了这个寄存器,发现依然有问题:
    P_SW2 |= 0x80;// 开启访问xsfr扩展寄存器
    /* 配置GP ...

/ 8

wsr2580 发表于 2024-11-21 20:43:30

邮箱 发表于 2024-11-21 15:17
/ 8

您好,我按您推荐的设置,现在不会死机了,但发现居然会影响其他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();   // 发送停止命令
}

wsr2580 发表于 2024-11-21 20:46:41

DebugLab 发表于 2024-11-21 15:14
测试通过的程序:

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

晓飛飛 发表于 2024-11-21 21:39:57

wsr2580 发表于 2024-11-21 20:46
您这个使用的是中断模式,我这里是想要轮询模式,不过我先烧录您的功能试试,谢谢 ...

中断方式和查询方式的体验是差不多的。

wsr2580 发表于 2024-11-22 09:01:47

晓飛飛 发表于 2024-11-21 21:39
中断方式和查询方式的体验是差不多的。

您这个中断方式实测修改为6M可以,但是我不知道我的查询方式为什么和您的按理是一样的,但是却有异常
页: [1] 2
查看完整版本: 请问在AI8G1K08中,主频是6M时,传输I2C一直会卡着