这一次使用的温湿度传感器也是经历了几次变动,从开始用的DHT11模块,到接下来的AMD2302,再到最后使用的AMD2302可用版本,不得不说,模块的价位真的决定了她的性能,很大程度上,开始的DHT11这个模块,真心尼玛坑爹啊,调试程序调试了好久,突然间发现他是坏的,AMD2302好好地,就是因为短了一下路,结果就烧了,又白等了几天,他们的性能都差不多,AMD2302的价位是20多块钱,我在想这个是不是在抢钱,好的传感器都比较贵,,,,,但是买东西的一条法则,尤其是元器件,那就是便宜没好货
总结几条买传感器的法则:1,由于传感器容易坏,所以项目的时候,一定要买两个,也就是所用项目传感器的2倍,
2:尽量挑好的传感器用于比赛,嘻嘻,因为学校有报销嘛
好了现在总结一下AMD2302传感器是怎么样工作的调试程序过程中又能学到什么!!!
这个是模块资料下载地址:http://download.csdn.net/detail/generoius/7142111
//****************************************************************// // AM系列读单总线使用范例 //单片机 :AT89S52 或 STC89C52RC // 功能 :串口发送温湿度数据 波特率 9600 // 晶振 :12M (用户系统时钟如不是12M 请更改相关宏定义及注释的延时时间) // 编译环境: Keil3 // 公司 :奥松电子 //****************************************************************// #include "reg52.h" #include <intrins.h> //用户根据自己的晶振修改相应值 #define FOSC 12000000 #define BAUD 9600 //读传感器 端口位定义,可修改 sbit Sensor_SDA = P0^0; sbit Sensor_SCL = P0^1; // 变量定义 unsigned char Sensor_Data[5]={0x00,0x00,0x00,0x00,0x00}; unsigned char Sensor_Check; //校验和 unsigned char Sensor_AnswerFlag; //收到起始标志位 unsigned char Sensor_ErrorFlag; //读取传感器错误标志 unsigned int Sys_CNT; unsigned int Tmp; unsigned char *String; //字符串定义 #define S_Temp "Temp:" #define S_RH "RH:" #define S_CRCT "Check: True" #define S_CRCF "Check: Wrong" #define S_Data "Data: " #define S_NotS "Sensor Not Connected" /********************************************\ |* 功能: 延时 晶振为12M时 *| |* t = 1 为 20us 然后成倍增加10us左右 *| \********************************************/ void Delay_N10us(unsigned char t) { while(t--) { _nop_(); } } /********************************************\ |* 功能: 延时 晶振为12M时 *| |* 延时大约 1ms *| \********************************************/ void Delay_N1ms(unsigned int t) { unsigned int i; unsigned int j; for(j=t;j>0;j--) for(i=124;i>0;i--); //延时大约 1ms } /********************************************\ |* 功能: 初始化串口 *| \********************************************/ void InitUART(void) { unsigned int iTmpBaud; unsigned long lTmpBaud; iTmpBaud = 0; //首先选定定时器2作为波特率发生器,16位定时器,自动装载 SCON = 0x50; //SM0 SM1 SM2 REN TB8 RB8 TI RI //0 1 0 1 0 0 0 0 PCON = 0x00; //PCON的地址是87H,这里SMOD =0 T2CON = 0x30; //TF2 EXF2 RCLK TCLK EXEN2 TR2 C(/T2) CP(/RL2) //0 0 1 1 0 0 0 0 T2MOD = 0x00; // / / / / / / T2OE DCEN //0 0 0 0 0 0 0 0 lTmpBaud = FOSC/BAUD; lTmpBaud /= 32; //12T-mode iTmpBaud = lTmpBaud & 0xFFFF; iTmpBaud = 65536 - iTmpBaud; RCAP2H = (iTmpBaud>>8) & 0x0FF; RCAP2L = iTmpBaud & 0x0FF; RI = 0; //清除接收中断标志 REN = 1; //允许串行接收 ES = 1; //允许串行中断 TR2 = 1; //启动定时器1 EA=1;//开总中断 } /********************************************\ |* 功能: 串口发送函数 *| \********************************************/ void UARTSend(char UCHAR) { SBUF=UCHAR; while(TI==0); TI=0; } /********************************************\ |* 功能: 串口中断函数 *| \********************************************/ void UARTRead(void) interrupt 4 { char temp; if(RI) { RI=0; temp = SBUF; } } /********************************************\ |* 功能: 串口发送子函数 *| \********************************************/ void UART_PutString(unsigned char *buf) { while(*buf) UARTSend(*buf++); } void UART_PutStringAndNum(unsigned char *buf ,unsigned int num) { unsigned char a[3],i; a[3] = '0'+num%10; a[2] = '.'; a[1] = '0'+num/10%10; a[0] = '0'+num/100%10; while(*buf) UARTSend(*buf++); UARTSend(' '); for(i=0;i<4;i++) { UARTSend(a[i]); } } void UART_PutStringAnd_Data(unsigned char *buf ,unsigned char *bufdata) { unsigned char a[2],i,j; while(*buf) UARTSend(*buf++); UARTSend(' '); for(i=0;i<5;i++) { a[0] = bufdata[i]/16; a[1] = bufdata[i]%16; for(j=0;j<2;j++) { if(a[j]>9) { a[j] = (a[j]-10)+'A'; } else { a[j] = a[j]+'0'; } UARTSend(a[j]); } UARTSend(' '); } } /********************************************\ |* 功能: 串口发送传感器数据函数 *| \********************************************/ void UARTSend_Nbyte(void) { if(Sensor_AnswerFlag == 1) { Sensor_Check = Sensor_Data[0]+Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3]; //校验成功 if(Sensor_Check ==Sensor_Data[4]) { String = S_RH;//"RH:"; Tmp = Sensor_Data[0]*256+Sensor_Data[1]; UART_PutStringAndNum(String,Tmp); UARTSend(' '); UARTSend(' '); String = S_Temp;// "Temp:"; Tmp = Sensor_Data[2]*256+Sensor_Data[3]; UART_PutStringAndNum(String,Tmp); UARTSend(' '); UARTSend(' '); String = S_CRCT;//"Check: True"; UART_PutString(String); }else //校验失败 送上读到数据 { String = S_Data;//"Data: "; UART_PutStringAnd_Data(String,Sensor_Data); UARTSend(' '); UARTSend(' '); String = S_CRCF;//"Check: Wrong"; UART_PutString(String); } }// 传感器未连接 else { String = S_NotS; //"Sensor Not Connected"; UART_PutString(String); } UARTSend(0x0A); } void Clear_Data (void) { int i; for(i=0;i<5;i++) { Sensor_Data[i] = 0x00; }//接收数据清零 } /********************************************\ |* 功能: 读传感器发送的单个字节 *| \********************************************/ unsigned char Read_SensorData(void) { unsigned char i,cnt; unsigned char buffer,tmp; buffer = 0; for(i=0;i<8;i++) { cnt=0; while(!Sensor_SDA) //检测上次低电平是否结束 { if(++cnt >= 300) { break; } } //延时Min=26us Max50us 跳过数据"0" 的高电平 Delay_N10us(2); //延时30us //判断传感器发送数据位 tmp =0; if(Sensor_SDA) { tmp = 1; } cnt =0; while(Sensor_SDA) //等待高电平 结束 { if(++cnt >= 200) { break; } } buffer <<=1; buffer |= tmp; } return buffer; } /********************************************\ |* 功能: 读传感器 *| \********************************************/ unsigned char Read_Sensor(void) { unsigned char i; //主机拉低(Min=800US Max=20Ms) Sensor_SDA = 0; Delay_N1ms(2); //延时2Ms //释放总线 延时(Min=30us Max=50us) Sensor_SDA = 1; Delay_N10us(1);//延时30us //主机设为输入 判断传感器响应信号 Sensor_SDA = 1; Sensor_AnswerFlag = 0; // 传感器响应标志 //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行 if(Sensor_SDA ==0) { Sensor_AnswerFlag = 1;//收到起始信号 Sys_CNT = 0; //判断从机是否发出 80us 的低电平响应信号是否结束 while((!Sensor_SDA)) { if(++Sys_CNT>300) //防止进入死循环 { Sensor_ErrorFlag = 1; return 0; } } Sys_CNT = 0; //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态 while((Sensor_SDA)) { if(++Sys_CNT>300) //防止进入死循环 { Sensor_ErrorFlag = 1; return 0; } } // 数据接收 传感器共发送40位数据 // 即5个字节 高位先送 5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和 // 校验和为:湿度高位+湿度低位+温度高位+温度低位 for(i=0;i<5;i++) { Sensor_Data[i] = Read_SensorData(); } } else { Sensor_AnswerFlag = 0; // 未收到传感器响应 } return 1; } void main(void) { Sensor_SCL = 0; InitUART(); //初始串口发送函数 while(1) { Clear_Data(); // 清除收到数据 Read_Sensor(); // 读取传感器数据 UARTSend_Nbyte(); // 串口发送读到传感器数据 Delay_N1ms(2000); // 延时 2S(两次读取间隔至少2S) } }
这个是模块提供的程序,有代码可以知道这个模块工作是用来I2C协议,并且提供的例程比较好,用串口可以进行调试,这个文件是一个单文件的程序,如何给他整理一个单独的模块,让他融进大程序中去,才是玩模块的人的核心工作,这也是为什么玩模块的人出去工作不怎么高的原因
这个是我的程序中的一段话:
//这个程序调试也调试了好久现在总结一下单文件变多文件的步骤
//第一:将要拆封的源文件 新建一个新的头文件
//第二:填入三句话:#ifndef *****#define******#endif
//第三在.h文件中包含原来文件中所有的函数声明
//第四:将源文件的变量名复制,记得是复制,因为放在头文件中只是声明,声明不等于定义
//第五:由于是声明:所以变量不需要赋值,所以将头文件中变量的赋值删除
//第六,在源文件中包含该头文件
注意以后修改程序,都要在先复制程序,然后在进行更改,并且对程序的修改作进一步的说明,以及程序哪些地方需要共同注意,这是程序员最基本的一种素质
此外还需要注意变量的定义,有些变量,在同一个文件中有别名,所以需要自己动手,修改他们
这是我修改的程序:我也把他晒出来
wendu.c
//****************************************************************// // AM系列读单总线使用范例 //单片机 :AT89S52 或 STC89C52RC // 功能 :串口发送温湿度数据 波特率 9600 // 晶振 :12M (用户系统时钟如不是12M 请更改相关宏定义及注释的延时时间) // 编译环境: Keil3 // 公司 :奥松电子 //****************************************************************// #include "reg52.h" #include <intrins.h> #include"wendu.h" // 变量定义 unsigned char Sensor_Check; //校验和 unsigned char Sensor_AnswerFlag; //收到起始标志位 unsigned char Sensor_ErrorFlag; //读取传感器错误标志 unsigned int Sys_CNT; /********************************************\ |* 功能: 延时 晶振为12M时 *| |* t = 1 为 20us 然后成倍增加10us左右 *| \********************************************/ void Delay_N10us(unsigned char t) { while(t--) { _nop_(); } } /********************************************\ |* 功能: 延时 晶振为12M时 *| |* 延时大约 1ms *| \********************************************/ void Delay_N1ms(unsigned int t) { unsigned int i; unsigned int j; for(j=t;j>0;j--) for(i=124;i>0;i--); //延时大约 1ms } void Clear_Data (void) { int i; for(i=0;i<5;i++) { Sensor_Data[i] = 0x00; }//接收数据清零 } /********************************************\ |* 功能: 读传感器发送的单个字节 *| \********************************************/ unsigned char Read_SensorData(void) { unsigned char i,cnt; unsigned char buffer,tmp; buffer = 0; for(i=0;i<8;i++) { cnt=0; while(!Sensor_SDA) //检测上次低电平是否结束 { if(++cnt >= 300) { break; } } //延时Min=26us Max50us 跳过数据"0" 的高电平 Delay_N10us(2); //延时30us //判断传感器发送数据位 tmp =0; if(Sensor_SDA) { tmp = 1; } cnt =0; while(Sensor_SDA) //等待高电平 结束 { if(++cnt >= 200) { break; } } buffer <<=1; buffer |= tmp; } return buffer; } /********************************************\ |* 功能: 读传感器 *| \********************************************/ unsigned char Read_Sensor(void) { unsigned char i; //主机拉低(Min=800US Max=20Ms) Sensor_SDA = 0; Delay_N1ms(2); //延时2Ms //释放总线 延时(Min=30us Max=50us) Sensor_SDA = 1; Delay_N10us(1);//延时30us //主机设为输入 判断传感器响应信号 Sensor_SDA = 1; Sensor_AnswerFlag = 0; // 传感器响应标志 //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行 if(Sensor_SDA ==0) { Sensor_AnswerFlag = 1;//收到起始信号 Sys_CNT = 0; //判断从机是否发出 80us 的低电平响应信号是否结束 while((!Sensor_SDA)) { if(++Sys_CNT>300) //防止进入死循环 { Sensor_ErrorFlag = 1; return 0; } } Sys_CNT = 0; //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态 while((Sensor_SDA)) { if(++Sys_CNT>300) //防止进入死循环 { Sensor_ErrorFlag = 1; return 0; } } // 数据接收 传感器共发送40位数据 // 即5个字节 高位先送 5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和 // 校验和为:湿度高位+湿度低位+温度高位+温度低位 for(i=0;i<5;i++) { Sensor_Data[i] = Read_SensorData(); } } else { Sensor_AnswerFlag = 0; // 未收到传感器响应 } return 1; } /*void main(void) { Sensor_SCL = 0; while(1) { Clear_Data(); // 清除收到数据 Read_Sensor(); // 读取传感器数据 Delay_N1ms(2000); // 延时 2S(两次读取间隔至少2S) } }*/
wendu.h
#ifndef __WENDU_H__ #define __WENDU_H__ #include <reg52.h> sbit Sensor_SDA = P3^3; sbit Sensor_SCL = P3^4; extern unsigned char Sensor_Data[5]; extern unsigned char Sensor_Check; //校验和 extern unsigned char Sensor_AnswerFlag; //收到起始标志位 extern unsigned char Sensor_ErrorFlag; //读取传感器错误标志 extern unsigned int Sys_CNT; extern unsigned int Tmp; void Clear_Data (void); void Delay_N10us(unsigned char t); void Delay_N1ms(unsigned int t); unsigned char Read_SensorData(void); unsigned char Read_Sensor(void); #endif
但是不要以为这样就可以得到正确的温湿度,因为这样得到的数字么有进行校正,需要在主程序中进行校正,这个校正也矫正了我好久
这个是主程序中的一段话:
Read_Sensor(); // 读取传感器数据 L1: //计算传感器数据 Sensor_Check = Sensor_Data[0]+Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3]; //校验成功 if(Sensor_Check ==Sensor_Data[4]) { // String = S_RH;//"RH:"; wetness = Sensor_Data[0]*256+Sensor_Data[1]; shidu[3] = '0'+wetness%10; shidu[2] = '.'; shidu[1] = '0'+wetness/10%10; shidu[0] = '0'+wetness/100%10; // String = S_Temp;// "Temp:"; temperature = Sensor_Data[2]*256+Sensor_Data[3]; wendu[3] = '0'+temperature%10; wendu[2] = '.'; wendu[1] = '0'+temperature/10%10; wendu[0] = '0'+temperature/100%10; } else { goto L1; }
经过上面的程序的修改,就可以得到精度为0.1的温湿度了
好了这个温湿度传感器模块就总结到这里!!!
版权所有,转载请注明链接地址:http://www.cnblogs.com/fengdashen/p/3643303.html
技术交流QQ:1070937053