wuzhengmin 发表于 2025-10-27 08:58:12

关于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应答么?



wuzhengmin 发表于 2025-10-27 09:28:55

难道以前


        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个函数完成?

wuzhengmin 发表于 2025-10-27 09:52:52

应该是我水平低,搞不懂他怎么处理:// 发送开始命令 发送器件地址(写) 发送数据地址 发送开始命令 发送器件地址(读)读数据
//头尾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吧?

wuzhengmin 发表于 2025-10-27 09:57:33



我能在def.h中找到:

typedef bit                     BOOL;

也知道是用它来代替ASK或者NASK

BOOL =0   就是ASK

BOOL =1   就是NASK

wuzhengmin 发表于 2025-10-27 10:18:48

*p = I2C_MasterReadByte(BOOL);        //第1圈P 第2圈 P 第3圈P第4圈P第5圈P第6圈P......

参数给BOOL,编译就报错

干脆不给参数:

wuzhengmin 发表于 2025-10-27 10:19:42

不知道去哪里找资料,搞懂这2个函数如何用在IIC上?

ercircle 发表于 2025-10-27 11:10:24

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交流社区

wuzhengmin 发表于 2025-10-27 13:41:25

ercircle 发表于 2025-10-27 11:10
BOOL是bit类型的别名,函数传参怎么能传类型名进去,要传实例。
接收后发NAK还是ACK查用到的从机IC手册 ...

感谢指点,我也是蒙了,真每理解,这个应答,不是我先读,或者先写才有的么?

怎么我读的时候叫我当入口参数?不睡觉都赶不上刘少奇啊!

ercircle 发表于 2025-10-27 14:40:12

wuzhengmin 发表于 2025-10-27 13:41
感谢指点,我也是蒙了,真每理解,这个应答,不是我先读,或者先写才有的么?

怎么我读的时候叫我当入口 ...

看函数逻辑,参数作用是在读后回复时决定回复NAK还是ACK行为

wuzhengmin 发表于 2025-10-27 14:47:03

ercircle 发表于 2025-10-27 14:40
看函数逻辑,参数作用是在读后回复时决定回复NAK还是ACK行为

对,我打算先定义sbitACKHF
ACKHF=0;
这样才能调用这个函数往下走,谢谢指点!
页: [1] 2 3
查看完整版本: 关于AiCube创建IIC项目的疑问?(在荣誉版主erci***耐心指导下已经解决)