
iic协议
法官的英文-学生自我陈述报告
2023年2月22日发(作者:付琳)STC8a8k64d4开发DHT20(IIC通讯协议)
STC8a8k64d4开发DHT20(IIC通讯协议)
注:在此⽤的晶振位22.1184Mhz,其他型号单⽚机相关延时函数请修改。
``
1、与DHT20通讯
DHT20.c
#include"DHT20.h"
sbitDHT20_SDA=P2^0;
sbitDHT20_SCL=P2^1;
u16DHT11Data[DHT11_DATA_SIZE];
staticvoidDelay1us()//@22.1184MHz
{
unsignedchari;
_nop_();
i=5;
while(--i);
}
staticvoidSensorDelay_us(u16t)//延时函数
{
u16i;
for(i=0;i { Delay1us(); } } staticvoidDelay_4us(void)//延时函数 { unsignedchari; _nop_(); i=27; while(--i); } staticvoidDelay_5us(void)//延时函数 { unsignedchari; i=35; while(--i); } voidDHT20_Delay1ms()//@22.1184MHz { unsignedchari,j; i=29; j=183; do { while(--j); }while(--i); }while(--i); } voidDelay_1ms(u16t)//延时函数 { while(t--) { DHT20_Delay1ms();//延时1ms } } voidAHT20_Clock_Init(void)//延时函数 { //RCC_APB2PeriphClockCmd(CC_APB2Periph_GPIOB,ENABLE); } voidSDA_Pin_Output_High(void)//将PB15配置为输出,并设置为⾼电平,PB15作为I2C的SDA { GPIO_InitTypeDefGPIO_InitStructure;//结构定义 GPIO_=GPIO_Pin_0;//指定要初始化的IO,GPIO_Pin_0~GPIO_Pin_7,或操作SDA GPIO_=GPIO_OUT_PP;//指定IO的输⼊或输出⽅式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 DHT20_SDA=1; } voidSDA_Pin_Output_Low(void)//将P15配置为输出并设置为低电平 { GPIO_InitTypeDefGPIO_InitStructure;//结构定义 GPIO_=GPIO_Pin_0;//指定要初始化的IO,GPIO_Pin_0~GPIO_Pin_7,或操作SDA GPIO_=GPIO_OUT_PP;//指定IO的输⼊或输出⽅式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 DHT20_SDA=0; } voidSDA_Pin_IN_FLOATING(void)//SDA配置为浮空输⼊ { GPIO_InitTypeDefGPIO_InitStructure;//结构定义 GPIO_=GPIO_Pin_0;//指定要初始化的IO,GPIO_Pin_0~GPIO_Pin_7,或操作SDA GPIO_=GPIO_HighZ;//指定IO的输⼊或输出⽅式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 } voidSCL_Pin_Output_High(void)//SCL输出⾼电平,P14作为I2C的SCL { DHT20_SCL=1; } voidSCL_Pin_Output_Low(void)//SCL输出低电平 { DHT20_SCL=0; } voidSCL_INIT(void) { GPIO_InitTypeDefGPIO_InitStructure;//结构定义 GPIO_=GPIO_Pin_1;//SCL GPIO_=GPIO_OUT_PP;//指定IO的输⼊或输出⽅式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 } voidInit_I2C_Sensor_Port(void)//初始化I2C接⼝,输出为⾼电平 { GPIO_InitTypeDefGPIO_InitStructure;//结构定义 GPIO_=GPIO_Pin_0;//指定要初始化的IO,GPIO_Pin_0~GPIO_Pin_7,或操作SDA GPIO_=GPIO_OUT_PP;//指定IO的输⼊或输出⽅式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 GPIO_Inilize(GPIO_P2,&GPIO_InitStructure);//初始化 DHT20_SDA=1; SCL_INIT(); DHT20_SDA=1; } staticvoidI2C_Start(void)//I2C主机发送START信号 { SDA_Pin_Output_High(); SensorDelay_us(8); SCL_Pin_Output_High(); SensorDelay_us(8); SDA_Pin_Output_Low(); SensorDelay_us(8); SCL_Pin_Output_Low(); SensorDelay_us(8); } voidAHT20_WR_Byte(u8Byte)//往AHT20写⼀个字节 { u8Data,N,i; Data=Byte; i=0x80; for(N=0;N<8;N++) { SCL_Pin_Output_Low(); Delay_4us(); if(i&Data) { SDA_Pin_Output_High(); } else { SDA_Pin_Output_Low(); } SCL_Pin_Output_High(); Delay_4us(); Data<<=1; } SCL_Pin_Output_Low(); SensorDelay_us(8); SDA_Pin_IN_FLOATING(); SensorDelay_us(8); } u8AHT20_RD_Byte(void)//从AHT20读取⼀个字节 { u8Byte,i,a; Byte=0; SCL_Pin_Output_Low(); SDA_Pin_IN_FLOATING(); SensorDelay_us(8); for(i=0;i<8;i++) { SCL_Pin_Output_High(); Delay_5us(); a=0; if(DHT20_SDA)a=1; Byte=(Byte<<1)|a; SCL_Pin_Output_Low(); Delay_5us(); } } SDA_Pin_IN_FLOATING(); SensorDelay_us(8); returnByte; } u8Receive_ACK(void)//看AHT20是否有回复ACK { u16CNT; CNT=0; SCL_Pin_Output_Low(); SDA_Pin_IN_FLOATING(); SensorDelay_us(8); SCL_Pin_Output_High(); SensorDelay_us(8); while((DHT20_SDA)&&CNT<100) CNT++; if(CNT==100) { return0; } SCL_Pin_Output_Low(); SensorDelay_us(8); return1; } voidSend_ACK(void)//主机回复ACK信号 { SCL_Pin_Output_Low(); SensorDelay_us(8); SDA_Pin_Output_Low(); SensorDelay_us(8); SCL_Pin_Output_High(); SensorDelay_us(8); SCL_Pin_Output_Low(); SensorDelay_us(8); SDA_Pin_IN_FLOATING(); SensorDelay_us(8); } voidSend_NOT_ACK(void)//主机不回复ACK { SCL_Pin_Output_Low(); SensorDelay_us(8); SDA_Pin_Output_High(); SensorDelay_us(8); SCL_Pin_Output_High(); SensorDelay_us(8); SCL_Pin_Output_Low(); SensorDelay_us(8); SDA_Pin_Output_Low(); SensorDelay_us(8); } voidStop_I2C(void)//⼀条协议结束 { SDA_Pin_Output_Low(); SensorDelay_us(8); SCL_Pin_Output_High(); SensorDelay_us(8); SDA_Pin_Output_High(); SensorDelay_us(8); } u8AHT20_Read_Status(void)//读取AHT20的状态寄存器 u8AHT20_Read_Status(void)//读取AHT20的状态寄存器 { u8Byte_first; I2C_Start(); AHT20_WR_Byte(0x71); Receive_ACK(); Byte_first=AHT20_RD_Byte(); Send_NOT_ACK(); Stop_I2C(); returnByte_first; } u8AHT20_Read_Cal_Enable(void)//查询calenable位有没有使能 { u8val=0;//ret=0, val=AHT20_Read_Status(); if((val&0x68)==0x08) return1; elsereturn0; } voidAHT20_SendAC(void)//向AHT20发送AC命令 { I2C_Start(); AHT20_WR_Byte(0x70); Receive_ACK(); AHT20_WR_Byte(0xac);//0xAC采集命令 Receive_ACK(); AHT20_WR_Byte(0x33); Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); Stop_I2C(); } //CRC校验类型:CRC8/MAXIM //多项式:X8+X5+X4+1 //Poly:001100010x31 //⾼位放到后⾯就变成100011000x8c //C现实代码: u8Calc_CRC8(u8*message,u8Num) { u8i; u8byte; u8crc=0xFF; for(byte=0;byte { crc^=(message[byte]); for(i=8;i>0;--i) { if(crc&0x80)crc=(crc<<1)^0x31; elsecrc=(crc<<1); } } returncrc; } voidAHT20_Read_CTdata(u16*ct)//没有CRC校验,直接读取AHT20的温度和湿度数据 { volatileu8Byte_1th=0; volatileu8Byte_2th=0; volatileu8Byte_3th=0; volatileu8Byte_4th=0; volatileu8Byte_4th=0; volatileu8Byte_5th=0; volatileu8Byte_6th=0; u16RetuData=0; u16cnt=0; AHT20_SendAC();//向AHT10发送AC命令 Delay_1ms(80);//延时80ms左右 cnt=0; while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表⽰为空闲状态,若为1,表⽰忙状态 { SensorDelay_us(1508); if(cnt++>=100) { break; } } I2C_Start(); AHT20_WR_Byte(0x71); Receive_ACK(); Byte_1th=AHT20_RD_Byte();//状态字,查询到状态为0x98,表⽰为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表⽰为空闲状态,bit[7]为0 Send_ACK(); Byte_2th=AHT20_RD_Byte();//湿度 Send_ACK(); Byte_3th=AHT20_RD_Byte();//湿度 Send_ACK(); Byte_4th=AHT20_RD_Byte();//湿度/温度 Send_ACK(); Byte_5th=AHT20_RD_Byte();//温度 Send_ACK(); Byte_6th=AHT20_RD_Byte();//温度 Send_NOT_ACK(); Stop_I2C(); RetuData=(RetuData|Byte_2th)<<8; RetuData=(RetuData|Byte_3th)<<8; RetuData=(RetuData|Byte_4th); RetuData=RetuData>>4; ct[0]=RetuData;//湿度 RetuData=0; RetuData=(RetuData|Byte_4th)<<8; RetuData=(RetuData|Byte_5th)<<8; RetuData=(RetuData|Byte_6th); RetuData=RetuData&0xfffff; ct[1]=RetuData;//温度 } voidAHT20_Read_CTdata_crc(u16*ct)//CRC校验后,读取AHT20的温度和湿度数据 { volatileu8Byte_1th=0; volatileu8Byte_2th=0; volatileu8Byte_3th=0; volatileu8Byte_4th=0; volatileu8Byte_5th=0; volatileu8Byte_6th=0; volatileu8Byte_7th=0; u16RetuData=0; u16cnt=0; //u8CRCDATA=0; u8CTDATA[6]={0};//⽤于CRC传递数组 AHT20_SendAC();//向AHT10发送AC命令 Delay_1ms(80);//延时80ms左右 cnt=0; while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表⽰为空闲状态,若为1,表⽰忙状态 while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表⽰为空闲状态,若为1,表⽰忙状态 { SensorDelay_us(1508); if(cnt++>=100) { break; } } I2C_Start(); AHT20_WR_Byte(0x71); Receive_ACK(); CTDATA[0]=Byte_1th=AHT20_RD_Byte();//状态字,查询到状态为0x98,表⽰为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表⽰为空闲状态,bit[ 7]为0 Send_ACK(); CTDATA[1]=Byte_2th=AHT20_RD_Byte();//湿度 Send_ACK(); CTDATA[2]=Byte_3th=AHT20_RD_Byte();//湿度 Send_ACK(); CTDATA[3]=Byte_4th=AHT20_RD_Byte();//湿度/温度 Send_ACK(); CTDATA[4]=Byte_5th=AHT20_RD_Byte();//温度 Send_ACK(); CTDATA[5]=Byte_6th=AHT20_RD_Byte();//温度 Send_ACK(); Byte_7th=AHT20_RD_Byte();//CRC数据 Send_NOT_ACK();//注意:最后是发送NAK Stop_I2C(); if(Calc_CRC8(CTDATA,6)==Byte_7th) { RetuData=(RetuData|Byte_2th)<<8; RetuData=(RetuData|Byte_3th)<<8; RetuData=(RetuData|Byte_4th); RetuData=RetuData>>4; ct[0]=RetuData;//湿度 RetuData=0; RetuData=(RetuData|Byte_4th)<<8; RetuData=(RetuData|Byte_5th)<<8; RetuData=(RetuData|Byte_6th); RetuData=RetuData&0xfffff; ct[1]=RetuData;//温度 } else { ct[0]=0x00; ct[1]=0x00;//校验错误返回值,客户可以根据⾃⼰需要更改 }//CRC数据 } voidAHT20_Init(void)//初始化AHT20 { Init_I2C_Sensor_Port(); I2C_Start(); AHT20_WR_Byte(0x70); Receive_ACK(); AHT20_WR_Byte(0xa8);//0xA8进⼊NOR⼯作模式 Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); Stop_I2C(); Stop_I2C(); Delay_1ms(10);//延时10ms左右 I2C_Start(); AHT20_WR_Byte(0x70); Receive_ACK(); AHT20_WR_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,AHT10的初始化命令是0xE1 Receive_ACK(); AHT20_WR_Byte(0x08);//相关寄存器bit[3]置1,为校准输出 Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); Stop_I2C(); Delay_1ms(10);//延时10ms左右 } voidJH_Reset_REG(u8addr) { u8Byte_first,Byte_second,Byte_third; I2C_Start(); AHT20_WR_Byte(0x70);//原来是0x70 Receive_ACK(); AHT20_WR_Byte(addr); Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); AHT20_WR_Byte(0x00); Receive_ACK(); Stop_I2C(); Delay_1ms(5);//延时5ms左右 I2C_Start(); AHT20_WR_Byte(0x71);// Receive_ACK(); Byte_first=AHT20_RD_Byte(); Send_ACK(); Byte_second=AHT20_RD_Byte(); Send_ACK(); Byte_third=AHT20_RD_Byte(); Send_NOT_ACK(); Stop_I2C(); Delay_1ms(10);//延时10ms左右 I2C_Start(); AHT20_WR_Byte(0x70);/// Receive_ACK(); AHT20_WR_Byte(0xB0|addr);寄存器命令 Receive_ACK(); AHT20_WR_Byte(Byte_second); Receive_ACK(); AHT20_WR_Byte(Byte_third); Receive_ACK(); Stop_I2C(); Byte_second=0x00; Byte_third=0x00; } voidAHT20_Start_Init(void) { JH_Reset_REG(0x1b); JH_Reset_REG(0x1c); JH_Reset_REG(0x1e); } //---------------------------------------------------------------------------------------------- voidDHT20_TASK(void)//这个函数写进循环 { AHT20_Read_CTdata(DHT11Data); } DHT20.h #ifndef_DHT20_H_ #define_DHT20_H_ #include"APP_ALL_DEVICE.h" #include"STC8A_GPIO.h" #defineDHT11_DATA_SIZE30 voidDHT20_TASK(void); voidDelay_N10us(u16t);//延时函数 voidSensorDelay_us(u16t);//延时函数 voidDelay_4us(void);//延时函数 voidDelay_5us(void);//延时函数 voidDelay_1ms(u16t); voidAHT20_Clock_Init(void);//延时函数 voidSDA_Pin_Output_High(void);//将PB15配置为输出,并设置为⾼电平,PB15作为I2C的SDA voidSDA_Pin_Output_Low(void);//将P15配置为输出并设置为低电平 voidSDA_Pin_IN_FLOATING(void);//SDA配置为浮空输⼊ voidSCL_Pin_Output_High(void);//SCL输出⾼电平,P14作为I2C的SCL voidSCL_Pin_Output_Low(void);//SCL输出低电平 voidInit_I2C_Sensor_Port(void);//初始化I2C接⼝,输出为⾼电平 voidI2C_Start(void);//I2C主机发送START信号 voidAHT20_WR_Byte(u8Byte);//往AHT20写⼀个字节 u8AHT20_RD_Byte(void);//从AHT20读取⼀个字节 u8Receive_ACK(void);//看AHT20是否有回复ACK voidSend_ACK(void);//主机回复ACK信号 voidSend_NOT_ACK(void);//主机不回复ACK voidStop_I2C(void);//⼀条协议结束 u8AHT20_Read_Status(void);//读取AHT20的状态寄存器 u8AHT20_Read_Cal_Enable(void);//查询calenable位有没有使能 voidAHT20_SendAC(void);//向AHT20发送AC命令 u8Calc_CRC8(u8*message,u8Num); voidAHT20_Read_CTdata(u16*ct);//没有CRC校验,直接读取AHT20的温度和湿度数据 voidAHT20_Read_CTdata_crc(u16*ct);//CRC校验后,读取AHT20的温度和湿度数据 voidAHT20_Init(void);//初始化AHT20 voidJH_Reset_REG(u8addr);///重置寄存器 voidAHT20_Start_Init(void);///上电初始化进⼊正常测量状态 #endif ------本⽂代码参考了DHT20官⽅资料