糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 智慧农场 51单片机上实现DS18B20与YL69土壤湿度传感器 并将两个获取的数据在LCD上显示出来

智慧农场 51单片机上实现DS18B20与YL69土壤湿度传感器 并将两个获取的数据在LCD上显示出来

时间:2022-05-16 16:35:29

相关推荐

智慧农场 51单片机上实现DS18B20与YL69土壤湿度传感器 并将两个获取的数据在LCD上显示出来

上一篇我说了我们做的是两个模块,但是介于DS18B20的资料太多,我就不再阐述,直接给最终的代码。

该代码是将温度传感器与YL69湿度传感器获取的数据在51单片机LCD上显示出来

#include <reg52.H>#include <intrins.H>#include <math.H>#define uchar unsigned char#define uint unsigned int#define AT24C02_ADDR 0xa0//AT24C02地址#define DAC_EN 0x40#define ADC_AutoINC 0x04#define PCF8591_ADDR 0x90//PCF8591地址sbit SDA = P2^0;sbit SCL = P2^1;sbit LCDEN=P3^4;sbit LCD_RS= P3^5;//LCD写数据或命令控制IOsbit LCD_RW = P3^6;//LCD读写控制IOsbit dula = P2^6;sbit wela = P2^7;sbit IN1=P1^0;sbit IN2=P1^1;sbit ENA=P1^2;sbit beep = P2^3;uint strHEX[4];INT8UtostrHEX函数转换的字符串显示10进制void delayUs(){_nop_();}void delayMs(uint a){uint i, j;for(i = a; i > 0; i--)for(j = 100; j > 0; j--);}/*I2C初始化*/void I2C_init(){SDA = 1;_nop_();SCL = 1;_nop_();}/*I2C起始信号*/void I2C_Start() {SCL = 1;_nop_();SDA = 1;delayUs();SDA = 0;delayUs();}/*I2C终止信号*/void I2C_Stop(){SDA = 0;_nop_();SCL = 1;delayUs();SDA = 1;delayUs();}/*主机发送应答*/void Master_ACK(bit i){SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化_nop_(); // 让总线稳定if (i) //如果i = 1 那么拉低数据总线 表示主机应答{SDA = 0;}else {SDA = 1; //发送非应答}_nop_();//让总线稳定SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号delayUs();SCL = 0;//拉低时钟总线, 占用总线继续通信_nop_();SDA = 1;//释放SDA数据总线。_nop_();}/*检测从机应答*/bit Test_ACK(){SCL = 1;delayUs();if (SDA){SCL = 0;_nop_();I2C_Stop();return(0);}else{SCL = 0;_nop_();return(1);}}/*发送一个字节*/void I2C_send_byte(uchar byte){uchar i;for(i = 0 ; i < 8 ; i++){SCL = 0;_nop_();if (byte & 0x80){SDA = 1;_nop_(); }else{SDA = 0;_nop_();}SCL = 1;_nop_();byte <<= 1;// 0101 0100B }SCL = 0;_nop_();SDA = 1;_nop_();}/*I2C 读一字节*/uchar I2C_read_byte(){uchar dat,i;SCL = 0;_nop_();SDA = 1;_nop_();for(i = 0 ; i < 8 ; i++){SCL = 1;_nop_();if (SDA) {dat |= 0x01; //}else{dat &= 0xfe;//1111 1110}_nop_();SCL = 0 ;_nop_();if(i < 7){dat = dat << 1;}}return(dat);}uint *INT8UtostrHEX(uint num)//将一个字节的数据转换为字符串{uint i = 0;switch(num/100){case 0:strHEX[i] = '0'; i++;break;case 1:strHEX[i] = '1';i++;break;case 2:strHEX[i] = '2';i++;break;case 3:strHEX[i] = '3';i++;break;case 4:strHEX[i] = '4';i++;break;case 5:strHEX[i] = '5';i++;break;case 6:strHEX[i] = '6';i++;break;case 7:strHEX[i] = '7';i++;break;case 8:strHEX[i] = '8';i++;break;case 9:strHEX[i] = '9';i++;break;}switch(num%100/10){case 0:strHEX[i] = '0';i++;break;case 1:strHEX[i] = '1';i++;break;case 2:strHEX[i] = '2';i++;break;case 3:strHEX[i] = '3';i++;break;case 4:strHEX[i] = '4';i++;break;case 5:strHEX[i] = '5';i++;break;case 6:strHEX[i] = '6';i++;break;case 7:strHEX[i] = '7';i++;break;case 8:strHEX[i] = '8';i++;break;case 9:strHEX[i] = '9';i++;break;}switch(num%100%10){case 0:strHEX[i] = '0';i++;break;case 1:strHEX[i] = '1';i++;break;case 2:strHEX[i] = '2';i++;break;case 3:strHEX[i] = '3';i++;break;case 4:strHEX[i] = '4';i++;break;case 5:strHEX[i] = '5';i++;break;case 6:strHEX[i] = '6';i++;break;case 7:strHEX[i] = '7';i++;break;case 8:strHEX[i] = '8';i++;break;case 9:strHEX[i] = '9';i++;break;}strHEX[3] = '\0';return (strHEX);}//写命令void writeComm(uchar comm){LCD_RS = 0; P0 = comm;LCDEN = 1;delayUs();LCDEN = 0;delayMs(1);}//写数据void writeData(uchar dat){LCD_RS = 1;P0 = dat;LCDEN = 1;delayUs();LCDEN = 0;delayMs(1);}//写字符串void writeString(uchar * str, uchar length){uchar i;for(i = 0; i < length; i++){writeData(str[i]);}}//写字符串void LCD1602_Write_String(uint x,uint y,uint *s) //LCD1602写字符串{if (y == 0) {writeComm(0x80 + x);//表示第一行}else {writeComm(0xC0 + x);//表示第二行} while (*s != '\0') {writeData(*s++); }}//初始化显示屏void init(){LCD_RW = 0; dula = wela = 0;writeComm(0x38);// 16*2显示 writeComm(0x0c); //打开显示 writeComm(0x06);//显示指针加1 writeComm(0x01); //清屏 }/*ad读数据*/bit I2C_ADC_ReadData(uchar ADDR, uint *ADC_Value){I2C_Start() ;I2C_send_byte(PCF8591_ADDR + 0);if (!Test_ACK()){return(0);}I2C_send_byte(ADDR);Master_ACK(0);I2C_Start();I2C_send_byte(PCF8591_ADDR + 1);if (!Test_ACK()){return(0);}*ADC_Value = I2C_read_byte();Master_ACK(0);I2C_Stop();return(1);}/*DS18B02温度*/ sbit ds = P2^2;void dsInit(){unsigned int i; ds = 0;i = 100; while(i>0) i--;ds = 1; i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds); while(~ds);i = 4;while(i > 0) i--;}bit readBit() //读时序{unsigned int i;bit b;ds = 0;i++; ds = 1; i++; i++; b = ds;i = 8; while(i>0) i--;return b;}unsigned char readByte() {unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();dat = (j << 7) | (dat >> 1);}return dat;}void writeByte(unsigned char dat)//用于写命令使用{unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;if(b) {ds = 0;i++; i++; ds = 1; i = 8; while(i>0) i--; }else {ds = 0;i = 8; while(i>0) i--; ds = 1;i++; i++;}}}void sendChangeCmd(){dsInit(); dsWait(); delayMs(1); writeByte(0xcc);//发送跳跃ROM指令 writeByte(0x44);// 发送温度转换指令 }void sendReadCmd(){dsInit();dsWait();delayMs(1);writeByte(0xcc); //发送跳跃指令 writeByte(0xbe); //读取DS18B20暂存器的值 }int getTmpValue(){unsigned int tmpvalue;int value; float t;unsigned char low, high;sendReadCmd();low = readByte();//只读取前温度的值 high = readByte();tmpvalue = high;//将两个字节温度的值储存在tempvalue中 tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;t = value * 0.0625;//将二进制的值转换为十进制 value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}void display(int v) //LCD显示温度的值{unsigned char count;unsigned char datas[] = {0, 0, 0, 0, 0};unsigned int tmp = abs(v);datas[0] = tmp / 10000;datas[1] = tmp % 10000 / 1000;datas[2] = tmp % 1000 / 100;datas[3] = tmp % 100 / 10;datas[4] = tmp % 10;writeComm(0x80|0x07);if(datas[0] != 0){writeData('0'+datas[0]);}for(count = 1; count != 5; count++){writeData('0'+datas[count]);if(count == 2){writeData('.');}}}void main(){int a;uint ADC_Value;uchar table1[] = "wendu: ";uchar table2[] = "shidu: ";sendChangeCmd();init();I2C_init();writeComm(0x80);writeString(table1, 6);writeComm(0x80 | 0x40);writeString(table2, 6);while(1){delayMs(1000); //温度转换时间需要750ms以上sendChangeCmd();writeComm(0xc0);do{a=getTmpValue();}while(a>=8500) ;display(a);if(a>=3000){ENA=1;IN1=0;IN2=1;beep=0;} else{ENA=0;beep=1;} I2C_ADC_ReadData(3, &ADC_Value);LCD1602_Write_String(7,1,INT8UtostrHEX(ADC_Value));delayMs(400); }}

其实一个用的I2C,一个用的单总线,所以将两个分别写出来之后合在一个程序里面即可。

如果觉得《智慧农场 51单片机上实现DS18B20与YL69土壤湿度传感器 并将两个获取的数据在LCD上显示出来》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。