大明狐 发表于 2025-5-19 11:34:11

请教关于AiCube的I2C的两个问题 | 已解决,最新修改在5楼

用AiCube创建基础工程、串口、USB、ADC 等等工程成功之后,
在尝试添加硬件I2C的程序时,遇到有两个问题。


问题一、
型号选择STC8H和STC32G,创建启用I2C的工程文件之后,在编译的时候都会报出一个错误提示:
Sources\i2c.c(37): error C202: 'I2CPSCR': undefined identifier
错误定位在设置时钟速度的地方
void I2C_Init(void)
{
    I2C_SwitchP1415();                  //选择I2C数据口: SCL(P1.5), SDA(P1.4)

    I2C_MasterMode();                   //设置I2C为主机模式
   (有问题) I2C_SetClockDivider(0);             //设置I2C为主机模式时钟

    I2C_Enable();                     //使能I2C功能

    //<<AICUBE_USER_I2C_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_I2C_INITIAL_END>>
}
查找发现,在stc8h_def.h和stc32g_def.h里的关于I2C_SetClockDivider的宏定义里,多了一个不存在的寄存器 I2CPSCR
#define I2C_SetClockDivider(n)          MODIFY_REG(I2CCFG, I2CCFG_SPEED_MSK, ((n) << 0)); \
                                              I2CPSCR = ((n) >> 6)注释掉第二行这句之后,编译就正常通过了。
如果选择AI8051U,生成的工程里同样也有这句,但是因为有这个寄存器所以不会报错。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

问题二、
I2C编译通过之后,尝试加入OLED的驱动程序。
看到stc8h_def.h里有关于硬件I2C的驱动函数的宏定义
#define I2C_Idle()                      I2C_SetMasterCommand(I2CCMD_IDLE)
#define I2C_Start()                     I2C_SetMasterCommand(I2CCMD_START)
#define I2C_SendData()                  I2C_SetMasterCommand(I2CCMD_SENDDATA)
#define I2C_RecvACK()                   I2C_SetMasterCommand(I2CCMD_RECVACK)
#define I2C_RecvData()                  I2C_SetMasterCommand(I2CCMD_RECVDATA)
#define I2C_SendACK()                   I2C_SetMasterCommand(I2CCMD_SENDACK)
#define I2C_Stop()                      I2C_SetMasterCommand(I2CCMD_STOP)
#define I2C_StartSendDataRecvACK()      I2C_SetMasterCommand(I2CCMD_START_SENDDATA_RECVACK)
#define I2C_SendDataRecvACK()         I2C_SetMasterCommand(I2CCMD_SENDDATA_RECVACK)
#define I2C_RecvDataSendACK()         I2C_SetMasterCommand(I2CCMD_RECVDATA_SENDACK)
#define I2C_RecvDataSendNAK()         I2C_SetMasterCommand(I2CCMD_RECVDATA_SENDNA)
但是不知道怎么使用,除了初始化函数I2C_Init() 之外,其它函数直接调用都没有效果,
比如发送数据的SendData没有关于数据缓冲区的I2CTXD的赋值部分,手动添加上也没效果。

而使用数据手册和试验箱例程里的硬件I2C的函数
void Wait()
{
while (!(I2CMSST & 0x40));
I2CMSST &= ~0x40; //清中断标志
}

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

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

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

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

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

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

void Stop()
{
I2CMSCR = 0x06; //I发送STOP命令
Wait();
}

则可以顺利点亮OLED屏幕。

因为之前没用过I2C库,所以不知道是不是我的操作有什么问题。
以及AiCube生成的工程里有没有直接可以用的I2C函数,而不用自己额外写一份。


zhp 发表于 2025-5-19 11:38:07

收到,多谢反馈!
今天会有新版本发布。

zhp 发表于 2025-5-19 11:51:09

I2C发送数据的方法:

先使用I2C_WriteData宏将数据写入数据缓冲区(实际语句:I2CTXD = dat;)
然后使用I2C_SendData触发发送命令(实际语句:I2CMSCR = 0x02;)
然后再使用I2C_CheckMasterFlag等待命令发送完成(实际语句:while (!(I2CMSST & 0x40));)
最后使用I2C_ClearMasterFlag清除完成标志(实际语句:I2CMSST &= ~0x40;)

后续会在生成代码中添加主要宏的使用示例代码

大明狐 发表于 2025-5-19 12:37:27

zhp 发表于 2025-5-19 11:51
I2C发送数据的方法:

先使用I2C_WriteData宏将数据写入数据缓冲区(实际语句:I2CTXD = dat;)


试了一下,按照这个过程用宏定义的方式写的还是没有反应,
但是把宏定义的函数都拆成实际语句之后,可以点亮屏幕{:shuai:}

期待后续版本的示例代码~~~~~~

大明狐 发表于 2025-5-19 16:54:10

zhp 发表于 2025-5-19 11:51
I2C发送数据的方法:

先使用I2C_WriteData宏将数据写入数据缓冲区(实际语句:I2CTXD = dat;)

ISP更新到V6.95P,寄存器问题没有了{:aini:}不过没看到示例代码。。。。。。

不过终于用宏定义的代码驱动OLED成功了{:4_183:}

因为I2C_CheckMasterFlag只是数值
所以需要写成

                while( !I2C_CheckMasterFlag() );
               

才起作用
所以在 stc8h_def.h 头文件里重新写了一个宏定义

                #define I2C_CheckMasterFlag1()         while(!READ_REG_BIT(I2CMSST, I2CMSST_MSIF_MSK))


