用12864显示18B20
- 格式:doc
- 大小:36.00 KB
- 文档页数:5
基于Arduino的18B20+LCD12864温度显示本帖最后由 greenfort 于 2012-8-13 01:49 编辑初学Arduino,制作的通过12864显示多个18B20温度的程序接线请参考本论坛中的18B20及LCD12864与Arduino接线,这里不再重复,只是强调一点,18B20的PIN1和PIN3要同时接地,否则会在返回若干值后出现一次错误值(85.00)不知道什么原因鉴于12864的显示大小,程序最多接9个18B20传感器,多了显示不了程序代码如下1. /*2. LCD Arduino3. PIN1 = GND4. PIN2 = 5V5. RS(CS) = 8;6. RW(SID)= 9;7. EN(CLK) = 3;8. PIN15 PSB = GND;9. */10. #include <OneWire.h>11. #include <DallasTemperature.h>12. #include <stdlib.h>13. #define ONE_WIRE_BUS 214. #include "LCD12864RSPI.h"15. #define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )16.17. OneWire oneWire(ONE_WIRE_BUS);18. DallasTemperature sensors(&oneWire);19.20. char str[4]; //定义温度值存储数组,4位,其中3位为数字,1位为小数点21. double temp =0; //定义中间变量,用于将获取的float型温度值转变为unsigned char数组22. unsigned char show[]={23. 0xB5,0xB1,0xC7,0xB0,0xBB,0xB7,0xBE,0xB3,0xCE,0xC2,0xB6,0xC8};//当前环境温度24. int numberOfDevices;25. void setup()26. {27. Serial.begin(9600);28. sensors.begin(); //传感器初始化29. numberOfDevices = sensors.getDeviceCount();30. LCDA.Initialise(); // 屏幕初始化31. LCDA.DisplayString(0,0,show,AR_SIZE(show));//第一行第1格开始,显示文字“当前环境温度”32. }33.34. void loop()35. {36. sensors.requestTemperatures(); //获取温度值37. for(int i=0;i<numberOfDevices; i++) //逐个获取传感器的温度38. {39. temp=sensors.getTempCByIndex(i); //使用索引序号获得摄氏度数值40. dtostrf(temp,4,2,str); //将获取的数值转换为字符型数组41. if (i<=2)42. {43. LCDA.DisplayString(1,i*3,(unsigned char *)str,sizeof(str));。
本程序实现的功能:用DS18B20测温度,并用LCD12864液晶屏显示#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charsbit rs=P1^1;sbit rw=P1^2;sbit en=P1^3;sbit psb=P1^4;sbit ds=P1^5;uchar code table0[]="Current temp:";uchar code table1[]="当前温度:";uchar code table2[]="摄氏度";uchar table[4];uint temp;float f_temp;void delay(uint tms){uint i,j;for(i=tms;i>0;i--)for(j=110;j>0;j--);}void init_ds(){uint i;ds=0;i=103;while(i>0)ds=1;i=4;while(i>0)i--;}void tempwritebyte(uchar )//由时序图知,向DS18B20写入数据时,写0和写1的时序恰好相反{ //所以如下程序用if和else分别写入0和1;而当从DS18B20读数据时,uint i,j; //读0和读1的时序根本一样,所以读0和读1的程序合二为一,不用分别写出bit bb;for(i=0;i<8;i++){bb=&0x01;//最低位开始写入DS18B20=>>1;if(bb){ds=0;j++;j++;ds=1;j=8;while(j>0)j--;}else{j=8;while(j>0)j--;ds=1;j++;j++;}}}void tempchange(){init_ds();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uchar tempreadbyte()//由时序图知,向DS18B20写入数据时,写0和写1的时序恰好相反{ //所以如下程序用if和else分别写入0和1;而当从DS18B20读数据时,uchar i,j,m,n; //读0和读1的时序根本一样,所以读0和读1的程序合二为一,不用分别写出bit dat;for(i=0;i<8;i++){ds=0;j++;j++;ds=1;j++;j++;dat=ds;j=8;while(j>0)j--;m=dat;//把一位数据赋给一个字节,且从最低位开始读数n=(m<<7)|(n>>1);}return n; //必须将n值返回去,以赋给a和b}void get_temp(){uchar a,b;init_ds();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempreadbyte();b=tempreadbyte();temp=b;temp<<=8;temp=temp|a;f_temp=temp*0.0625*10+0.5;//保存一位小数,且最低位四舍五入temp=f_temp;//return temp;}void wr_data(date) {rs=1;rw=0;en=0;P0=date;delay(3);en=1;delay(3);en=0;}void wr_(uchar ) {rs=0;rw=0;en=0;P0=;delay(3);en=1;delay(3);en=0;}void lcd_init() {psb=1;wr_(0x30);delay(3);wr_(0x0c);delay(3);wr_(0x06);delay(3);// wr_(0x01);// delay(3);}void lcd_pos(uchar X,uchar Y){if(X==0)X=0x80;else if(X==1)X=0x90;else if(X==2)X=0x88;else if(X==3)X=0x98;wr_(X+Y);}void display()//显示第一行为 current temp: { //第二行为当前温度:uchar i; //第三行为 xxx摄氏度table[0]=temp/100+'0';table[1]=temp/10%10+'0';table[2]='.';table[3]=temp%10+'0';lcd_pos(2,2);for(i=0;i<4;i++)wr_data(table[i]);lcd_pos(2,4);i=0;while(table2[i]!='\0'){wr_data(table2[i]);i++;}lcd_pos(0,0);i=0;while(table0[i]!='\0'){wr_data(table0[i]);i++;}lcd_pos(1,0);i=0;while(table1[i]!='\0'){wr_data(table1[i]);i++;}}void main(){lcd_init();while(1){tempchange();get_temp();display();}}。
基于12864及18B20的温度液晶显示#include <reg52.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <math.h>/*-------------------Define the register commandcode----------------------*/#define Disp_On 0x3f#define Disp_Off 0x3e#define Col_Add 0x40#define Page_Add 0xb8#define Start_Line 0xc0#define Lcd_Bus P0#define uchar unsigned char#define uint unsigned intuchar t1,t2,t3,ser;sbit DS=P2^2; /*----------与单片机的单总线接口--------*/uint temp; /*----------可变温度值------------------*/uchar flag1; /*----------温度正负标志----------------*/sbit Mcs=P3^7;sbit Scs=P2^4;sbit Enable=P3^4;sbit Di=P3^5;sbit RW=P3^6;sbit Lcd_Rst=P2^1;sbit DIO=P2^5;sbit DU=P2^6;sbit WE=P2^7;char code ezk[]={0xF8,0xFC,0x04,0xC4,0x24,0xFC,0xF8,0x00, // -0-0x07,0x0F,0x09,0x08,0x08,0x0F,0x07,0x00,0x00,0x10,0x18,0xFC,0xFC,0x00,0x00,0x00, // -1-0x00,0x08,0x08,0x0F,0x0F,0x08,0x08,0x00,0x08,0x0C,0x84,0xC4,0x64,0x3C,0x18,0x00, // -2-0x0E,0x0F,0x09,0x08,0x08,0x0C,0x0C,0x00,0x08,0x0C,0x44,0x44,0x44,0xFC,0xB8,0x00, // -3-0x04,0x0C,0x08,0x08,0x08,0x0F,0x07,0x00,0xC0,0xE0,0xB0,0x98,0xFC,0xFC,0x80,0x00, // -4-0x00,0x00,0x00,0x08,0x0F,0x0F,0x08,0x00,0x7C,0x7C,0x44,0x44,0xC4,0xC4,0x84,0x00, // -5-0x04,0x0C,0x08,0x08,0x08,0x0F,0x07,0x00,0xF0,0xF8,0x4C,0x44,0x44,0xC0,0x80,0x00, // -6-0x07,0x0F,0x08,0x08,0x08,0x0F,0x07,0x00,0x0C,0x0C,0x04,0x84,0xC4,0x7C,0x3C,0x00, // -7-0x00,0x00,0x0F,0x0F,0x00,0x00,0x00,0x00,0xB8,0xFC,0x44,0x44,0x44,0xFC,0xB8,0x00, // -8-0x07,0x0F,0x08,0x08,0x08,0x0F,0x07,0x00,0x38,0x7C,0x44,0x44,0x44,0xFC,0xF8,0x00, // -9-0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00,/*------- ----0x30,0x30-----':'已改为'.'-----*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00,0x00,};uchar code FirstPage[] ={0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x30,0x10,0x80,0x30,0x10,0x80 ,0xC8,0xB0,0xB0,0x76,0xC8,0xE8,0x76,0x99,0x7C,0x7E,0x9F,0x79,0x7C,0x7E,0x79,0x3E ,0x1C,0x09,0x37,0x13,0x09,0x0E,0x01,0x01,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0x20,0x00,0x23,0x32,0x98,0x44,0x63,0x33,0x9C,0x23,0x75,0xCC ,0x03,0x25,0x34,0x1B,0x04,0x26,0x33,0x04,0x82,0x03,0x30,0x03,0x80,0x80,0x40,0x08 ,0x98,0x80,0x40,0x40,0x00,0x80,0x40,0xC0,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0x00 ,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x20,0x60,0xC0,0x02,0x12,0x98,0xC0,0xCC,0x85,0x20,0xEC,0xF0,0xF9,0xE4,0xFC ,0xFC,0xFD,0xFE,0xFC,0xFC,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFC,0xFE,0xFE,0xF0,0xF8,0xF0,0xF0,0x20,0x00 ,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x0C,0x06,0x06,0x60,0x08,0x4D,0xED,0xF8,0xFE,0xFF,0xFF,0x1F,0x9F,0x9F,0x0F,0x67 ,0x63,0x01,0x00,0x48,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xE7,0xF3 ,0x81,0xC9,0xED,0xE7,0xF3,0xE2,0xE0,0x31,0x69,0x2D,0xDF,0x8F,0xD7,0x93,0x03,0x0F ,0x0F,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x03,0x08,0x08,0x60,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x79,0xB6,0xB8,0x78,0x96,0x78 ,0x78,0x33,0x78,0x38,0x18,0x68,0x99,0xBB,0x1F,0x3F,0x1F,0x0F,0x3F,0x1F,0x0F,0x0F ,0x07,0x07,0x03,0x01,0x06,0x05,0x01,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x03,0x01,0x00,0x1B,0x01,0x00,0x06,0x00,0x00,0x06,0x00,0x04,0x04,0x01,0x00 ,0x02,0x03,0x00,0x04,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00};uchar code SecondPage[] = // 数据表64*64{0xFF,0x03,0x01,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFF,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01 ,0xFF,0xFF,0xFF,0x0F,0x03,0x01,0x39,0x19,0x39,0x39,0x39,0x19,0x19,0x09,0x1B,0xFF ,0xC1,0x81,0x8F,0x9F,0x9F,0x9F,0x9F,0x01,0x01,0x1F,0x9F,0x9F,0x9F,0x9F,0x81,0xC1 ,0xF3,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00 ,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xC0,0x60,0xF8,0xFF ,0x03,0x01,0x48,0xCC,0xCC,0xCC,0xCC,0x00,0x00,0x48,0xCC,0xCC,0xCC,0x48,0x01,0x01 ,0xCF,0xFF,0xFF,0xC0,0x80,0x80,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F ,0x9F,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFC ,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x78,0x78,0x78,0x78,0x78,0x78,0x00,0x00,0xC0,0xFF ,0x0F,0x06,0x44,0xE4,0xE4,0xE4,0xE4,0x00,0x00,0xE4,0xE4,0xE4,0xE4,0xE4,0x06,0x0E ,0xFF,0xFF,0xFF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF ,0xCF,0xC0,0xC0,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF ,0xFF,0xFF,0xFF,0xC0,0xC0,0xE0,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF ,0xC6,0xC0,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0xC4 ,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x01,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F ,0x3F,0x7D,0x78,0x78,0x38,0x38,0x28,0x00,0x00,0x20,0x38,0x38,0x38,0x19,0x01,0x83 ,0xE7,0xFF,,0xF9,0x09,0x09,0xF9,0xFF,0xDB,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x19,0x39 ,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFE ,0xFF,0xF1,0xE0,0xC0,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8F,0x1F,0x3F ,0x7F,0xFF,0xFF,0xDC,0x08,0x88,0x83,0x83,0x83,0x83,0x83,0x81,0x89,0x88,0x0C,0x8F ,0x8F,0x40,0x40,0xCF,0xFF,0x7B,0x33,0x13,0x93,0x93,0x81,0x81,0x91,0x91,0x18,0x3C ,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0xC0,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7 ,0xC7,0xC7,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0xC0 ,0xFC,0xFF,0xFF,0xC0,0x80,0x18,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x80,0xFF ,0xFF,0x00,0x00,0xFF,0xFF,0xFC,0x80,0x01,0x1F,0x8F,0x07,0x23,0xF3,0xF3,0xF8,0xF8 ,0xFF,0xFF,0xFF,0xFF,0xF0,0xE0,0xC0,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF ,0x8F,0xCF,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0xC0 ,0xDF,0xFF,0xFF,0xDF,0xCF,0xC7,0xE7,0xE7,0xE7,0xE3,0xE3,0xE7,0xE7,0xC7,0xC7,0xCF ,0xC7,0xE0,0xF0,0xFF,0xFF,0xEF,0xC0,0xE0,0xFE,0xFF,0xFE,0xFC,0xF8,0xF1,0xE3,0xC7 ,0xFF,0xFF};/*------------------延时子程序-----------------------------*/void delay(uint t){uint i,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}/*------------------写命令到LCD------------------------------*/void write_com(uchar cmdcode){Di=0;RW=0;Lcd_Bus=cmdcode;delay(0);Enable=1;delay(0);Enable=0;}/*-------------------写数据到LCD----------------------------*/void write_data(uchar Dispdata){Di=1;RW=0;Lcd_Bus=Dispdata;delay(0);Enable=1;delay(0);Enable=0;}/*------------------清除内存---------------*/void Clr_Scr(){uchar j,k;Mcs=1;Scs=1;write_com(Page_Add+0);write_com(Col_Add+0);for(k=0;k<8;k++){write_com(Page_Add+k);for(j=0;j<64;j++)write_data(0x00);}}/*---------------------指定位置显示8*16数字-----------------------*/ /* 使用全部ASCII字符x=(order-0x20)*16 *//*------------同时main中数字abcdef应分别加0x30--------------------*/void ez_disp(uchar pag,uchar col,uchar order){uchar i=0;uchar j=0;uint x;x=(order-0x30)*16;for(j=0;j<2;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);for(i=0;i<8;i++){write_data(ezk[x]);x++;}}}/*-----------------指定位置显示x*y的点阵图片-------------------*/ void Disp_Img(uchar pag,uchar col, uchar code *zk){uchar j=0,i=0;uchar k=0;for(j=0;j<8;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);for(i=0;i<64;i++)write_data(zk[64*j+i]);}}void dadian(uchar pag,uchar col,uchar x){uchar j=0,i=0;for(j=0;j<1;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);write_data(x);}}/*------------------初始化LCD屏--------------------------*/void init_lcd(){Lcd_Rst=0;delay(100);Lcd_Rst=1;delay(100);Mcs=1;Scs=1;delay(100);write_com(Disp_Off);write_com(Page_Add+0);write_com(Start_Line+0);write_com(Col_Add+0);write_com(Disp_On);}void Init_Com(void){TMOD = 0x20;PCON = 0x00;SCON = 0x50;TH1 = 0xFd;TL1 = 0xFd;TR1 = 1;}void dsreset(void) //send reset and initialization command {uint i;DS=0;i=103;while(i>0)i--;DS=1;i=4;while(i>0)i--;}bit tmpreadbit(void) //read a bit{uint i;bit dat;DS=0;i++; //i++ for delayDS=1;i++;i++;dat=DS;i=8;while(i>0)i--;return (dat);}uchar tmpread(void) //read a byte date{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里}return(dat);}void tmpwritebyte(uchar dat) //write a byte to ds18b20{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb) //write 1{DS=0;i++;i++;DS=1;i=8;while(i>0)i--;}else{DS=0; //write 0i=8;while(i>0)i--;DS=1;i++;i++;}}}void readrom() //read the serial{uchar sn1,sn2;dsreset();delay(1);tmpwritebyte(0x33);sn1=tmpread();sn2=tmpread();}void tmpchange(void) //DS18B20 begin change{dsreset();delay(1);tmpwritebyte(0xcc); // address all drivers on bustmpwritebyte(0x44); // initiates a single temperature conversion}uint tmp() //get the temperature{float tt;uchar a,b;dsreset();delay(1);tmpwritebyte(0xcc);tmpwritebyte(0xbe);a=tmpread();b=tmpread();temp=b;temp<<=8; //two byte compose a int variable temp=temp|a;tt=temp*0.0625;temp=tt*10+0.5;return temp;}/******************************************************************** ***************//*-----------------------主程序--------------------------------*/main(){uchar a=0;uchar b=0;DU=0;WE=0;Clr_Scr();init_lcd();Init_Com();dsreset();readrom();while(1){tmp();ser=temp/10;SBUF=ser;tmpchange();delay(200);DIO=0;t1=temp/100;t2=temp%100/10;t3=temp%10;Mcs=1,Scs=0;#include <reg52.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <math.h>/*-------------------Define the register commandcode----------------------*/#define Disp_On 0x3f#define Disp_Off 0x3e#define Col_Add 0x40#define Page_Add 0xb8#define Start_Line 0xc0#define Lcd_Bus P0#define uchar unsigned char#define uint unsigned intuchar t1,t2,t3,ser;sbit DS=P2^2; /*----------与单片机的单总线接口--------*/uint temp; /*----------可变温度值------------------*/uchar flag1; /*----------温度正负标志----------------*/sbit Mcs=P3^7;sbit Scs=P2^4;sbit Enable=P3^4;sbit Di=P3^5;sbit RW=P3^6;sbit Lcd_Rst=P2^1;sbit DIO=P2^5;sbit DU=P2^6;sbit WE=P2^7;char code ezk[]={0xF8,0xFC,0x04,0xC4,0x24,0xFC,0xF8,0x00, // -0-0x07,0x0F,0x09,0x08,0x08,0x0F,0x07,0x00,0x00,0x10,0x18,0xFC,0xFC,0x00,0x00,0x00, // -1-0x00,0x08,0x08,0x0F,0x0F,0x08,0x08,0x00,0x08,0x0C,0x84,0xC4,0x64,0x3C,0x18,0x00, // -2-0x0E,0x0F,0x09,0x08,0x08,0x0C,0x0C,0x00,0x08,0x0C,0x44,0x44,0x44,0xFC,0xB8,0x00, // -3-0x04,0x0C,0x08,0x08,0x08,0x0F,0x07,0x00,0xC0,0xE0,0xB0,0x98,0xFC,0xFC,0x80,0x00, // -4-0x00,0x00,0x00,0x08,0x0F,0x0F,0x08,0x00,0x7C,0x7C,0x44,0x44,0xC4,0xC4,0x84,0x00, // -5-0x04,0x0C,0x08,0x08,0x08,0x0F,0x07,0x00,0xF0,0xF8,0x4C,0x44,0x44,0xC0,0x80,0x00, // -6-0x07,0x0F,0x08,0x08,0x08,0x0F,0x07,0x00,0x0C,0x0C,0x04,0x84,0xC4,0x7C,0x3C,0x00, // -7-0x00,0x00,0x0F,0x0F,0x00,0x00,0x00,0x00,0xB8,0xFC,0x44,0x44,0x44,0xFC,0xB8,0x00, // -8-0x07,0x0F,0x08,0x08,0x08,0x0F,0x07,0x00,0x38,0x7C,0x44,0x44,0x44,0xFC,0xF8,0x00, // -9-0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00,/*------- ----0x30,0x30-----':'已改为'.'-----*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00,0x00,};uchar code FirstPage[] ={0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x30,0x10,0x80,0x30,0x10,0x80 ,0xC8,0xB0,0xB0,0x76,0xC8,0xE8,0x76,0x99,0x7C,0x7E,0x9F,0x79,0x7C,0x7E,0x79,0x3E ,0x1C,0x09,0x37,0x13,0x09,0x0E,0x01,0x01,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0x20,0x00,0x23,0x32,0x98,0x44,0x63,0x33,0x9C,0x23,0x75,0xCC ,0x03,0x25,0x34,0x1B,0x04,0x26,0x33,0x04,0x82,0x03,0x30,0x03,0x80,0x80,0x40,0x08 ,0x98,0x80,0x40,0x40,0x00,0x80,0x40,0xC0,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0x00 ,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00 ,0x00,0x20,0x60,0xC0,0x02,0x12,0x98,0xC0,0xCC,0x85,0x20,0xEC,0xF0,0xF9,0xE4,0xFC ,0xFC,0xFD,0xFE,0xFC,0xFC,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFC,0xFE,0xFE,0xF0,0xF8,0xF0,0xF0,0x20,0x00 ,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x0C,0x06,0x06,0x60,0x08,0x4D,0xED,0xF8,0xFE,0xFF,0xFF,0x1F,0x9F,0x9F,0x0F,0x67 ,0x63,0x01,0x00,0x48,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xE7,0xF3 ,0x81,0xC9,0xED,0xE7,0xF3,0xE2,0xE0,0x31,0x69,0x2D,0xDF,0x8F,0xD7,0x93,0x03,0x0F ,0x0F,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x03,0x08,0x08,0x60,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x79,0xB6,0xB8,0x78,0x96,0x78 ,0x78,0x33,0x78,0x38,0x18,0x68,0x99,0xBB,0x1F,0x3F,0x1F,0x0F,0x3F,0x1F,0x0F,0x0F0x03,0x01,0x06,0x05,0x01,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x03,0x01,0x00,0x1B,0x01,0x00,0x06,0x00,0x00,0x06,0x00,0x04,0x04,0x01,0x00 ,0x02,0x03,0x00,0x04,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00};uchar code SecondPage[] = // 数据表64*64{0xFF,0x03,0x01,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFF,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01 ,0xFF,0xFF,0xFF,0x0F,0x03,0x01,0x39,0x19,0x39,0x39,0x39,0x19,0x19,0x09,0x1B,0xFF ,0xC1,0x81,0x8F,0x9F,0x9F,0x9F,0x9F,0x01,0x01,0x1F,0x9F,0x9F,0x9F,0x9F,0x81,0xC1 ,0xF3,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00 ,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xC0,0x60,0xF8,0xFF0x48,0xCC,0xCC,0xCC,0xCC,0x00,0x00,0x48,0xCC,0xCC,0xCC,0x48,0x01,0x01 ,0xCF,0xFF,0xFF,0xC0,0x80,0x80,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F ,0x9F,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFC ,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x78,0x78,0x78,0x78,0x78,0x78,0x00,0x00,0xC0,0xFF ,0x0F,0x06,0x44,0xE4,0xE4,0xE4,0xE4,0x00,0x00,0xE4,0xE4,0xE4,0xE4,0xE4,0x06,0x0E ,0xFF,0xFF,0xFF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF ,0xCF,0xC0,0xC0,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF ,0xFF,0xFF,0xFF,0xC0,0xC0,0xE0,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF ,0xC6,0xC0,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0xC4 ,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x01,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F ,0x3F,0x7D,0x78,0x78,0x38,0x38,0x28,0x00,0x00,0x20,0x38,0x38,0x38,0x19,0x01,0x83 ,0xE7,0xFF,0xFF,0x0B,0x09,0x19,0x99,0x99,0x99,0x99,0x99,0x99,0x19,0x09,0x09,0xF9 ,0xF9,0x09,0x09,0xF9,0xFF,0xDB,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x19,0x39 ,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFE ,0xFF,0xF1,0xE0,0xC0,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8E,0x8F,0x1F,0x3F ,0x7F,0xFF,0xFF,0xDC,0x08,0x88,0x83,0x83,0x83,0x83,0x83,0x81,0x89,0x88,0x0C,0x8F ,0x8F,0x40,0x40,0xCF,0xFF,0x7B,0x33,0x13,0x93,0x93,0x81,0x81,0x91,0x91,0x18,0x3C ,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0xC0,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7,0xC7 ,0xC7,0xC7,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0xC0 ,0xFC,0xFF,0xFF,0xC0,0x80,0x18,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x80,0xFF ,0xFF,0x00,0x00,0xFF,0xFF,0xFC,0x80,0x01,0x1F,0x8F,0x07,0x23,0xF3,0xF3,0xF8,0xF8 ,0xFF,0xFF,0xFF,0xFF,0xF0,0xE0,0xC0,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xCF0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0xC0 ,0xDF,0xFF,0xFF,0xDF,0xCF,0xC7,0xE7,0xE7,0xE7,0xE3,0xE3,0xE7,0xE7,0xC7,0xC7,0xCF ,0xC7,0xE0,0xF0,0xFF,0xFF,0xEF,0xC0,0xE0,0xFE,0xFF,0xFE,0xFC,0xF8,0xF1,0xE3,0xC7 ,0xFF,0xFF};/*------------------延时子程序-----------------------------*/void delay(uint t){uint i,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}/*------------------写命令到LCD------------------------------*/void write_com(uchar cmdcode){Di=0;RW=0;Lcd_Bus=cmdcode;delay(0);Enable=1;delay(0);Enable=0;}/*-------------------写数据到LCD----------------------------*/void write_data(uchar Dispdata){Di=1;RW=0;Lcd_Bus=Dispdata;delay(0);Enable=1;delay(0);Enable=0;}/*------------------清除内存---------------*/void Clr_Scr(){uchar j,k;Mcs=1;Scs=1;write_com(Page_Add+0);write_com(Col_Add+0);for(k=0;k<8;k++){write_com(Page_Add+k);for(j=0;j<64;j++)write_data(0x00);}}/*---------------------指定位置显示8*16数字-----------------------*/ /* 使用全部ASCII字符x=(order-0x20)*16 *//*------------同时main中数字abcdef应分别加0x30--------------------*/void ez_disp(uchar pag,uchar col,uchar order){uchar i=0;uchar j=0;uint x;x=(order-0x30)*16;for(j=0;j<2;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);for(i=0;i<8;i++){write_data(ezk[x]);x++;}}}/*-----------------指定位置显示x*y的点阵图片-------------------*/ void Disp_Img(uchar pag,uchar col, uchar code *zk){uchar j=0,i=0;uchar k=0;for(j=0;j<8;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);for(i=0;i<64;i++)write_data(zk[64*j+i]);}}void dadian(uchar pag,uchar col,uchar x){uchar j=0,i=0;for(j=0;j<1;j++){write_com (Page_Add+pag+j);write_com (Col_Add+col);write_data(x);}}/*------------------初始化LCD屏--------------------------*/ void init_lcd(){Lcd_Rst=0;delay(100);Lcd_Rst=1;delay(100);Mcs=1;Scs=1;delay(100);write_com(Disp_Off);write_com(Page_Add+0);write_com(Start_Line+0);write_com(Col_Add+0);write_com(Disp_On);}void Init_Com(void){TMOD = 0x20;PCON = 0x00;SCON = 0x50;TH1 = 0xFd;TL1 = 0xFd;TR1 = 1;}void dsreset(void) //send reset and initialization command {uint i;DS=0;i=103;while(i>0)i--;DS=1;i=4;while(i>0)i--;}bit tmpreadbit(void) //read a bit{uint i;bit dat;DS=0;i++; //i++ for delayDS=1;i++;i++;dat=DS;i=8;while(i>0)i--;return (dat);}uchar tmpread(void) //read a byte date{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里}return(dat);}void tmpwritebyte(uchar dat) //write a byte to ds18b20 {uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb) //write 1{DS=0;i++;i++;DS=1;i=8;while(i>0)i--;}else{DS=0; //write 0i=8;while(i>0)i--;DS=1;i++;i++;}}}void readrom() //read the serial{uchar sn1,sn2;dsreset();delay(1);tmpwritebyte(0x33);sn1=tmpread();sn2=tmpread();}void tmpchange(void) //DS18B20 begin change{dsreset();delay(1);tmpwritebyte(0xcc); // address all drivers on bustmpwritebyte(0x44); // initiates a single temperature conversion}uint tmp() //get the temperature{float tt;uchar a,b;dsreset();delay(1);tmpwritebyte(0xcc);tmpwritebyte(0xbe);a=tmpread();b=tmpread();temp=b;temp<<=8; //two byte compose a int variable temp=temp|a;tt=temp*0.0625;temp=tt*10+0.5;return temp;}/******************************************************************** ***************//*-----------------------主程序--------------------------------*/main(){uchar a=0;uchar b=0;DU=0;WE=0;Clr_Scr();init_lcd();Init_Com();dsreset();readrom();while(1){tmp();ser=temp/10;SBUF=ser;tmpchange();delay(200);DIO=0;t1=temp/100;t2=temp%100/10;t3=temp%10;Mcs=1,Scs=0;Disp_Img(0,a,SecondPage);a++;if(a==64)a=0;delay(50);Mcs=0;Scs=1;Disp_Img(0,b,FirstPage); // b++;// if(b==64)// b=0;// delay(50);ez_disp(6,12,t1);ez_disp(6,20,t2);ez_disp(6,28,':');ez_disp(6,36,t3);dadian(6,44,0x04);dadian(6,45,0x0a);dadian(6,46,0x04);}}。
自己用51单片机写的读取多个18B20温度并显示在12864上的实验程序,测试通过#include<reg51.h>#define u8 unsigned char#define u16 unsigned intsbit dq=P3^3;u16 sbuf;float t;bit n;void send_string(u8 *p);float t1,t2;//存放2个18b20 的温度//18b20u8 code id1[]={0x28,0x05,0x9d,0x06,0x03,0x00,0x00,0x43};//第一18b20的序列号u8 code id2[]={11111111};//第二18b20的序列号void delay_18b20(u8 x){for(;x>0;x--);}void delay(u16 x){while(x--);}void send_0(){dq=0;delay_18b20(12);dq=1;delay_18b20(0);}void send_1(){dq=0;delay_18b20(0);dq=1;delay_18b20(8);}void send_cmd(u8 cmd){u8 i;for(i=0;i<8;i++){if(cmd&0x01==0x01){send_1();}else{send_0();}cmd>>=1;}}u8 receive_8bit(){u8 d;u8 i;for(i=0;i<8;i++){dq=0;dq=0;dq=0;dq=1;d>>=1;if(dq==1){d|=0x80;}delay_18b20(10);}return d;}u8 start(){u16 k;k=0;dq=0;delay_18b20(120);dq=1;while(dq==1){k++;if(k>=6000){return 1;}}k=0;while(dq==0){k++;if(k>=6000){return 2;}}return 0;}void send_id(u8 *id) //向DS18B20发送序列号{u8 i;for(i=0;i<8;i++){send_cmd(*id++);}}//读温度float read_ds18b20(u8 *id){u8 k;u8 tH,tL;u16 d;k=start();if(k!=0){send_string("错误");return 0;}send_cmd(0x55);//("匹配序列号");send_id(id);send_cmd(0x44);delay(5000);start();send_cmd(0x55);send_id(id);send_cmd(0xbe);tL=receive_8bit();tH=receive_8bit();d=tH;d<<=8;d|=tL;t=d*0.0625;return t;}//18b20void serial_int(){TMOD|=0x20;TH1=250;TL1=250;TR1=1;SM0=0;SM1=1;SM2=0;REN=1;}void end(){EA=1;ES=1;}void send_end() interrupt 4{if(RI==1){RI=0;sbuf=SBUF;if((sbuf=='1')|(sbuf=='2')){n=1;}}}void send_byte(u8 x) //底层驱动{SBUF=x;//启动发送while(TI==0);//等待数据发送完成TI=0;}void send_string(u8 *p){while(*p)send_byte(*p++);}void send_temp(float t){u16 tt;tt=(u16)(t*10);send_byte(tt/1000+48);send_byte(tt%1000/100+48);send_byte(tt%100/10+48);send_byte(tt%10+48);}//18b20void main(){serial_int();send_byte(12);send_string("串口初始化完成...\r\n");send_string("单总线访问两只DS18B20...\r\n");send_string("请按键盘 1 或2 分别读取两只DS18B20的温度...\r\n"); end();while(1){t1=read_ds18b20(id1);delay(5000);t2=read_ds18b20(id2);delay(5000);if(n==1){n=0;if(sbuf=='1'){send_string("\r\nt1=");send_temp(t1);send_string("度");}if(sbuf=='2'){send_string("\r\nt2=");send_temp(t2);send_string("度");}}}}。
用汇编写了那么多程序,马上就要用C了,所以做一个我近期在单片机上用汇编写代码的心得和一些自认为有用的程序。
主要是近期自学过的模块,比如protues中的AMPIRE128X64—LCD,DS18B20—温度测量模块,DS1302—时钟芯片。
好啦,废话也不多说了,注意我是按照我写程序的规范来写的,不过很容易理解,我也希望能帮助更多的单片机爱好者。
AMPIRE128X64一、Protues上LCD与单片机相连如图:二、打开keil新建一个AT89C51单片机的工程。
建立如下工程12864.A51用于存放驱动程序,方便调用。
main.a51用于存放主程序。
如果想知道这款LCD的详细信息可去百度文库搜索。
三、以下是12864.A51内的驱动程序,有详细解说。
PUBLICDISPLAY_BMP,DISPLAY_LCD,CLEAR_SCREEN,CHEC_BUSY,WRITE_IR,WRITE_DR,INIT_LCD,SELECT_SCREEN,SET_LINE;以上是声明外部调用语句,后面的子程序可被本工程的其它文件调用CODE_12864 SEGMENT CODE ;声明代码段LCD_RS BIT P2.2LCD_RW BIT P2.1LCD_E BIT P2.0LCD_CS1 BIT P2.4 ;低电平有效,左半屏LCD_CS2 BIT P2.3 ;低电平有效,右半屏ZIMO_NUM EQU 37H ;取字模的大小数;;;;;;;;;;;;;;;;;;;;;;;;;RSEG CODE_12864 ;;;;;;;;;;;;;;;;;;;;;;;;;检查忙等待CHEC_BUSY: MOV P0,#00H;;;;;;;;;;;;;;;;CLR LCD_RSSETB LCD_RWSETB LCD_E;详细资料里有这种命令;;;;;;;;;;;;;;;后面的就不细说了JB P0.7,$CLR LCD_ERET;;;;;;;;;;;;;;;;;;;;;;;;;向指令寄存器传送指令,传送参数为AWRITE_IR: LCALL CHEC_BUSYCLR LCD_RSCLR LCD_RWMOV P0,A ;P0作为数据口SETB LCD_ENOPNOPCLR LCD_ERET;;;;;;;;;;;;;;;;;;;;;;;;;向数据寄存器传送指令,传送参数为AWRITE_DR: LCALL CHEC_BUSYSETB LCD_RSCLR LCD_RWMOV P0,ASETB LCD_ENOPNOPCLR LCD_ERET;;;;;;;;;;;;;;;;;;;;;;;;;设置"页"LCD12864共8页,一页是8行点阵点SET_PAGE: ORL A,#0B8H ;页的首地址为0xB8LCALL WRITE_IRRET;;;;;;;;;;;;;;;;;;;;;;;;;设置显示的起始行SET_LINE: ORL A,#0C0H ;起始行地址为0xC0LCALL WRITE_IR;设置从哪行开始:共0--63;一般从0 行开始显示RET;;;;;;;;;;;;;;;;;;;;;;;;;设置显示的列SET_COLUMN: ANL A,#3FH ;列的最大值为64ORL A,#40H ;列的首地址为0x40LCALL WRITE_IR;规定显示的列的位置RET;;;;;;;;;;;;;;;;;;;;;;;;;显示开关函数:0x3E是关显示,0x3F是开显示SET_ON_OFF: ORL A,#3EH ;0011 111x,onoff只能为0或者1LCALL WRITE_IRRET;;;;;;;;;;;;;;;;;;;;;;;;;选择屏幕SELECT_SCREEN: CJNE A,#0,SELECTN0;0全屏CLR LCD_CS1CLR LCD_CS2LJMP SELECT_ENDSELECTN0: CJNE A,#1,SELECTN1;1左半屏CLR LCD_CS1SETB LCD_CS2LJMP SELECT_ENDSELECTN1: CJNE A,#2,SELECT_END;2右半屏CLR LCD_CS2SETB LCD_CS1SELECT_END: RET;;;;;;;;;;;;;;;;;;;;;;;;;清屏函数CLEAR_SCREEN: LCALL SELECT_SCREEN;0--全屏;1---左半屏;2---右半屏MOV R7,#0 ;控制页数0-7,共8页CLR_K1: MOV A,R7LCALL SET_PAGEMOV A,#0LCALL SET_COLUMNMOV R6,#0 ;控制列数0-63,共64列CLR A ;0CLR_K0: LCALL WRITE_DR;写入0,地址指针自加1INC R6CJNE R6,#64,CLR_K0INC R7CJNE R7,#8,CLR_K1RET;;;;;;;;;;;;;;;;;;;;;;;;;LCD的初始化INIT_LCD: LCALL CHEC_BUSYCLR A;选择全屏LCALL SELECT_SCREENCLR A;关闭显示LCALL SET_ON_OFFCLR A;选择全屏LCALL SELECT_SCREENMOV A,#01H;开启显示LCALL SET_ON_OFFCLR A;选择全屏LCALL SELECT_SCREENCLR A;清屏LCALL CLEAR_SCREENCLR A;开始行0LCALL SET_LINERET ;;;;;;;;;;;;;;;;;;;;;;;;;显示汉字子程序DISPLAY_LCD:;R5传入那半屏显示,R6传入页,R7传入列,DPTR传入字模表MOV A,R5LCALL SELECT_SCREEN;选择屏幕MOV A,R6LCALL SET_PAGE;选上半页MOV A,R7LCALL SET_COLUMN;控制列MOV R5,#0 ;控制16列的数据输出DISP_K0: MOV A,R5MOVC A,@A+DPTRLCALL WRITE_DR;选择查出的字模INC R5CLR CMOV A,R5SUBB A,ZIMO_NUMJNZ DISP_K0MOV A,R6INC ALCALL SET_PAGE;选下半页MOV A,R7LCALL SET_COLUMN;控制列MOV R5,#0 ;控制16列的数据输出DISP_K1: MOV A,R5ADD A,ZIMO_NUMMOVC A,@A+DPTRLCALL WRITE_DR;选择查出的字模INC R5CLR CMOV A,R5SUBB A,ZIMO_NUMJNZ DISP_K1RET ;;;;;;;;;;;;;;;;;;;;;;;;;显示BMP图片DISPLAY_BMP:;DPTR为图片取模表首址MOV R7,#0DISP_BMP_K2: MOV A,#1LCALL SELECT_SCREEN;选择左半屏MOV A,R7LCALL SET_PAGE;选择页CLR ALCALL SET_COLUMN;选择第0列MOV R6,#0DISP_BMP_K0: CLR A;MOVC A,@A+DPTRLCALL WRITE_DR;每隔一行取一次数组中的数据INC R6INC DPTRCJNE R6,#64,DISP_BMP_K0MOV A,#2LCALL SELECT_SCREEN;选择右半屏MOV A,R7LCALL SET_PAGE;选择页CLR ALCALL SET_COLUMN;选择第0列MOV R6,#0DISP_BMP_K1: CLR A;MOVC A,@A+DPTRLCALL WRITE_DR;每隔一行取一次数组中的数据INC R6INC DPTRCJNE R6,#64,DISP_BMP_K1INC R7CJNE R7,#8,DISP_BMP_K2RET ;;;;;;;;;;;;;;;;;;;;;;;;;END四、下面介绍一款LCD取模软件。
#ifndef __LCD12864_H#define __LCD12864_H//---包含头文件---//#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif//---如果使用画图模式定义这个---//#define LCD12864_PICTURE//---定义使用的IO口---//#define LCD12864_DATAPORT P1 //数据IO口sbit LCD12864_RS = P2^6; //(数据命令)寄存器选择输入sbit LCD12864_RW = P2^5; //液晶读/写控制sbit LCD12864_EN = P2^7; //液晶使能控制sbit LCD12864_PSB = P3^2; //串/并方式控制sbit LCD12864_RST = P3^4; //复位端//---声明全局函数---//void LCD12864_Delay1ms(uint c);uchar LCD12864_Busy(void);void LCD12864_WriteCmd(uchar cmd);void LCD12864_WriteData(uchar dat);void LCD12864_Init();void LCD12864_ClearScreen(void);void LCD12864_SetWindow(uchar x, uchar y);void LCD12864_DrowPic(uchar *a);void LCD12864_DrowPoint(uchar x, uchar y);#endif#ifndef __TEMP_H_#define __TEMP_H_#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif//--定义使用的IO口--//sbit DSPORT=P3^3;//--声明全局函数--//void Delay1ms(uint );uchar Ds18b20Init();void Ds18b20WriteByte(uchar com);uchar Ds18b20ReadByte();void Ds18b20ChangTemp();void Ds18b20ReadTempCom();int Ds18b20ReadTemp();#endif#include"lcd12864.h"/****************************************************************************** ** 函数名: LCD12864_Delay1ms* 函数功能: 延时1MS* 输入: c* 输出: 无******************************************************************************* /void LCD12864_Delay1ms(uint c)uchar a,b;for(; c>0; c--){for(b=199; b>0; b--){for(a=1; a>0; a--);}}}/****************************************************************************** ** 函数名: LCD12864_Busy* 函数功能: 检测LCD是否忙* 输入: 无* 输出: 1或0(1表示不忙,0表示忙)******************************************************************************* /uchar LCD12864_Busy(void){uchar i = 0;LCD12864_RS = 0; //选择命令LCD12864_RW = 1; //选择读取LCD12864_EN = 1;LCD12864_Delay1ms(1);while((LCD12864_DA TAPORT & 0x80) == 0x80) //检测读取到的值{i++;if(i > 100){LCD12864_EN = 0;return 0; //超过等待时间返回0表示失败}}LCD12864_EN = 0;return 1;}/****************************************************************************** ** 函数名: LCD12864_WriteCmd* 函数功能: 写命令* 输入: cmd* 输出: 无******************************************************************************* /void LCD12864_WriteCmd(uchar cmd){uchar i;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return; //超过等待退出}}LCD12864_RS = 0; //选择命令LCD12864_RW = 0; //选择写入LCD12864_EN = 0; //初始化使能端LCD12864_DATAPORT = cmd; //放置数据LCD12864_EN = 1; //写时序LCD12864_Delay1ms(1);LCD12864_EN = 0;}/****************************************************************************** ** 函数名: LCD12864_WriteData* 函数功能: 写数据* 输入: dat* 输出: 无******************************************************************************* /void LCD12864_WriteData(uchar dat){uchar i;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return; //超过等待退出}}LCD12864_RS = 1; //选择数据LCD12864_RW = 0; //选择写入LCD12864_EN = 0; //初始化使能端LCD12864_DATAPORT = dat; //放置数据LCD12864_EN = 1; //写时序LCD12864_Delay1ms(1);LCD12864_EN = 0;}/****************************************************************************** ** 函数名: LCD12864_ReadData* 函数功能: 读取数据* 输入: 无* 输出: 读取到的8位数据******************************************************************************* /#ifdef LCD12864_PICTUREuchar LCD12864_ReadData(void){uchar i, readValue;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return 0; //超过等待退出}}LCD12864_RS = 1; //选择命令LCD12864_RW = 1;LCD12864_EN = 0;LCD12864_Delay1ms(1); //等待LCD12864_EN = 1;LCD12864_Delay1ms(1);readValue = LCD12864_DA TAPORT;LCD12864_EN = 0;return readValue;}#endif/****************************************************************************** ** 函数名: LCD12864_Init* 函数功能: 初始化LCD12864* 输入: 无* 输出: 无******************************************************************************* /void LCD12864_Init(){LCD12864_PSB = 1; //选择并行输入LCD12864_RST = 1; //复位LCD12864_WriteCmd(0x30); //选择基本指令操作LCD12864_WriteCmd(0x0c); //显示开,关光标LCD12864_WriteCmd(0x01); //清除LCD12864的显示内容}/****************************************************************************** ** 函数名: LCD12864_ClearScreen* 函数功能: 在画图模式下,LCD12864的01H命令不能清屏,所以要自己写一* * 屏函数* 输入: 无* 输出: 无******************************************************************************* /#ifdef LCD12864_PICTUREvoid LCD12864_ClearScreen(void){uchar i,j;LCD12864_WriteCmd(0x34); //开启拓展指令集for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次{LCD12864_WriteCmd(0x80+i); //先写入纵坐标Y的值LCD12864_WriteCmd(0x80); //再写入横坐标X的值for(j=0;j<32;j++) //横坐标有16位,每位写入两个字节的的数据,也{ //就写入32次以为当写入两个字节之后横坐标会自LCD12864_WriteData(0x00); //动加1,所以就不用再次写入地址了。
#include<reg52.h>#include<intrins.h> //包含_nop_()函数定义的头文件#define uint unsigned int#define uchar unsigned charsbit ds=P3^3; //DS18B20接口uint temp;float f_temp;//12864端口定义sbit LCD12864_RS=P2^0;sbit LCD12864_WR=P2^1;sbit LCD12864_E=P2^2;sbit LCD12864_PSB=P2^3;sbit LCD12864_busy=P0^7;#define LCD12864_dat P0void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--) ;}//****************************************//以下为12864液晶显示部分子程序模块//****************************************//函数定义void wr_d_lcd(uchar content);void wr_i_lcd(uchar content);void clrram_lcd (void);void init_lcd(void);void busy_lcd(void);void rev_row_lcd(uchar row);void rev_co_lcd(uchar row,uchar col,uchar mode);void clr_lcd(void);void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);void wr_row_lcd(uchar row,char *p);//延时子程序模块//**********************************************void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<80;i++) //1ms延时.{;}}}//***********************************//填充液晶DDRAM全为空格//**********************************void clrram_lcd (void){wr_i_lcd(0x30);wr_i_lcd(0x01);}//***********************************//对液晶写数据//content为要写入的数据//***********************************//*********************写数据函数void wr_d_lcd(uchar content){busy_lcd();LCD12864_RS=1;LCD12864_WR=0;LCD12864_dat=content;LCD12864_E=1;;LCD12864_E=0;}//********************************//对液晶写指令//content为要写入的指令代码//*****************************//**************************写命令函数void wr_i_lcd(uchar content){busy_lcd();LCD12864_RS=0;LCD12864_WR=0;LCD12864_dat=content;LCD12864_E=1;;LCD12864_E=0;}//********************************//液晶检测忙状态//在写入之前必须执行//********************************void busy_lcd(void){LCD12864_dat=0xff;LCD12864_RS=0;LCD12864_WR=1;LCD12864_E =1;while(LCD12864_busy==1);LCD12864_E=0;}//**********************************//液晶初始化//**********************************void init_lcd(void){wr_i_lcd(0x30);wr_i_lcd(0x06); /*光标的移动方向*/wr_i_lcd(0x0c); /*开显示,关游标*/wr_i_lcd(0x01); //清屏}//********************************//指定要显示字符的坐标//*******************************void LCD12864_pos(unsigned char y, unsigned char x){if(y==1)wr_i_lcd(0x80|x);if(y==2)wr_i_lcd(0x90|x);if(y==3)wr_i_lcd((0x80|x)+8);if(y==4)wr_i_lcd((0x90|x)+8);}//**********************************//液晶显示字符串程序//**********************************void LCD12864print(uchar *str){while(*str!='\0'){wr_d_lcd(*str);str++;}}//**********************************//液晶显示位置、字符串、显示间隔时间//**********************************//LCD12864_display1(1,3,500,"中国CHN")//意思为在第1行第4列显示"中国CHN",每个字显示间隔为500ms LCD12864_display1(unsigned char y, unsigned char x,uint t, uchar *str) {LCD12864_pos(y,x);while(*str!='\0'){wr_d_lcd(*str);str++;delay(t);}}LCD12864_display2(unsigned char y, unsigned char x,uchar n){LCD12864_pos(y,x);wr_d_lcd(0x30+n);}//此函数是显示变量的,比如要在第1行第2列显示一个不断变化的变量a代表的值,//就用LCD12864_display2(1,2,a);//****************************************//以上为12864液晶显示部分子程序模块//****************************************/*****************************************************以下为DS18B20模块语句***************************************************//*void delay(uint z)//延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}*/void dsreset(void) //18B20复位,初始化函数{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit tempreadbit(void) //读1位函数{uint i;bit dat;ds=0;i++; //i++ 起延时作用ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return (dat);}uchar tempread(void) //读1个字节{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DA T里}return(dat);}void tempwritebyte(uchar dat) //向18B20写一个字节数据{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb) //写1{ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0; //写0i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) //DS18B20 开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc); // 写跳过读ROM指令tempwritebyte(0x44); // 写温度转换指令}uint get_temp() //读取寄存器中存储的温度数据{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread(); //读低8位b=tempread(); //读高8位temp=b;temp<<=8; //两个字节组合为1个字temp=temp|a;f_temp=temp*0.0625; //温度在寄存器中为12位分辨率位0.0625°temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入f_temp=f_temp+0.05;return temp; //temp是整型}/*****************************************************以上为DS18B20模块语句***************************************************/void dis_temp(uint t){uchar shi,ge,xiao;shi=t/100;//十位ge=t%100/10;//个位xiao=t%100%10;//小数位LCD12864_display1(1,0,0,"当前温度为:");LCD12864_display1(3,0,0,"摄氏度");LCD12864_display2(3,3,shi);LCD12864_display2(3,4,ge);LCD12864_display1(3,5,0,".");LCD12864_display2(3,6,xiao);LCD12864_display1(3,7,0,"C");}main(){init_lcd();while(1){tempchange();dis_temp(get_temp());}}。
/******************************************************************************* ******************************************************************************** *******///程序说明:本程序为12864(st7920)驱动程序,只实现了最简单的显示功能//端口设置:RS、RW、EN分别为P0口的0、1、2,数据口为P2口用取模软件取的图形或汉字必须是逐行取的,因为本函数是在液晶上逐行打点的/******************************************************************************* ******************************************************************************** ******/#include<reg51.h>#include<intrins.h> //内含-NOP-函数#include<stdlib.h> //内含rand()函数#define uchar unsigned char#define uint unsigned int//**********宏定义所需指令#define BASIC_SET 0x30#define EXTEND_SET 0x34#define DRAW_ON 0x36#define DRAW_OFF 0x34//*************端口定义sbit LCD_RS = P2^5;sbit LCD_RW = P2^6;sbit LCD_EN = P2^7;sbit DS=P3^3; //定义温度DS18B20接口,详情见原理图//************变量定义uchar code t0[]="温度 . ℃";uchar code t1[]="0123456789"; //利用一个温度表解决温度显示乱码uchar i,k,a,b;//****************短延时void delay(uint k){uint i;uchar j;for(i = 0; i < k ;i ++)for(j = 0; j < 10 ;j ++);}//***********12864写指令函数void write_com(uchar cmd){LCD_RS = 0;LCD_RW = 0;P0 = cmd;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0;}//********12864写数据函数void write_dat(uchar dat){LCD_RS = 1;LCD_RW = 0;P0 = dat;delay(5);LCD_EN = 1;delay(5);LCD_EN = 0;}//****************从LCD中读数据uchar read_dat(void){uchar temp;P0 = 0XFF; //释放数据线LCD_RS = 1; //数据LCD_RW = 1; // 读模式LCD_EN = 1; //E为高电平进行读数据或指令delay(1);temp = P0;LCD_EN = 0;return temp;}//******************************************************** //设置光标(地址)函数//参数说明:x---为行号,y为列号//********************************************************void set_cursor(unsigned char x, unsigned char y){unsigned char i;switch(x) //确定行号{case 0x00: i=0x80; break; //第一行case 0x01: i=0x90; break; //第二行case 0x02: i=0x88; break; //第三行case 0x03: i=0x98; break; //第四行default : break;}i = y+i; //确定列号write_com(i);}//********************************************************//显示字符函数//********************************************************void display_char(unsigned char Alphabet){write_dat(Alphabet); //写入需要显示字符的显示码}//********************************************************//指定位置显示字符串函数//参数说明:x为行号,y为列号//********************************************************void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet) {unsigned char i=0;set_cursor(x,y); //设置显示的起始地址while(Alphabet[i]!='\0'){write_dat(Alphabet[i]); //写入需要显示字符的显示码i++;}}//***************************************************************************以下为GDRAM绘图部分************************************************************************////*********************绘图显示的清屏函数(因清屏指令在画图时不能用)------------------------------------------------------------------------------注意!!!!!!!void gui_clear(){uchar i , j , k;write_com(EXTEND_SET);//扩展指令集,8位数据传输write_com(DRAW_OFF);//绘图显示关闭for(i = 0; i < 2; i ++)//分上下两屏写{for(j = 0; j < 32; j ++){write_com(0x80 + j);//写y坐标delay(1);if(i == 0) //写x坐标{write_com(0x80);delay(1);}else //写下半屏{write_com(0x88);delay(1);}for(k = 0; k < 16; k ++)//写一整行数据{write_dat(0x00);//写高字节write_dat(0x00);//写低字节delay(1);}}}write_com(DRAW_ON);//打开绘图显示write_com(BASIC_SET);//打开基本指令集}//***********(给定坐标并打点的)任意位置打点函数void lcd_set_dot(uchar x,uchar y){uchar x_byte,x_bit;//确定在坐标的那一字节哪一位uchar y_ping , y_bit;//确定在坐标的哪一屏哪一行uchar tmph , tmpl;//定义两个临时变量,用于存放读出来的数据write_com(EXTEND_SET);//扩展指令集write_com(DRAW_OFF);//绘图显示关闭x_byte = x / 16;//算出在哪一字节,注意一个地址是16位的x_bit = x % 16;//& 0x0f;//算出在哪一位y_ping = y / 32;//确定在上半屏还是下半屏,0代表上半屏,1代表下半屏y_bit = y % 32;//& 0x1f;//确定在第几行write_com(0X80 + y_bit);//先写垂直地址(最高位必须)write_com(0x80 + x_byte + 8 * y_ping);//水平坐标,下半屏坐标起始地址为0x88,(+8*y_ping)就是用来确定上半屏还是下半屏read_dat();//预读取数据tmph = read_dat();//读取当前显示高8位数据tmpl = read_dat();//读取当前显示低8位数据delay(1);write_com(0x80 + y_bit);//读操作会改变AC,所以重新设置一下write_com(0x80 + x_byte + 8 * y_ping);delay(1);if(x_bit < 8){write_dat(tmph | (0x01 << (7 - x_bit)));//写高字节,因为坐标是从左向右的,GDRAM高位在昨,低位在右write_dat(tmpl);//原低位数据送回}else{write_dat(tmph);//原高位数据送回write_dat(tmpl | (0x01 << (15 - x_bit)));}write_com(DRAW_ON); //打开绘图显示write_com(BASIC_SET);//回到基本指令集}//************画水平线函数**********************************////x0、x1为起始点和终点的水平坐标,y为垂直坐标***************////**********************************************************// void gui_hline(uchar x0, uchar x1, uchar y){uchar bak;//用于对两个数互换的中间变量,使x1为大值if(x0 > x1){bak = x1;x1 = x0;x0 = bak;}do{lcd_set_dot(x0 , y);//从左到右逐点显示x0 ++;}while(x1 >= x0);}//***********画竖直线函数***********************************// //x为起始点和终点的水平坐标,y0、y1为垂直坐标***************// //**********************************************************// void gui_rline(uchar x, uchar y0, uchar y1){uchar bak;//用于对两个数互换的中间变量,使y1为大值if(y0 > y1){bak = y1;y1 = y0;y0 = bak;}do{lcd_set_dot(x , y0);//从上到下逐点显示y0 ++;}while(y1 >= y0);}//*********任意两点间画直线*********************************// //x0、y0为起始点坐标,x1、y1为终点坐标**********************// //**********************************************************//void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1){char dx;//直线x轴差值char dy;//直线y轴差值char dx_sym;//x轴增长方向,为-1时减值方向,为1时增值方向char dy_sym;//y轴增长方向,为-1时减值方向,为1时增值方向char dx_x2;//dx*2值变量,用于加快运算速度char dy_x2;//dy*2值变量,用于加快运算速度char di; //决策变量if(x0 == x1)//判断是否为垂直线{gui_rline(x0 , y0 , y1);//画垂直线return;}if(y0 == y1)//判断是否为水平线{gui_hline(x0 , x1 , y0);//画水平线return;}dx = x1 - x0;//求取两点之间的差值dy = y1 - y0;//****判断增长方向,或是否为水平线、垂直线、点*//if(dx > 0)//判断x轴方向dx_sym = 1;else{if(dx < 0)dx_sym = -1;else{gui_rline(x0 , y0 , y1);return;}}if(dy > 0)//判断y轴方向dy_sym = 1;else{if(dy < 0)dy_sym = -1;else{gui_hline(x0 , x1 , y0);return;}}/*将dx、dy取绝对值***********/dx = dx_sym * dx;dy = dy_sym * dy;/****计算2倍的dx、dy值*******/dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点对应dy_x2 = dy * 1;/***使用bresenham法进行画直线***/if(dx >= dy)//对于dx>=dy,使用x轴为基准{di = dy_x2 - dx;while(x0 != x1){lcd_set_dot(x0,y0);x0 +=dx_sym;if(di < 0)di += dy_x2;//计算出下一步的决策值else{di += dy_x2 - dx_x2;y0 += dy_sym;}}lcd_set_dot(x0, y0);//显示最后一点}else //对于dx<dy使用y轴为基准{di = dx_x2 - dy;while(y0 != y1){lcd_set_dot(x0, y0);y0 += dy_sym;if(di < 0)di += dx_x2;else{di += dx_x2 - dy_x2;x0 += dx_sym;}}lcd_set_dot(x0, y0);//显示最后一点}}//***************************************************************************以上为自定义字库部分**************************************************************////****************12864初始化函数void lcd_init(){write_com(0x30);//基本指令操作,8位并口delay(1);write_com(0x06);//设置为游标右移,DDRAM地址加一,画面不动delay(1);write_com(0x0c);//显示开,关光标delay(1);write_com(0x01);//清除lcd显示内容delay(1);}//5ms延时void Delay5Ms(void){unsigned int TempCyc = 5552;while(TempCyc--);}//400ms延时void Delay400Ms(void){unsigned char TempCycA = 5;unsigned int TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);};}/*************DS18B20温度读取模块*************/void tmpDelay(int num)//延时函数{while(num--) ;}void Init_DS18B20()//初始化ds1820{unsigned char x=0;DS = 1; //DS复位tmpDelay(8); //稍做延时DS = 0; //单片机将DS拉低tmpDelay(80); //精确延时大于 480usDS = 1; //拉高总线tmpDelay(14);x=DS; //稍做延时后如果x=0则初始化成功 x=1则初始化失败tmpDelay(20);}unsigned char ReadOneChar()//读一个字节{unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DS = 0; // 给脉冲信号dat>>=1;DS = 1; // 给脉冲信号if(DS)dat|=0x80;tmpDelay(4);}return(dat);}void WriteOneChar(unsigned char dat)//写一个字节{unsigned char i=0;for (i=8; i>0; i--){DS = 0;DS = dat&0x01;tmpDelay(5);DS = 1;dat>>=1;}}unsigned int Readtemp()//读取温度{unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器a=ReadOneChar(); //连续读两个字节数据 //读低8位b=ReadOneChar(); //读高8位t=b;t<<=8;t=t|a; //两字节合成一个整型变量。
实用文案基于单片机STC89C51的温度显示系统的设计引言随着电子技术,特别是随大规模集成电路的产生而出现的微型计算机技术的飞速发展,人类生活发生了根本性的改变。
如果说微型计算机的出现使现代科学研究得到了质的飞跃,那么可以毫不夸张地说,单片机技术的出现则是给现代工业测控领域带来了一次新的技术革命。
目前,单片机以其体积小、重量轻、抗干扰能力强、对环境要求不高、高可靠性、高性能价格比、开发较为容易,在工业控制系统、数据采集系统、智能化仪器仪表、办公自动化等诸多领域得到极为广泛的应用,并已走人家庭,从洗衣机、微波炉到音响、汽车,到处都可见到单片机的踪影。
因此,单片机技术开发和应用水平已逐步成为一个国家工业发展水平的标志之一。
本课题研究的内容就是以单片机为主要控制元件,通过温度传感器DS18B20实现对温度的测量,并通过LCD12864直接显示所测温度。
1、设计任务用温度传感器DS18b20检测空气中的温度,STC89C51采集DS18B20的数据并通过LCD12864显示实时温度。
2、系统硬件设计2.1 系统方框图见图2-1.图3-1 系统方框图2.2 各模块方案的选择2.2.1 温度检测方案选择方案一:采用热电偶或热敏电阻作感温元件,但热电偶需冷端补偿,电路设计复杂,热敏电阻虽然精度较高,但需要标准稳定电阻匹配才能使用,而且重复性、可靠性都比较差。
方案二:采用集成温度传感器 DS18B20 。
该传感器结构简单,不需外接电路,数据传输采用one-wire。
总线,可用一根 I/O数据线即供电又传输数据,在-10 ℃ --+85℃范围内精度为±0.5℃,分辨率较高,重复性和可靠性好。
故采用方案二。
2.2.2 显示模块方案的选择方案一:采用数码管显示。
数码管亮度高、体积小、重量轻,但其显示信息简单、有限,在本题目中应用受到很大的限制。
方案二:采用液晶显示。
液晶显示功耗低,轻便防震。
采用液晶显示界面友好清晰,操作方便,显示信息丰富。
//*******************资源配置***********************////******计数器0用于超声波记录接收端高电平时长*******////******计数器1用于记录1s内外部脉冲数目即转速*******////********定时器2用于精确定时,定时时间50ms*********////*****************P3^5用于脉冲计数*****************//#include <reg52.H>#include <intrins.h>//*************特殊引脚定义*****************//sbit RX = P1^0; //超声波接收端sbit TX = P1^1; //超声波触发端sbit RS = P2^6;//LCD数据/命令控制端sbit RW = P2^5;//读写控制端sbit EN = P2^7; //使能端sbit RES= P2^4; //复位端sbit PSB= P2^3; //并口/串口选择端sbit DQ = P3^7; //DS18B20数据端sbit BEEP=P1^5; //蜂鸣器#define DataPort P0 //MCU P0<------> LCM#define uchar unsigned char#define uint unsigned int//***********Function Definition*********************////****************函数声明***************************//void LCD_Write_number(uchar s);void Write_char(bit start, uchar ddata); //写入某坐标void Send_byte(uchar bbyte);void Lcd_init(void);//lcd初始化void Disp_img(uchar *img);//显示图片void LCD_Write_string(uchar X,uchar Y,uchar*s); //写入某字符串void LCD_set_xy( uchar x,uchar y );void Lcd_Mark3(void); //画面3void Lcd_Mark2(void); //画面2bit temp_flag; //判断DS18B20正常工作位DS18B20_init();//DS18B20初始化void delay(uint num);//DS18B20延时函数void Delaynms(uint di);//短延时void delayms(uint x);//1ms延时函数readonebyte(void);//读一个字节函数void writeonebyte(uchar dat); //写一个字节函数void gettemperture(void);//获取温度值void temperture_display(); //温度显示函数void tempconv(); //温度转换void beep(); //蜂鸣器响一声函数void timer_init(); //中断初始化函数(计数器0,计数器1,定时器2)void zhuansu_display(); //转速显示函数void speed_conv(); //速度转换函数void speed_display(); //速度显示函数void chaoshengbo_conv(void); //超声波转换//***************变量定义*****************//uchar data temp_dat[2]={0}; //temp[0],temp[1]用来存放温度的低、高8位uchar data DQdisp_buf[5]={0}; //温度显示缓冲区uchar zhuansu_buff[6]={0}; //转速显示缓存uchar speed_buff[6]={0};//速度显示缓存uchar temp_comp; //存放温度整数部分uchar DS18B20_OK,speed2;//DS18B20_OK=0复位正常uchar t2=0,T,L,H,WENDU; //t2代表timer2中断次数,T代表温度整数部分//H:温度高8位,L:温度低8位uint time=0; //超声波往返时间long S=0,num1=0,speed; //s表示超声波距离,num1表示发动机转速// speed表示车轮转速=》速度bit flag =0; //超声波中断溢出标志位uchar disbuff[4]={0}; //超声波数据显示缓存uchar code num[]={"09 :.-℃"};uchar code line1_data[]={"速度:km/h"};uchar code line2_data[]={"转速:r/min"};uchar code line3_data[]={"前方车距:m"};uchar code line4_data[]={"车内温度: "};uchar code line5_data[]={" #**欢迎使用**# "};uchar code line6_data[]={" 您的安全"};uchar code line7_data[]={" 是全家人"};uchar code line8_data[]={" 最大的幸福···"};uchar code picture[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x06,0x30,0x01,0xE0,0x00,0x00,0x2A,0x00,0x00,0xD8,0x00,0x00,0x00,0x00,0x 00,0x00,0x0F,0x7B,0x63,0xE0,0x00,0x00,0x22,0x00,0x01,0x24,0x00,0x00,0x00,0x00,0x0 0,0x00,0x0F,0xFB,0x63,0x07,0x34,0x00,0x14,0x00,0x01,0x04,0x00,0x00,0x00,0x00,0x0 0,0x00,0x0D,0xDB,0x63,0x01,0xBC,0x00,0x08,0x00,0x00,0x88,0x00,0x00,0x00,0x00,0x0x00,0x0C,0x1B,0x63,0x07,0xB0,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x0 0,0x00,0x0C,0x1B,0x63,0xED,0xB0,0xDB,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x 00,0x00,0x0C,0x19,0xE1,0xE7,0xB0,0xDB,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x 00,0x00,0x0C,0x19,0xE1,0xE7,0xB0,0xDB,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x 00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x0A,0x80,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x0A,0x00,0x00,0xFF,0xF8,0xE0,0x05,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x06,0xC0,0x15,0x00,0x1F,0xFF,0xFF,0xC0,0x02,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x09,0x20,0x11,0x00,0xFB,0xFF,0xE1,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x08,0x20,0x0A,0x03,0x9F,0x00,0x9E,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x04,0x40,0x04,0x0E,0x70,0x00,0x81,0xC7,0x80,0x01,0x40,0x00,0x00,0x00,0x0 0,0x00,0x02,0x80,0x00,0x1D,0x80,0x00,0xE0,0x61,0xE0,0x02,0xA0,0x00,0x00,0x00,0x 00,0x00,0x01,0x00,0x00,0x77,0x9F,0xFC,0xF0,0x18,0xF8,0x02,0x20,0x00,0x00,0x00,0x00x00,0x00,0x00,0x01,0xDF,0x00,0x00,0xF3,0x0C,0x3C,0x01,0x40,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x03,0x9E,0x00,0x00,0xF8,0x06,0x1E,0x00,0x80,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x07,0x0E,0x30,0x01,0xFC,0x7F,0x07,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x07,0x0E,0x30,0x01,0xFC,0x7F,0x07,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xC0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x0F,0xFD,0xFF,0xFF,0xFF,0xFF,0xFC,0x01,0xF0,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x3F,0x81,0xFF,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0xFE,0xF0,0x00,0x00,0x01,0x00,0x00,0xC0,0x1C,0x00,0x00,0x00,0x00,0x0 0,0x00,0x03,0xC0,0x07,0x80,0x00,0x03,0xE0,0x07,0x00,0x1C,0x00,0x00,0x00,0x00,0x0 0,0x00,0x03,0x80,0x03,0x40,0x00,0x03,0xE0,0x0C,0x00,0x0E,0x00,0x00,0x00,0x00,0x0 0,0x00,0x07,0x00,0x00,0xC0,0x00,0x00,0x20,0x18,0x00,0x07,0x00,0x00,0x00,0x00,0x0 0,0x00,0x09,0x01,0x80,0x60,0x00,0x00,0x20,0x73,0x9F,0x03,0x80,0x00,0x00,0x00,0x0 0,0x00,0x1E,0x0F,0xF2,0x20,0x00,0x00,0x20,0x67,0xFF,0xC1,0xC0,0x00,0x00,0x00,0x0 0,0x00,0x1E,0x1F,0xF9,0x30,0x00,0x00,0x20,0xEF,0xFF,0xE0,0xE0,0x00,0x00,0x00,0x00 ,0x00,0x38,0x3F,0xFC,0x90,0x00,0x00,0x20,0xCB,0xFF,0xF9,0xF0,0x00,0x00,0x00,0x00 ,0x00,0x7F,0x7F,0xFE,0x10,0x00,0x00,0x20,0xDB,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00, 0x00,0x6E,0xF9,0xBF,0x10,0x00,0x00,0x20,0xF7,0xED,0xFF,0xF0,0x00,0x00,0x00,0x00 ,0x00,0x7C,0xFC,0x3F,0x10,0x00,0x00,0x20,0x67,0xE1,0xFD,0xE0,0x00,0x00,0x00,0x0 0,0x00,0x7C,0xFC,0x3F,0x10,0x00,0x00,0x20,0x67,0xE1,0xFD,0xE0,0x00,0x00,0x00,0x0 0,0x00,0x38,0xFC,0x3F,0x18,0x00,0x00,0x20,0x87,0xE0,0xFD,0xC0,0x00,0x00,0x00,0x0 0,0x00,0x38,0xF1,0x8F,0x18,0x00,0x1F,0xE7,0x87,0x9C,0x7D,0xC0,0x00,0x00,0x00,0x0 0,0x00,0x1C,0xFE,0x1F,0x81,0xFF,0xFF,0xC0,0x0F,0xE0,0xFF,0x80,0x00,0x00,0x00,0x00, 0x00,0x0C,0xFC,0x3F,0x80,0x00,0x00,0x00,0x0F,0xE1,0xF8,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0xF9,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xFE,0x00,0x00,0x00,0x00,0x00, 0x00,0x03,0xF9,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00, 0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0 0,0x00,0x00,0x00,0x00,0x00,0x00};//************************************************////********** DS18B20 ********////************************************************////************************************************////************蜂鸣器响一声函数*******//void beep(){BEEP=0; //开蜂鸣器delayms(500); //延时半秒BEEP=1; //关蜂鸣器delayms(500); //延时半秒}//************温度转换***************//void tempconv(){uchar sign=0; //定义符号标志位uchar temp; //定义温度数据暂存if(H>127) //大于127,即高4位全为1,即温度为负值{L=(~L)+1; //取反加1,将补码变成原码if((~L)>=0xff) //H=(~L)+1; //取反加一else H=~H; //否则只取反sign=1; //置符号标志位为1}temp=L&0x0f; //取小数位DQdisp_buf[0]=temp*0.625; //所获得的是四位数,所测温度加大了10倍DQdisp_buf[0]=DQdisp_buf[0]%1000%100%10;//将小数部分转换成ASCII码temp_comp=((L&0xf0)>>4|(H&0x0f)<<4); //取温度整数部分DQdisp_buf[3]=temp_comp/100; //温度百位temp=temp_comp%100; //温度的十位和个位一起DQdisp_buf[2]=temp/10; //温度十位DQdisp_buf[1]=temp%10; //温度个位if(DQdisp_buf[3]==0) //如果温度的百位为0{DQdisp_buf[3]=17; //则不显示,if(DQdisp_buf[2]==0) //在这种前提下,如果十位也为0的话,DQdisp_buf[2]=17; //不显示十位}if(sign)DQdisp_buf[3]=13; //如果符号标志位为1,则显示负号}//************温度显示函数**************//void temperture_display(){LCD_set_xy(4,4); //从第四行第5列开始显示LCD_Write_number(11);LCD_Write_number(DQdisp_buf[3]); //显示百位LCD_Write_number(DQdisp_buf[2]); //显示十位LCD_Write_number(DQdisp_buf[1]); //显示个位LCD_Write_number(12); //小数点LCD_Write_number(DQdisp_buf[0]); //十分位LCD_set_xy(4,7);Write_char(1,num[14]);Write_char(1,num[15]);}//************获取温度值*****************//void gettemperture(void){uchar i;DS18B20_init(); //DS18B20初始化if(DS18B20_OK==0) //如果正常{writeonebyte(0xcc); //跳过读序列号的操作writeonebyte(0x44); //启动温度转换for(i;i<100;i++) //调用显示函数延时,等待A/D转换完成,分辨率为12位的需要延时750ms以上temperture_display();DS18B20_init(); //DS18B20初始化writeonebyte(0xcc); //跳过读序列号的操作writeonebyte(0xbe); //读取温度寄存器temp_dat[0]=readonebyte(); //温度低8位放入temp_dat[0]temp_dat[1]=readonebyte(); //温度高8位放入temp_dat[1]L=temp_dat[0]; //温度低8位H=temp_dat[1]; //温度高8位temp_flag=1; //接收正常}else temp_flag=0; //否则接收不正常}//************写一个字节函数*****************//void writeonebyte(uchar dat){uchar i=0;for(i=8;i>0;i--){DQ=0;DQ=dat&0x01;delay(5);DQ=1;dat>>=1;}}//************读一个字节函数***************//readonebyte(void){uchar i=0;uchar dat=0;for(i=8;i>0;i--){DQ=0;dat>>=1;DQ=1;if(DQ)dat|=0x80;delay(4);}return (dat);}//***************DS18B20延时函数************//void delay(uint num){while(--num);}//***************DS18B20初始化*******************//DS18B20_init(void){DQ=1; //DQ复位delay(8); //延时DQ=0; //单片机将DQ拉低delay(90); //等待至少480us的时间DQ=1; //拉高总线delay(8); //等待DS18B20反馈存在低脉冲,单片机检测DS18B20_OK=DQ; //如果为0,则初始化成功,为1,初始化失败delay(100);DQ=1;return (DS18B20_OK); //返回信号,若DS18B20_OK为0,则存在,若DS18B20_OK=1;则不存在}//************************************************////********** LCD 12864 ********////************************************************////************************************************/void Lcd_init(void) //初始化LCD{delayms(40); //大于40MS的延时程序PSB=1; //设置为8BIT并口工作模式delayms(1); //延时RES=0; //复位delayms(1); //延时RES=1; //复位置高delayms(1);Write_char(0,0x30); //选择基本指令集delayms(1); //延时大于100usWrite_char(0,0x30); //选择8bit数据流delayms(1); //延时大于37usWrite_char(0,0x0c); //开显示(无游标、不反白)delayms(1); //延时大于100usWrite_char(0,0x01); //清除显示,并且设定地址指针为00Hdelayms(1); //延时大于10msWrite_char(0,0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动delayms(1); //延时大于100us}/******************************************************************** **********//*------------------------------------------------检测忙位------------------------------------------------*/void Check_Busy(){RS=0;RW=1;EN=1;DataPort=0xff;while((DataPort&0x80)==0x80);//忙则等待EN=0;}void Write_char(bit start, uchar ddata) //start=0写指令,start=1写数据{if(start==0) //如果start==0,检查忙碌位后写指令{ Check_Busy(); //忙碌则等待RS=0;RW=0;EN=0;DataPort=ddata; //发送指令_nop_();_nop_();EN=1;_nop_();_nop_();_nop_();_nop_();EN=0;}else //如果start==1,即可以开始{ Check_Busy(); //再次检查,进行些数据操作RS=1;RW=0;EN=1;DataPort=ddata;EN=0;}}/******************************************************************** **********/void Delaynms(uint di) //延时0.1ms左右{uint da,db;for(da=0;da<di;da++)for(db=0;db<10;db++);}/******************************************************************** **********/void Disp_img(uchar *img) //图形方式12864显示字模221 横向取膜{uchar i,j;uint k = 0;Write_char(0,0x34); //图形方式,关闭for(i=0;i<32;i++) //每行128位。
12864液晶电子时钟+温度显示上午花了一上午时间,用12864 液晶写了一个电子时钟加温度传感器程序,先说一下程序的功能,可以实现显示年月日时间和温度,年月日和时间是可通过按键调节的,调节相应的选项时,该选项会闪烁,并停止走时,当调节完毕后时钟恢复走时。
现在将程序和思路写下来,以便日后查看和与大家探讨改进,欢迎高手提出宝贵意见。
我使用的是HJ12864M-1 带字库液晶,所以在显示上稍微方便一点。
下面先来说一下我的编程思路。
时间更新用的是单片机自带的定时器,液晶要显示数字必需将它转换成ASCii 码的形式,数字0-9 的ASCii 码与数字之间有一个定量的关系,当数字加上0x30 之后便得到该数字的ASCii 码,这样以来液晶更新数据就变得简单了。
调节时间时对应选项闪烁,是通过不断的交替写入数据和空格实现的。
温度显示用的是DS18B20,,将测得的当前温度不断更新显示在液晶上。
调节时间用的是三个独立按键。
由于这个程序我使用模块化来写的,就只能将每个模块分别给出来,大家只要组装一下便可以使用。
如果需要完整程序的可以给我留言我发给你们。
下面是12864 液晶的初始化,读写命令,及读忙操作#include “lcd12864.h”#include reg52.hsbit RS=P2 ; //控制端口位定义sbitRW=P2;s b it EN=P2;vo id init_12864(){delay(40);write_com(0x30);//8 位数据格式,基本指令显示delay(10); //延时时间write_com(0x30);//8 位数据格式,基本指令显示delay(37);write_com(0x0C);//开显示、关闭光标delay(10);write_com(0x01);//清屏指令delay(10); //延时write_com(0x06);//设置显示点:指针自加1}tips:感谢大家的阅读,本文由我司收集整编。
#include<reg52.h>#include<intrins.h>sbit SCLK=P3^7;sbit IO=P3^6;sbit CE=P3^5;sbit DQ = P3^4;sbit FM=P2^7;sbit RS=P2^3;sbit RW=P2^4;sbit EN=P2^5;sbit PSB=P2^2;sbit key=P1^0;sbit key1=P1^1;sbit key2=P1^2;sbit key3=P1^3;#define uchar unsigned char#define uint unsigned intuchar S1num,flag,second,minute,hour,week,day,month,year; bit keyflag=0;uchar num1[]="王厚谊加油";uchar num2[]="世上无难事";uchar num3[]="只要肯攀登";void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delay_us(){_nop_();_nop_();_nop_();_nop_();void fs_FM(){FM=0;delay(20);FM=1;}/*************************************************12864程序*************************************************/ void write_12864com(uchar com){RS=0;RW=0;P0=com;delay(5);EN=1;delay(5);EN=0;}void write_12864dat(uchar dat){RS=1;RW=0;P0=dat;delay(5);EN=1;delay(5);EN=0;}void write_12864(uchar add,uchar dat){write_12864com(add);write_12864dat(dat);}void Write_zfc(uchar *p){while(*p!=0)write_12864dat(*p++);}void init_12864(){PSB=1;write_12864com(0x30);delay(5);write_12864com(0x0f);delay(5);write_12864com(0x01);delay(5);// write_12864(0x81,'20');}void disp(){write_12864com(0x80);Write_zfc("日期:");write_12864com(0x90);Write_zfc("时间:");write_12864com(0x88);Write_zfc("星期:");write_12864com(0x98);Write_zfc("温度:");write_12864(0x84,'-');write_12864(0x86,'-');write_12864(0x94,':');write_12864(0x96,':');}void disp0(){uchar i;write_12864com(0x81);for(i=0;i<10;i++){write_12864dat(num1[i]);delay(4);}}void disp1()uchar i;write_12864com(0x91);for(i=0;i<10;i++){write_12864dat(num2[i]);delay(4);}}void disp2(){uchar i;write_12864com(0x89);for(i=0;i<10;i++){write_12864dat(num3[i]);delay(4);}}/***************************************************1302程序****************************************************/ void write_1302byte(uchar dat){uchar i;SCLK=0;delay_us();for(i=8;i>0;i--){IO=dat&0x01;delay_us();SCLK=1;delay_us();SCLK=0;dat>>=1;}}uchar read_1302byte(){uchar i,dat;delay_us();for(i=8;i>0;i--){dat>>=1;if(IO==1){dat|=0x80;}SCLK=1;delay_us();SCLK=0;delay_us();}return dat;}void write_1302(uchar add,uchar dat) {CE=0;delay_us();SCLK=0;delay_us();CE=1;write_1302byte(add);delay_us();write_1302byte(dat);delay_us();CE=0;}uchar read_1302add(uchar add){uchar timedat;CE=0;_nop_();SCLK=0;_nop_();CE=1;write_1302byte(add);timedat=read_1302byte();SCLK=1;_nop_();CE=0;return timedat;}void init_1302(){flag=read_1302add(0x81);if(flag&0x80){write_1302(0x8e,0x00);write_1302(0x80,((55/10)<<4|(55%10)));write_1302(0x82,((59/10)<<4|(59%10)));write_1302(0x84,((23/10)<<4|(23%10)));write_1302(0x86,((31/10)<<4|(31%10)));write_1302(0x88,((12/10)<<4|(12%10)));write_1302(0x8a,((2/10)<<4|(2%10)));write_1302(0x8c,((12/10)<<4|(12%10)));write_1302(0x90,0xa5);write_1302(0x8e,0x80);}}uchar readsecond(){uchar dat;dat=read_1302add(0x81);second=((dat&0x70)>>4)*10+(dat&0x0f);return second;}uchar readminute(){uchar dat;dat=read_1302add(0x83);minute=((dat&0x70)>>4)*10+(dat&0x0f);return minute;}uchar readhour(){uchar dat;dat=read_1302add(0x85);hour=((dat&0x70)>>4)*10+(dat&0x0f);return hour;}uchar readday()uchar dat;dat=read_1302add(0x87);day=((dat&0x70)>>4)*10+(dat&0x0f);return day;}uchar readmonth(){uchar dat;dat=read_1302add(0x89);month=((dat&0x70)>>4)*10+(dat&0x0f);return month;}uchar readweek(){uchar dat;dat=read_1302add(0x8b);week=((dat&0x70)>>4)*10+(dat&0x0f);return week;}uchar readyear(){uchar dat;dat=read_1302add(0x8d);year=((dat&0xf0)>>4)*10+(dat&0x0f);return year;}void write_second(){uchar shi,ge;shi=second/10;ge=second%10;write_12864com(0x97);write_12864dat(0x30+shi);write_12864dat(0x30+ge);}void write_minute(){uchar shi,ge;shi=minute/10;ge=minute%10;write_12864com(0x95);write_12864dat(0x30+shi);write_12864dat(0x30+ge); }void write_hour(){uchar shi,ge;shi=hour/10;ge=hour%10;write_12864com(0x93);write_12864dat(0x30+shi);write_12864dat(0x30+ge); }void write_day(){uchar shi,ge;shi=day/10;ge=day%10;write_12864com(0x87);write_12864dat(0x30+shi);write_12864dat(0x30+ge); }void write_month(){uchar shi,ge;shi=month/10;ge=month%10;write_12864com(0x85);write_12864dat(0x30+shi);write_12864dat(0x30+ge); }void write_year(){uchar shi,ge;shi=year/10;ge=year%10;write_12864com(0x83);write_12864dat(0x30+shi);write_12864dat(0x30+ge);}void write_week(){write_12864com(0x8b);write_12864dat(0x30+week);}/*****************************************************按键程序*****************************************************/ void keycan(){if(key==0){delay(5);if(key==0){S1num++;while(!key);fs_FM();switch(S1num){case 1:keyflag=1;write_1302(0x8e,0x00);write_1302(0x80,0x80);write_12864com(0x97);write_12864com(0x0f);break;case 2:write_12864com(0x95);break;case 3:write_12864com(0x93);break;case 4:write_12864com(0x87);break;case 5:write_12864com(0x85);break;case 6:write_12864com(0x83);break;case 7:write_12864com(0x8b);break;case 8:S1num=0;keyflag=0;write_12864com(0x0c);write_1302(0x80,0x00);write_1302(0x80,(second/10)<<4|second%10);write_1302(0x82,(minute/10)<<4|minute%10);write_1302(0x84,(hour/10<<4)|hour%10);write_1302(0x86,(day/10<<4)|day%10);write_1302(0x88,(month/10<<4)|month%10);write_1302(0x8a,(week/10<<4)|week%10);write_1302(0x8c,(year/10<<4)|year%10);write_1302(0x8e,0x80);break;}}}if(S1num!=0){if(key1==0){delay(5);while(!key1);fs_FM();switch(S1num){case 1:second++;if(second==60)second=0;write_second();write_12864com(0x97);break;case 2:minute++;if(minute==60)minute=0;write_minute();write_12864com(0x95);break;case 3:hour++;if(hour==24)hour=0;write_hour();write_12864com(0x93);break;case 4:day++;if(day==32)day=1;write_day();write_12864com(0x87);break;case 5:month++;if(month==13)month=1;write_month();write_12864com(0x85);break;case 6:year++;if(year==99)year=0;write_year();write_12864com(0x83);break;case 7:week++;if(week==8)week=1;write_week();write_12864com(0x8b);break;}}}if(S1num!=0){if(key2==0){delay(5);while(!key2);fs_FM();switch(S1num){case 1:second--;if(second==-1)second=59;write_second();write_12864com(0x97);break;case 2:minute--;if(minute==-1)minute=59;write_minute();write_12864com(0x95);break;case 3:hour--;if(hour==-1)hour=23;write_hour();write_12864com(0x93);break;case 4:day--;if(day==0)day=31;write_day();write_12864com(0x87);break;case 5:month--;if(month==0)month=12;write_month();write_12864com(0x85);break;case 6:year--;if(year==-1)year=99;write_year();write_12864com(0x83);break;case 7:week--;if(week==0)week=7;write_week();write_12864com(0x8b);break;}}}}/*****************************************************18B20程序*******************************************************/uint temp; //温度值variable of temperaturevoid delay2(unsigned char i) //延时函数{while(--i);}void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command{DQ = 1; //DQ复位,不要也可行。
基于STC89C52单片机的18b20测温程序主程序:/***************************************************************************** 使用单片机:STC89C52晶振频率:11.0592MHZ开发环境:Keil4.0功能简述:调试用12864LCD的显示功能,蜂鸣器报警装置******************************************************************************/ #include<reg52.h>#include<intrins.h>#include<stdio.h>#include <math.h>#define uchar unsigned char#define uint unsigned int#define lcd_data P0#include "lcd.h"#include "ds18b20.h"code uchar Display1[8]={"实际温度"};code uchar Display2[8]={"报警温度"};sbit sl=P0^3;sbit sr=P0^4;sbit su=P0^5;sbit sd=P0^6;char f=0; //定义标志位sbit beep=P1^7; //蜂鸣器uint temp,templa; //定义整形温度数据float f_temp; //定义浮点型得温度数据int Actual_Temp;int Alarm_Temp;unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint z) //延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void Key_Scan() //键盘扫描程序{if(sl==0) //实现光标的左移{delay(5); //消抖if(sl==0){while(!sl); //按键松手检测等待按键释放if(f==0)f=4;else f--; // 按键自减1}}if(sr==0) //实现光标的右移{delay(5); //消抖if(sr==0){while(!sr); //按键松手检测f++;if(f==4)f=0;}}if(su==0) //实现按键加的功能{delay(5); //消抖if(su==0){while(!su); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp+100;}if(f==2){Alarm_Temp=Alarm_Temp+10;}if(f==3){Alarm_Temp=Alarm_Temp+1;}}}if(sd==0) // 实现按键减的功能{delay(5); //消抖if(sd==0){while(!sd); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp-100;}if(f==2){Alarm_Temp=Alarm_Temp-10;}if(f==3){Alarm_Temp=Alarm_Temp-1;}}}Alarm_Temp= Alarm_Temp;}void LCD_Display(int value,char x,char y){uint abs_value;code uchar Display_Dot[1]={"."};code uchar Display_Unit[1]={"C"};if(value<0){LCD_Pos(x,y-1);LCD_SendData("-",1);}else{LCD_Pos(x,y-1);LCD_SendData("+",1);}abs_value=abs(value);LCD_Pos(x,y);LCD_Write(abs_value/100+0x30,1);LCD_Write(abs_value%100/10+0x30,1);LCD_SendData(Display_Dot,1); //显示小数点LCD_Write(abs_value%10+0x30,1);LCD_SendData(Display_Unit,1); //显示单位}void LCD_DisplayTemp() ////显示实际温度与报警温度值{LCD_Display(Actual_Temp ,0,5);LCD_Display(Alarm_Temp ,1,5);switch(f){case 0:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 1:LCD_Pos(2,5);LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 2: LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 3:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符case 4:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示向上指针LCD_Write(24,1); //显示空白字符}}void DS18B20_TempChange(void) //DS18B20 开始获取温度并转换{DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc); // 写跳过读ROM指令DS18B20_WriteByte(0x44); // 写温度转换指令}void DS18B20_GetTemp() // 从DS18B20读取寄存器中存储的温度数据{uchar a,b;DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc);DS18B20_WriteByte(0xbe);a=DS18B20_Read(); //读低8位b=DS18B20_Read(); //读高8位temp=b;temp<<=8; //两个字节组合为1个字temp=temp|a;if(temp&0x80==0x80) temp=-(~temp+1); //判断实测温度的正负f_temp=temp*0.0625; //温度在寄存器中为12位分辨率位0.0625°temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入 f_temp=f_temp+0.05;Actual_Temp=temp; //temp是整型}void Beep_Warn() //蜂鸣器报警{if(Actual_Temp>Alarm_Temp)beep=0; //蜂鸣器响elsebeep=1; //蜂鸣器不响}void main(){ uint i;LCD_init(); //初始化LCDLCD_Clear(); //LCD清屏LCD_Pos(0,0); //设置显示位置为第一行的第一个字符LCD_SendData(Display1,8); //显示:实际温度LCD_Pos(1,0); //设置显示位置为第二行的第一个字符LCD_SendData(Display2,8); //显示报警温度while(1){ DS18B20_TempChange( );for(i=0;i<10;i++){Beep_Warn ();DS18B20_GetTemp();LCD_DisplayTemp(); //调用显示函数}Key_Scan(); //调用键盘函数}}//程序很棒,仅供参考,不明白处可留言。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^2;
sbit RW=P2^3;
sbit E=P2^4;
sbit DQ=P1^7; //ds18b20与单片机连接口uint tvalue; //温度值
uchar tflag; //温度正负标志
bit ReadTempFlag;
void Init_Timer0();
uchar code tabwendu[]="温度: . C"; void init();
void display();
void ds1820disp();
void tabwendu(uchar add,uchar date);
void delay(unsigned int ms) //延时1毫秒{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
void delay_18B20(unsigned int i)//延时1微秒{
while(i--);
}
void write_com(uchar con)
{
RS=0;
RW=0;
P0=con;
delay(50);
E=1;
delay(50);
E=0;
}
void write_date(uchar date)
{
RS=1;
RW=0;
P0=date;
delay(5);
E=1;
delay(5);
E=0;
}
void init()
{
uchar i;
write_com(0x30);
delay(5);
write_com(0x0c);
delay(5);
write_com(0x01);
delay(5);
write_com(0x98);
for(i=0;i<16;i++)
{
write_date(tabwendu[i]);
delay(1);
}
}
/*****ds1820复位******/
void ds1820rst()
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd()/*读数据*/
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
/***********写数据**********/
void ds1820wr(uchar wdata)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
/***读取温度值并转换***/
read_temp()
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc); //*跳过读序列号*/
ds1820wr(0x44); //*启动温度转换*/
ds1820rst();
ds1820wr(0xcc); //*跳过读序列号*/
ds1820wr(0xbe); //*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
tvalue=tvalue*0.0625*10; //温度值扩大10倍,精确到1位小数return(tvalue);
}
/*******************************************************************/ void ds1820disp() //温度值显示
{
uchar shi;
uchar ge;
uchar flagdat;
bai=tvalue/100; //百位数
shi=(tvalue%100)/10; //十位数
ge=(tvalue%100)%10; //个位数
if(tflag==0)
flagdat=0x20; //正温度不显示符号
else
flagdat=0x2d; //负温度显示负号:-
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00; //给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
static unsigned int num;
TH0=(65536-2000)/256; //重新赋值2ms
TL0=(65536-2000)%256;
num++;
if(num==300) //
{
num=0;
ReadTempFlag=1; //读标志位置1
}
}
void display()
{
uchar bai;
uchar ge;
bai=tvalue/100; //百位数shi=(tvalue%100)/10; //十位数
ge=(tvalue%100)%10; //个位数write_com(0x9b);
write_date(0x30+bai);
delay(1);
write_com(0x9c);
write_date(0x30+shi);
delay(1);
write_com(0x9e);
write_date(0x30+ge);
delay(1);
// write_com(0x80);
//write_date(0x2e);
}
void main()
{
// uchar i;
init(); //初始化液晶
Init_Timer0();
// ds1820rst();
while (1) //主循环
{
if(ReadTempFlag==1)
{
ReadTempFlag=0;
read_temp() ;
display();
ReadTempFlag=0;
}
}
}。