IO口模拟ARM系列IIC通讯

摘要

之前写过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_Start();IIC_Write1Byte();IIC_Ack();IIC_Stop();delay_us();这几个函数都是自己封装好的

 

/**************************************************************
函数名:		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<n;i++)
	{
		 IIC_Write1Byte(dat[i]);
		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<n;i++)
	{
		dat[i]=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

 

太基础的东西就不说了直接给连接:http://blog.sina.com.cn/s/blog_73006d600102wcs5.html

能力有限,有不好的地方请谅解

有疑惑的可以留言,看到后会解答!

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值