STM32 IIC 通信 模拟方式
reading stucture | ||||||||||||||||
device address | read command | write address to board | device address | read data from board | ||||||||||||
start | 0xb0 | ack | 0x01 | ack | address high | ack | address low | ack | start | 0xb1 | ack | data high | ack | data low | nack | stop |
example to read address 0x1234 and result 0x789A | ||||||||||||||||
start | 0xb0 | ack | 0x01 | ack | 0x12 | ack | 0x34 | ack | start | 0xb1 | ack | 0x78 | ack | 0x9a | nack | stop |
writing stucture | ||||||||||||||||
device address | write command | write address to board | read data from board | |||||||||||||
start | 0xb0 | ack | 0x81 | ack | address high | ack | address low | ack | data high | ack | data low | ack | stop | |||
example to write address 0x5678 with data 0xcdef | ||||||||||||||||
start | 0xb0 | ack | 0x81 | ack | 0x56 | ack | 0x78 | ack | 0xcd | ack | 0xef | ack | stop | 0x9a |
ReadSensor
uint16_t IIC_ReadSensor(uint8_t byAD, uint16_t byRA, uint8_t byCount ) { uint8_t tmp_h=0, tmp_l=0; IIC_Start(); /*启动总线*/ IIC_WriteBit(byAD); /*发送器件地址*/ IIC_WaitAck(); IIC_WriteBit(0x01); /*发送器件地址*/ IIC_WaitAck(); IIC_WriteBit(byRA>>8); /*发送器件子地址---数据寄存器*/ IIC_WaitAck(); IIC_WriteBit((uint8_t)byRA); /*发送器件子地址---数据寄存器*/ IIC_WaitAck(); IIC_Start(); /*重新启动总线*/ IIC_WriteBit(byAD + 1);//address_read IIC_WaitAck(); tmp_h=IIC_ReadBit(); /*接收数据*/ IIC_Respond(0); /*发送就答位*/ tmp_l=IIC_ReadBit(); IIC_Respond(1); /*发送非应位*/ IIC_Stop(); /*结束总线*/ return((tmp_h<<8) | tmp_l); }
WriteSensor
uint16_t IIC_WriteSensor(uint8_t byAD, uint16_t byRA, uint16_t data ) { uint8_t tmp_h=0, tmp_l=0; IIC_Start(); /*启动总线*/ IIC_WriteBit(byAD); /*发送器件地址*/ IIC_WaitAck(); IIC_WriteBit(0x81); /*发送器件地址*/ IIC_WaitAck(); IIC_WriteBit(byRA>>8); /*发送器件子地址---数据寄存器*/ IIC_WaitAck(); IIC_WriteBit((uint8_t)byRA); /*发送器件子地址---数据寄存器*/ IIC_WaitAck(); IIC_WriteBit(data>>8); /*发送数据高八位*/ IIC_WaitAck(); IIC_WriteBit((uint8_t)data); /*发送数据低八位*/ IIC_WaitAck(); IIC_Stop(); /*结束总线*/ }
IIC_Start
void IIC_Start(void) //IIC开始函数 { IIC_SDA_Out(); IIC_SDA_SET; IIC_SCL_SET; Delay_Us(4); IIC_SDA_RESET; Delay_Us(4); IIC_SCL_RESET; }
IIC_Stop
void IIC_Stop(void) //IIC结束函数 { IIC_SDA_Out(); IIC_SCL_RESET; IIC_SDA_RESET; Delay_Us(4); IIC_SCL_SET; Delay_Us(4); IIC_SDA_SET; }
IIC_Respond
void IIC_Respond(u8 re) //IIC应答函数 { u8 i; IIC_SDA_Out(); if(re) IIC_SDA_SET; else IIC_SDA_RESET; IIC_SCL_SET; Delay_Us(5); IIC_SCL_RESET; Delay_Us(2); }
IIC_WaitAck
u8 IIC_WaitAck(void) { u8 Out_Time=350; IIC_SDA_SET; IIC_SDA_In(); Delay_Us(1); IIC_SCL_SET; Delay_Us(1); // IIC_SDA_In(); while(IIC_SDA_GET) { if(--Out_Time) { printf("IIC time out!"); IIC_Stop(); return 1; } } IIC_SCL_RESET; return 0; }
IIC_Init
void IIC_Init(void) //IIC初始化函数 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(GPIOB,&GPIO_InitStructure); IIC_SDA_Out(); IIC_SDA_SET; IIC_SCL_SET; }
IIC_SDA_Out & IIC_SDA_In
void IIC_SDA_Out(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(IIC_PORT, &GPIO_InitStructure); } void IIC_SDA_In(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IIC_SDA; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(IIC_PORT, &GPIO_InitStructure); }
IIC_ReadBit
u8 IIC_ReadBit(void) //从2402中读取一字节函数 { u8 i,Temp; IIC_SDA_In(); for(i=0;i<8;i++) { IIC_SCL_RESET; Delay_Us(2); IIC_SCL_SET; Temp<<=1; //错误原来在这里 写成Temp<<1; if(IIC_SDA_GET)Temp++; Delay_Us(2); } IIC_SCL_RESET; return Temp; }
IIC_WriteBit
void IIC_WriteBit(u8 Temp) //向2402中写一字节数据 { u8 i; IIC_SDA_Out(); IIC_SCL_RESET; for(i=0;i<8;i++) { if(Temp&0x80) { IIC_SDA_SET; } else { IIC_SDA_RESET; } Temp<<=1; Delay_Us(2); IIC_SCL_SET; Delay_Us(4); IIC_SCL_RESET; Delay_Us(2); } }
此代码为朋友所写,记录在此学习用。
谢谢东林
在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件(见图3):当SCL保持“高”时,SDA由“高”变为“低”为开始条件;当SCL保持“高”且SDA由“低”变为“高”时为停止条件。开始和停止条件均由主控制器产生。
SDA线上的数据在时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,每次传输的字节不受限制,但每个字节必须要有一个应答ACK。