时序:
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
/* 每一个IIC设备必须有一个地址 一共8位 其中前7位根硬件有关 最后一位表示读写位 为了防止IIC地址冲突,设备端不会IIC地址写死 预留几位,可以根据电路改变地址 A0 A1 A2 接低端 1010000 R/W 存储设备 24c02 字符类型存储芯片 256个字节 0~255 */ //gpio模拟IIC //所谓GPIO模拟总线,用GPIO的高低电平模拟总线通信的时序 //总线 设备分离的思想 //myiic.c 只实现IIC 协议的部分 //初始化¯IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIO //GPIOB8,B9初始化设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 IIC_SCL=1; //空闲状态,空闲的时候要拉高 IIC_SDA=1; } //产生IIC起始信号 //IIC_Start() //IIC_Send_Byte(0x5a) //IIC_Wait_Ack() //等待应答不处理 //IIC_Stop() //iic clk(时钟线) pb8 sda(数据线) PB9 //24c02 硬件手册中 IIC 时钟高电平 最低0.6us //低电平 最低 1.2us void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; delay_us(2); IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(2); IIC_SCL=0;//钳住IIC总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(2); IIC_SCL=1; delay_us(1); IIC_SDA=1;//发送IIC总线结束信号 delay_us(2); } //等待应答信号到到 //返回值:1,接收应答失败 // 0,接收到应答成功 u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 delay_us(1); IIC_SCL=1; delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0;//ʱÖÓÊä³ö0 return 0; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //IIC发送一个字节 //返回从机有无应答 //1有应答 //0无应答 //0X5A 01011010 void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); //主机发送 输出模式 IIC_SCL=0;//拉低时钟开始数据传输 for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7; //获取最高位,赋值给SDA数据线 txd<<=1; delay_us(1); // IIC_SCL=1; delay_us(1); IIC_SCL=0; delay_us(1); } } //读1个字节,ack=1时, 发送ACK, ack=0,发送nACK u8 IIC_Read_Byte(unsigned char ack) {//1010 unsigned char i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; }