iic双线制。一根是SCL,作为时钟同步线;一根是SDA,作为数据传输线
SDN



- #include "iic.h"
-
- #define SCL PBout(8)
-
- #define SDA_W PBout(9)
- #define SDA_R PBin(9)
-
-
- void IIC_GPIOInit(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- //使能时钟G
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
-
- //3、配置PG9
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_NOPULL;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
-
-
- static void __IIC_SDAMode( GPIOMode_TypeDef GPIO_Mode)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //使能时钟G
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
-
- //3、配置PG9
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_NOPULL;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- }
-
-
-
- //1、主机发送启动信号操作
- //启动信号:在SCL的高电平期间,SDA产生下降沿
- void IIC_Start(void)
- {
- //设置SDA引脚为输出模式
- __IIC_SDAMode(GPIO_Mode_OUT);
-
- //先保持一段时间空闲>=4us
- SCL = 1;
- SDA_W = 1;
- delay_us(5);
-
- //开始启动信号
- SDA_W = 0;//下降沿
- delay_us(5);
-
- SCL = 0;//保证启动信号后面函数能顺畅的接上
- }
-
- //2、主机发送停止信号操作
- //停止信号:在SCL的高电平期间,SDA产生上升沿
- void IIC_Stop(void)
- {
- //SDA设置为输出模式
- __IIC_SDAMode(GPIO_Mode_OUT);
-
- SDA_W = 0;
- SCL = 0;
- delay_us(5);
-
- SCL = 1;//先拉高 --- 高电平期间
- delay_us(5);
- SDA_W = 1;//产生上升沿
- }
-
-
- //3、主机给从机发送8个数据位
- void IIC_WriteByte(unsigned char WData)
- {
- //SDA设置为输出模式
- __IIC_SDAMode(GPIO_Mode_OUT);
-
- for(int i=0;i<8;i++)
- {
- SCL = 0;
- delay_us(2);
- SDA_W = (WData>>(7-i)) & 0x01;
- delay_us(3);
-
- SCL = 1;
- delay_us(5);
- }
-
- SCL = 0;
- }
-
-
- //4、主机读取从机发送过来8个数据位
- void IIC_ReadByte(unsigned char *RData)
- {
- unsigned char TemData=0;//临时存放读取的8bit数据
- //SDA设置为输入模式
- __IIC_SDAMode(GPIO_Mode_IN);
-
- for(int i=0;i<8;i++)
- {
- SCL = 0;
- delay_us(5);//SCL低电平期间是给从机发送数据位的时间
-
- SCL = 1;
- delay_us(2);
- if(SDA_R)
- {
- //数字1
- TemData |= 0x80>>i; //1000 0000
- }
- delay_us(3);//高电平期间主机可以判断SDA_R读取
- }
-
- SCL = 0;
- *RData = TemData;//将读到的结果存放到外面的容器中
-
- }
-
- //5、主机读取从机发送过来1个应答位
- //返回读到的应答位 0---有应答 1-----无应答
- char IIC_ReadAck(void)
- {
- char Ack=1;
- //SDA设置为输入模式
- __IIC_SDAMode(GPIO_Mode_IN);
-
- SCL = 0;
- delay_us(5);//低电平期间给从机发送应答信号的时间
-
- SCL = 1;
- delay_us(2);//高电平期间给主机读取数据位的时间
- Ack = SDA_R;
- delay_us(3);
-
- SCL = 0;
- return Ack;//返回读取到的应答结果 外面做判断处理
- }
-
- //6、主机发送给从机1个应答位
- //主机调用这个函数可以传参自己决定是发有应答还是无
- void IIC_WriteAck(char Ack)
- {
- //SDA设置为输出模式
- __IIC_SDAMode(GPIO_Mode_OUT);
-
- SCL = 0;
- delay_us(2);
- SDA_W = Ack;
- delay_us(3);
-
- SCL = 1;
- delay_us(5);
-
- SCL = 0;
- }