摘要
之前写过51内核系列的IO口模拟IIC通讯,最近用arm内核的mcu模拟IIC通讯,发现与51内核有些区别(arm内核不支持位寻址)
IIC的信号:开始信号(SCL保持高,拉低SDA)、应答信号(第九个时钟,SDA为低)、非应答信号(第九个时钟,SDA为低)、结束信号(SCL保持高,拉高SDA)
(非)应答信号: 有应答信号才可以进行下一步,非应答信号会结束通讯
IIC写数据设置三个信号:起始信号、从地址+写(如:addr为0x18(00011000),左移1位后为0x30(00110000),最后一位是0表示写)、寄存器
IIC读数据设置五个信号:起始信号、从地址+写、寄存器、起始信号、从地址+读(如:addr为0x18(00011000),左移1位后为0x30(00110000)与上1后为0x31,最后一位是1表示读(上个图帮助理解)
看下代码吧
一、IO宏定义
51内核定义方式:
#define IIC_SCL P04//SCL输出模式
#define IIC_SDA P03 //SDA输出模式
#define READ_SDA P03//读取应答信号SDA 输入模式
arm内核定义方式:
//IIC IO定义
#define IIC_SCL(x) GPIO_output(0, 2, x)//SCL输出模式
#define IIC_SDA(x) GPIO_output(0, 3, x) //SDA输出模式
#define READ_SDA() gpio_input(0,2)//读取应答信号SDA 输入模式
#define READ_SCL() gpio_input(0,3)//读取应答信号SDA 输入模式
//SDA线输入输出设置
#define SET_SDA_IN() GPIO_config(0,2,0)
#define SET_SDA_OUT() GPIO_config(0,2,1)
//SCL线输入输出设置
#define SET_SCL_IN() GPIO_config(0,3,0)
#define SET_SCL_OUT() GPIO_config(0,3,1)
二、写数据
/**************************************************************
函数名: IIC_SendNByte
功能: 发送Nbyte数据
输入参数: ADDR从机地址,REG寄存器地址 待发送数据dat,n数据大小
返回值: 成功写了多少个
函数类型: void
-------------------------------------------------------------*/
unsigned char IIC_WriteNByte(unsigned char addr,unsigned char reg_addr,unsigned char *dat,unsigned char n)
{
unsigned char i;
IIC_Start();//一个起始信号
addr <<= 1; //左移1位,最低位为0 表示写
IIC_Write1Byte(addr);//一个从机地址信号
IIC_Write1Byte(reg_addr);//一个寄存器地址信号
//下面可以连续写啦
for(i = 0;i
{
IIC_Write1Byte(dat
);
if(IIC_Ack())
{
IIC_Stop();
return i;
}
}
IIC_Stop();
return i;
}
硬件IIC内部有地址自增功能,所以一直读就可以了
三、读数据
/**************************************************************
函数名: IIC_ReadNByte
功能: 接收Nbyte数据
输入参数: 是否需要发送应答信号 1:需要 0:不需要
返回值: 接收到的数据
函数类型: u8
-------------------------------------------------------------*/
void IIC_ReadNByte(unsigned char addr,unsigned char reg_addr,unsigned char *dat,unsigned char n)
{
unsigned char i;
IIC_Start();//一个起始信号
addr <<= 1; //左移1位,最低位为0 表示写
IIC_Write1Byte(addr);//一个从机地址信号
IIC_Write1Byte(reg_addr);//一个寄存器地址信号
IIC_Start();//restart信号
IIC_Write1Byte(addr|1);//从机地址+读
//下面就可以读啦
for(i = 0;i
{
dat=IIC_Read1Byte();
if(i<(n-1))
IIC_SendAck();
}
IIC_NoSendAck();//发送非应答
IIC_Stop();
}
四,读和写的区别
1、写数据要接收应答或非应答信号、读数据发送应答或非应答信号
2、写数据:start、addr+w、reg; 读数据:start、addr+w、reg、start、addr+r 多了start、addr+r
摘要
之前写过51内核系列的IO口模拟IIC通讯,最近用arm内核的mcu模拟IIC通讯,发现与51内核有些区别(arm内核不支持位寻址)
IIC的信号:开始信号(SCL保持高,拉低SDA)、应答信号(第九个时钟,SDA为低)、非应答信号(第九个时钟,SDA为低)、结束信号(SCL保持高,拉高SDA)
(非)应答信号: 有应答信号才可以进行下一步,非应答信号会结束通讯
IIC写数据设置三个信号:起始信号、从地址+写(如:addr为0x18(00011000),左移1位后为0x30(00110000),最后一位是0表示写)、寄存器
IIC读数据设置五个信号:起始信号、从地址+写、寄存器、起始信号、从地址+读(如:addr为0x18(00011000),左移1位后为0x30(00110000)与上1后为0x31,最后一位是1表示读(上个图帮助理解)
看下代码吧
一、IO宏定义
51内核定义方式:
#define IIC_SCL P04//SCL输出模式
#define IIC_SDA P03 //SDA输出模式
#define READ_SDA P03//读取应答信号SDA 输入模式
arm内核定义方式:
//IIC IO定义
#define IIC_SCL(x) GPIO_output(0, 2, x)//SCL输出模式
#define IIC_SDA(x) GPIO_output(0, 3, x) //SDA输出模式
#define READ_SDA() gpio_input(0,2)//读取应答信号SDA 输入模式
#define READ_SCL() gpio_input(0,3)//读取应答信号SDA 输入模式
//SDA线输入输出设置
#define SET_SDA_IN() GPIO_config(0,2,0)
#define SET_SDA_OUT() GPIO_config(0,2,1)
//SCL线输入输出设置
#define SET_SCL_IN() GPIO_config(0,3,0)
#define SET_SCL_OUT() GPIO_config(0,3,1)
二、写数据
/**************************************************************
函数名: IIC_SendNByte
功能: 发送Nbyte数据
输入参数: ADDR从机地址,REG寄存器地址 待发送数据dat,n数据大小
返回值: 成功写了多少个
函数类型: void
-------------------------------------------------------------*/
unsigned char IIC_WriteNByte(unsigned char addr,unsigned char reg_addr,unsigned char *dat,unsigned char n)
{
unsigned char i;
IIC_Start();//一个起始信号
addr <<= 1; //左移1位,最低位为0 表示写
IIC_Write1Byte(addr);//一个从机地址信号
IIC_Write1Byte(reg_addr);//一个寄存器地址信号
//下面可以连续写啦
for(i = 0;i
{
IIC_Write1Byte(dat
);
if(IIC_Ack())
{
IIC_Stop();
return i;
}
}
IIC_Stop();
return i;
}
硬件IIC内部有地址自增功能,所以一直读就可以了
三、读数据
/**************************************************************
函数名: IIC_ReadNByte
功能: 接收Nbyte数据
输入参数: 是否需要发送应答信号 1:需要 0:不需要
返回值: 接收到的数据
函数类型: u8
-------------------------------------------------------------*/
void IIC_ReadNByte(unsigned char addr,unsigned char reg_addr,unsigned char *dat,unsigned char n)
{
unsigned char i;
IIC_Start();//一个起始信号
addr <<= 1; //左移1位,最低位为0 表示写
IIC_Write1Byte(addr);//一个从机地址信号
IIC_Write1Byte(reg_addr);//一个寄存器地址信号
IIC_Start();//restart信号
IIC_Write1Byte(addr|1);//从机地址+读
//下面就可以读啦
for(i = 0;i
{
dat=IIC_Read1Byte();
if(i<(n-1))
IIC_SendAck();
}
IIC_NoSendAck();//发送非应答
IIC_Stop();
}
四,读和写的区别
1、写数据要接收应答或非应答信号、读数据发送应答或非应答信号
2、写数据:start、addr+w、reg; 读数据:start、addr+w、reg、start、addr+r 多了start、addr+r
举报