GPIO引脚 模拟 IIC(软件IIC)
IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。
IIC总线的时序图:
空闲状态
当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
起始信号与停止信号
起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;
停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。
数据有效性
IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
数据的传达
在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
以下是具体的代码
static void sda_mode(uint8_t mode)
{
stc_gpio_cfg_t GPIO_Init;
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);
GPIO_Init.enDir = mode;
GPIO_Init.enOD = GpioOdEnable;
GPIO_Init.enPu = GpioPuEnable;
GPIO_Init.enPd = GpioPdDisable;
Gpio_Init(GpioPortA,GpioPin12,&GPIO_Init);
}
void Iic_Start(void)
{
sda_mode(GPIO_Mode_OUT);
SCL=1;
SDA_H;
delay10us(1);
SDA_L;
delay10us(1);
SCL=0;
}
void Iic_Stop(void)
{
sda_mode(GPIO_Mode_OUT);
SCL=0;
SDA_L;
delay10us(1);
SCL=1;
delay10us(1);
SDA_H;
}
uint8_t Iic_Wait_Ack(void)
{
uint8_t ack = 0;
sda_mode(GPIO_Mode_IN);
SCL=0;
delay10us(1);
SCL=1;
if(SDA_IN)
{
ack = 1;
}
else
{
ack = 0;
}
delay10us(1);
SCL=0;
return ack;
}
void Iic_Send_Ack(uint8_t ack)
{
sda_mode(GPIO_Mode_OUT);
SCL=0;
if(ack == 1)
{
SDA_H;
}
if(ack == 0)
{
SDA_L;
}
delay10us(1);
SCL=1;
delay10us(1);
SCL=0;
}
void Iic_Send_Byte(uint8_t txd)
{
uint8_t i;
sda_mode(GPIO_Mode_OUT);
SCL=0;
for(i=0; i<8; i++)
{
if(txd & (1<<(7-i)))
{
SDA_H;
}
else
{
SDA_L;
}
delay10us(1);
SCL=1;
delay10us(1);
SCL=0;
}
}
uint8_t Iic_Read_Byte()
{
uint8_t i;
uint8_t date=0;
sda_mode(GPIO_Mode_IN);
for(i=0; i<8; i++)
{
SCL=1;
delay10us(1);
if(SDA_IN==1)
{
date+=1;
}
if(i!=7)
date=date << 1;
SCL=0;
delay10us(1);
}
return date;
}
void Write_Bytes(uint8_t addr, uint8_t data)
{
uint8_t ack;
Iic_Start();
Iic_Send_Byte(I2C_WADDR);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
Iic_Send_Byte(addr);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
delay10us(1);
Iic_Send_Byte(data);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
Iic_Stop();
}
void Read_Bytes(uint8_t addr, uint8_t *read_buff,uint8_t len)
{
uint8_t ack;
uint8_t i=0;
Iic_Start();
Iic_Send_Byte(I2C_WADDR);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
Iic_Send_Byte(addr);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
Iic_Start();
Iic_Send_Byte(I2C_RADDR);
ack=Iic_Wait_Ack();
if(ack == 1)
{
return ;
}
while(len--)
{
read_buff[i++]=Iic_Read_Byte();
if(len==0)
{
Iic_Send_Ack(1);
}
else
{
Iic_Send_Ack(0);
}
}
Iic_Stop();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)