关于AiCube创建IIC项目的疑问?(在荣誉版主erci***耐心指导下已经解决)
前天开始USB的学习,按照老师指点,先学习AiCube那么就先试一试IIC,我创建了多文件的项目,可以顺利通过编译
但是系统生成的函数I2C.c,把我搞糊涂了
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: i2c.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-10-27) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h"
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// I2C初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_Init(void)
{
I2C_SwitchP2425(); //选择I2C数据口: SCL(P2.5), SDA(P2.4)
I2C_MasterMode(); //设置I2C为主机模式
I2C_SetClockDivider(12); //设置I2C为主机模式时钟
I2C_Enable(); //使能I2C功能
//<<AICUBE_USER_I2C_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_I2C_INITIAL_END>>
}
////////////////////////////////////////
// 主机模式等待命令完成
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_MasterWait(void)
{
while (!I2C_CheckMasterFlag()); //等待完成标志
I2C_ClearMasterFlag(); //清除完成标志
I2C_Idle(); //恢复IDLE状态
}
////////////////////////////////////////
// 主机模式发送起始信号
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_MasterStart(void)
{
I2C_Start(); //触发主机模式起始命令
I2C_MasterWait(); //等待命令完成
}
////////////////////////////////////////
// 主机模式发送停止信号
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_MasterStop(void)
{
I2C_Stop(); //触发主机模式停止命令
I2C_MasterWait(); //等待命令完成
}
////////////////////////////////////////
// 主机模式发送1字节数据
// 入口参数: dat (待发送的字节数据)
// 函数返回: 0 (接收的应答信号为ACK)
// 1 (接收的应答信号为NAK)
////////////////////////////////////////
BOOL I2C_MasterSendByte(uint8_t dat)
{
I2C_WriteData(dat); //将数据写入I2C数据寄存器
I2C_SendData(); //触发主机模式写数据命令
I2C_MasterWait(); //等待命令完成
I2C_RecvACK(); //触发主机模式接收应答命令
I2C_MasterWait(); //等待命令完成
return I2C_MasterReadACK(); //读取并返回应答信号
}
////////////////////////////////////////
// 主机模式接收1字节数据
// 入口参数: ack (待发送的应答信号)
// 函数返回: (接收的字节数据)
////////////////////////////////////////
uint8_t I2C_MasterReadByte(BOOL ack)
{
uint8_t dat;
I2C_RecvData(); //触发主机模式读数据命令
I2C_MasterWait(); //等待命令完成
dat = I2C_ReadData(); //读取接收的数据
if (!ack)
I2C_MasterSetACK(); //将ACK数据写入寄存器
else
I2C_MasterSetNAK(); //将NAK数据写入寄存器
I2C_SendACK(); //触发主机模式发送应答命令
I2C_MasterWait(); //等待命令完成
return dat; //返回接收的数据
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
就是主机模式接收1字节数据,要求入口参数是ack (待发送的应答信号)
主机读数据的时候,不是读完数据才发送ASK应答么?
难道以前
IIC_SENDBYTE(slave); //主机发送命令字。该字由 7 位的外围器件地址和 1 位读写控制位R/W组成(此时RW=0为写)
//slave 由 7 位的外围器件地址和 1 位读写控制位R/W组成(此时RW=0为写)
IIC_WAITACK();//等待从机应答ACK,结果由ask保存,为0就正确,为1就错误
这2个函数的功能,由
I2C_MasterSendByte(slave) //主机模式发送1字节数据,函数返回: 0 (接收的应答信号为ACK)
//函数返回:1 (接收的应答信号为NAK)
这1个函数完成?
应该是我水平低,搞不懂他怎么处理:// 发送开始命令 发送器件地址(写) 发送数据地址 发送开始命令 发送器件地址(读)读数据
//头尾2个器件地址(第1个最后一位写0,第2个最后一位写1),数据片内地址只发1次
void IIC_Read_NByte( u8 slave,u8 addr,u8 *p,u8 number ) //iic读取连续的几个字节
{
I2C_MasterStart(); //发送一个启动信号"S”,开始一次通信的开始
//IIC_SENDBYTE(slave); //主机发送命令字。该字由 7 位的外围器件地址和 1 位读写控制位R/W组成(此时RW=1为读)
//slave 由 7 位的外围器件地址和 1 位读写控制位R/W组成(此时RW=1为读)
//IIC_WAITACK(); //等待从机应答ACK,结果由ask保存,为0就正确,为1就错误
I2C_MasterSendByte(slave); //主机模式发送1字节数据,函数返回: 0 (接收的应答信号为ACK)
//函数返回:1 (接收的应答信号为NAK)
//IIC_SENDBYTE(addr); //要写入芯片24C02的读取数据片内地址addr
//IIC_WAITACK(); //等待从机应答ACK,结果由ask保存,为0就正确,为1就错误
I2C_MasterStart(); //发送一个启动信号"S”,开始一次通信的开始
I2C_MasterSendByte((u8)(slave+0x01)); //主器件发送器件地址(读/写选择位为"1"),主机模式发送1字节数据
//函数返回: 0 (接收的应答信号为ACK)函数返回:1 (接收的应答信号为NAK)
//IIC_START();
//IIC_SENDBYTE((u8)(slave+0x01)); //主器件发送器件地址(读/写选择位为"1")
//IIC_WAITACK(); //芯片24C02应答ACK,并随时钟送出数据
do
{
*p = I2C_MasterReadByte(BOOL ack); //第1圈P 第2圈 P 第3圈P第4圈P第5圈P第6圈P.......
p++;
if( number!=1 ) //不是最后一位
IIC_SENDACK(); //等待从机应答ACK,结果由ask保存,为0就正确,为1就错误,这句不写也OK
}
while(--number);
IIC_SENDNACK();
IIC_STOP();//主机发送停止信号“P”
}
像这里:
do
{
*p = I2C_MasterReadByte(BOOL ack); //第1圈P 第2圈 P 第3圈P第4圈P第5圈P第6圈P.......
p++;
if( number!=1 ) //不是最后一位
IIC_SENDACK(); //等待从机应答ACK,结果由ask保存,为0就正确,为1就错误,这句不写也OK
}
I2C_MasterReadByte(BOOL ack); 是读当前地址的1个字节数据,那么这个入口参数BOOL ack,我从哪里获取?
总不能直接带入0吧?
我能在def.h中找到:
typedef bit BOOL;
也知道是用它来代替ASK或者NASK
BOOL =0 就是ASK
BOOL =1 就是NASK
*p = I2C_MasterReadByte(BOOL); //第1圈P 第2圈 P 第3圈P第4圈P第5圈P第6圈P......
参数给BOOL,编译就报错
干脆不给参数:
不知道去哪里找资料,搞懂这2个函数如何用在IIC上? wuzhengmin 发表于 2025-10-27 10:18
*p = I2C_MasterReadByte(BOOL); //第1圈P 第2圈 P 第3圈P第4圈P第5圈P第6圈P......
参 ...
BOOL是bit类型的别名,函数传参怎么能传类型名进去,要传实例。
接收后发NAK还是ACK查用到的从机IC手册。
【新提醒】《8051U深度入门到32位51大型实战视频》,【免费 + 包邮 送】实验箱@Ai8051U,100万套 - 字库生成,图片取模,串口绘图,串口助手,虚拟硬件,外部串行Flash编程 国芯人工智能技术交流网站 - AI32位8051交流社区
ercircle 发表于 2025-10-27 11:10
BOOL是bit类型的别名,函数传参怎么能传类型名进去,要传实例。
接收后发NAK还是ACK查用到的从机IC手册 ...
感谢指点,我也是蒙了,真每理解,这个应答,不是我先读,或者先写才有的么?
怎么我读的时候叫我当入口参数?不睡觉都赶不上刘少奇啊! wuzhengmin 发表于 2025-10-27 13:41
感谢指点,我也是蒙了,真每理解,这个应答,不是我先读,或者先写才有的么?
怎么我读的时候叫我当入口 ...
看函数逻辑,参数作用是在读后回复时决定回复NAK还是ACK行为
ercircle 发表于 2025-10-27 14:40
看函数逻辑,参数作用是在读后回复时决定回复NAK还是ACK行为
对,我打算先定义sbitACKHF
ACKHF=0;
这样才能调用这个函数往下走,谢谢指点!