而且不想每次都要写这么多,所以又加了一条
                #define I2C_Wait()                I2C_CheckMasterFlag1(); \
                                                        I2C_ClearMasterFlag()

这样驱动函数就可以简洁一些了

void Write_IIC_Command(unsigned char IIC_Command){
      I2C_Start();
      I2C_Wait();
      I2C_WriteData(0x78);                        //OLED从机地址0x78
      I2C_SendData();
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
      I2C_WriteData(0x00);                        //写命令指令
      I2C_SendData();
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
      I2C_WriteData(IIC_Command);      //发送命令
      I2C_SendData();
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
      I2C_Stop();
      I2C_Wait();
}



=====================================================================

另外每次需要先I2C_WriteData赋值,然后再用I2C_SendData发送,试着加了一条宏定义

                #define I2C_SendData1(d)                     I2C_WriteData(d); \
                                                                             I2C_SendData();

这样每次发送数据也只需要写一条命令了

void Write_IIC_Command(unsigned char IIC_Command){
      I2C_Start();
      I2C_Wait();
      I2C_SendData1(0x78);                        //OLED从机地址0x78
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
       I2C_SendData1(0x00);                              //写命令指令
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
      I2C_SendData1(IIC_Command);      //发送命令
      I2C_Wait();
      I2C_RecvACK();
      I2C_Wait();
      I2C_Stop();
      I2C_Wait();
}



{:4_189:}{:4_189:}{:4_189:}{:4_189:}{:4_189:}{:4_189:}{:4_189:}
不过还是觉得手册里那种封装成函数的更好用一点儿,很少几行就够了

void Write_IIC_Command(unsigned char IIC_Command){
      Start();
      SendData(0x78);                                        //OLED从机地址0x78
      RecvACK();
      SendData(0x00);                                        //写命令指令
      RecvACK();
      SendData(IIC_Command);      //发送命令
      RecvACK();
      Stop();
}




zhp 发表于 2025-5-19 20:01:21

大明狐 发表于 2025-5-19 16:54
ISP更新到V6.95P,寄存器问题没有了不过没看到示例代码。。。。。。

不过终于用宏定义的代码驱动OLED成功 ...

由于特殊需要,今天升级比较匆忙,
I2C示例代码还没有来得及添加,
下一个版本会添加
{:baoquan:}

zhp 发表于 2025-5-23 16:19:11

大明狐 发表于 2025-5-19 16:54
ISP更新到V6.95P,寄存器问题没有了不过没看到示例代码。。。。。。

不过终于用宏定义的代码驱动OLED成功 ...

楼主,6.95Q版本的ISP软件已发布
这个版本的AiCube已添加I2C的示例代码

我使用示例代码可正常读写24C02
请您有空测试看看,望多提宝贵意见{:baoquan:}

大明狐 发表于 2025-5-23 19:33:53

zhp 发表于 2025-5-23 16:19
楼主,6.95Q版本的ISP软件已发布
这个版本的AiCube已添加I2C的示例代码


收到。
下载了新版ISP V6.95Q,还没测试I2C,但是ISP的USB自动下载有个问题,
每次下载,都会停在“正在等待HID-ISP”(监控程序区选项卡里的勾勾都已经打上了)。
发现每次点下载按钮之后,“扫描串口”那一栏会从【USB-CDC, CDC】,自动变成【(COM1) 通信端口】,需要再次手动选择CDC端口才能下载。

如果手动按住P32重新上电,也不会像以前一样自动切换成【(HID1) USB-Writer 】,也需要手动选择,而且有时候还会自动变回【(COM1) 通信端口】
(V6.95P之前的版本都能正常自动下载)



============================
稍后再试一下新的那些I2C函数

大明狐 发表于 2025-5-23 22:48:50

zhp 发表于 2025-5-23 16:19
楼主,6.95Q版本的ISP软件已发布
这个版本的AiCube已添加I2C的示例代码

刚刚又重新下载了一遍V6.95Q版的ISP,发现刚才说的用USB自动下载的时候串口号乱跑的情况没有了。
试了下用i2c.c里的几个新函数替换进OLED12864的驱动程序里,完美点亮屏幕,而且更简洁了
{:huaixiao:}

void Write_IIC_Command(unsigned char IIC_Command)
{
    I2C_MasterStart();
    I2C_MasterSendByte( 0x78 );
    I2C_MasterSendByte( 0x00 );
    I2C_MasterSendByte( IIC_Command );
    I2C_MasterStop();
}

void Write_IIC_Data(unsigned char IIC_Data)
{
    I2C_MasterStart();
    I2C_MasterSendByte( 0x78 );
    I2C_MasterSendByte( 0x40 );
    I2C_MasterSendByte( IIC_Data );
    I2C_MasterStop();
}


{:4_189:}{:4_189:}{:4_189:}{:4_189:}{:4_189:}




神农鼎 发表于 2025-5-24 08:29:16

大明狐 发表于 2025-5-23 22:48
刚刚又重新下载了一遍V6.95Q版的ISP,发现刚才说的用USB自动下载的时候串口号乱跑的情况没有了。
试了下 ...
帮用 AiCube 多做些 OLED12864的演示程序给大家交流/学习
AiCube 已优先支持 STC8H8K64U / STC32G12K128 / Ai8051U

深圳国芯人工智能有限公司-工具软件






AiCube最新版发布@AIapp-ISP V6.95Q 版, 支持STC32/STC8H8K64U/Ai8051U - AiCube@AIapp-ISP 最新版本, 强大的32位8051辅助开发工具 国芯技术交流网站 - AI32位8051交流社区
页: [1]
查看完整版本: 请教关于AiCube的I2C的两个问题 | 已解决,最新修改在5楼