请教关于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函数,而不用自己额外写一份。
收到,多谢反馈!
今天会有新版本发布。
I2C发送数据的方法:
先使用I2C_WriteData宏将数据写入数据缓冲区(实际语句:I2CTXD = dat;)
然后使用I2C_SendData触发发送命令(实际语句:I2CMSCR = 0x02;)
然后再使用I2C_CheckMasterFlag等待命令发送完成(实际语句:while (!(I2CMSST & 0x40));)
最后使用I2C_ClearMasterFlag清除完成标志(实际语句:I2CMSST &= ~0x40;)
后续会在生成代码中添加主要宏的使用示例代码
zhp 发表于 2025-5-19 11:51
I2C发送数据的方法:
先使用I2C_WriteData宏将数据写入数据缓冲区(实际语句:I2CTXD = dat;)
试了一下,按照这个过程用宏定义的方式写的还是没有反应,
但是把宏定义的函数都拆成实际语句之后,可以点亮屏幕{:shuai:}
期待后续版本的示例代码~~~~~~ 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();
}
大明狐 发表于 2025-5-19 16:54
ISP更新到V6.95P,寄存器问题没有了不过没看到示例代码。。。。。。
不过终于用宏定义的代码驱动OLED成功 ...
由于特殊需要,今天升级比较匆忙,
I2C示例代码还没有来得及添加,
下一个版本会添加
{:baoquan:} 大明狐 发表于 2025-5-19 16:54
ISP更新到V6.95P,寄存器问题没有了不过没看到示例代码。。。。。。
不过终于用宏定义的代码驱动OLED成功 ...
楼主,6.95Q版本的ISP软件已发布
这个版本的AiCube已添加I2C的示例代码
我使用示例代码可正常读写24C02
请您有空测试看看,望多提宝贵意见{:baoquan:} 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函数
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-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]