由于本程序使用了STC12C5A60S2单片机,最好不要使用太高的晶振,不然DS18B20延时部分太难调试(搞不好会显示00.0度),一般12M以下相对好些.
制作出来的实物图如下:
单片机源程序如下:
- //******************************************************************************
- //LCD12864行地址地址定义 *
- //第一行地址:80H 81H 82H 83H 84H 85H 86H 87H *
- //第二行地址:90H 91H 92H 93H 94H 95H 96H 97H *
- //第三行地址:88H 89H 8AH 8BH 8CH 8DH 8EH 8FH *
- //第四行地址:98H 99H 9AH 9BH 9CH 9DH 9EH 9FH *
- //程序说明:本程序为带有字库汉字显示的12864液晶显示器源程序
- //****************************************************************
- //#include<stc12c5a60s2.h>表示头文件在keil5软件安装目录(根目录)下,编译时软件到安装目录找头文件。
- //#include"stc12c5a60s2.h"表示头文件在当前的工程目录下,如果找不到头文件再到安装目录的根目录找。
- //****************************************************************
- #include<stc12c5a60s2.h> //载入STC12C5A60S2头文件
- #include<intrins.h> //用到这个头文件表示你可以在程序中调用单片机中库文件中的函数
- #define uchar unsigned char //用Uchar代替unsigned char
- #define uint unsigned int //用uint代替unsigned int
- //****************************************************************
- //定义LCD12864的数据线和相关函数
- //****************************************************************
- sbit LCD_RS=P2^7; //模式位,低电平输入指令,高电平输入数据
- sbit LCD_RW=P2^6; //读写位,低电平读,高电平写
- sbit LCD_E =P2^5; //LCD12864使能位,低电平无效,高电平使能
- #define Busy 0x80
- #define LCD_Data P0 //LCD12864的8位数据总线,单片机的P0端口
- void WriteDataLCD(unsigned char WDLCD); //给LCD12864写数据
- void WriteCommandLCD(unsigned char WCLCD); //给LCD12864写指令
- void LCDInit(void); //LCD12864初始化
- void LCDClear(void); //LCD12864清屏
- void CheckBusy(void); //忙检测
- void LCDSendWord(unsigned char *p); //向LCD发送一个字符串
- void LCDTestWord(bit i,unsigned char word);
- //****************************************************************
- //定义时间芯片DS1302的数据线及相关函数
- //****************************************************************
- void DisplaySec(void); //在LCD上显示秒钟
- void DisplayMin(void); //在LCD上显示分钟
- void DisplayHour(void); //在LCD上显示小时
- unsigned char sec,min,hour; //秒,分,小时
- sbit DS1302_CLK=P2^0; //DS1302的时钟信号线
- sbit DS1302_IO =P2^1; //DS1302的数据端口线
- sbit DS1302_RST=P2^2; //DS1302的片选信号线
- void WriteDs1302byte(unsigned char temp); //给DS1302写一个字节
- void WriteDs1302(unsigned char address,unsigned char dat); //给DS1302写入时间,先确定地址,再确定要写入的数据
- unsigned char ReadDs1302(unsigned char address); //读取DS1302的数据
- void InitDS1302();
- //****************************************************************
- //定义温度传感器DS18B20的数据线和相关函数
- //****************************************************************
- sbit DS18B20=P1^2; //DS18B20的数据线
- int temp;
- void DS18B20Init(void); //DS18B20初始化函数
- int GetTemp(void);
- void TempWriteByte(unsigned char dat);
- unsigned char TempRead(void);
- bit TempReadBit(void);
- void TempChange(void);
- //****************************************************************
- //定义延时部分相关函数
- //****************************************************************
- void delayb(unsigned int count);
- void DelayMs(unsigned int a);
- void Delay(unsigned char num);
- //****************************************************************
- //定义开关按键的端口
- //****************************************************************
- sbit Key1 =P1^4; //按键功能:设置(本程序未使用按键)
- sbit Key2 =P1^5; //按键功能:确认(本程序未使用按键)
- sbit Key3 =P1^6; //按键功能:加 (本程序未使用按键)
- sbit Key4 =P1^7; //按键功能:左移(本程序未使用按键)
- void Key(void);
- //****************************************************************
- //定义提示音乐部分相关函数
- //****************************************************************
- #define Fosc 6000000 //定义晶振频率24000000HZ
- sbit Speaker=P3^7; //定义输出管脚
- void SpeakerDiDi(void)
- {
- unsigned char i; //整点报时延时
- for(i=0;i<3;i++)
- {
- Speaker=0;
- DelayMs(800);
- Speaker=1;
- DelayMs(800);
- }
- DelayMs(4000);
- for(i=0;i<3;i++)
- {
- Speaker=0;
- DelayMs(800);
- Speaker=1;
- DelayMs(800);
- }
- DelayMs(4000);
- for(i=0;i<2;i++)
- {
- Speaker=0;
- DelayMs(4000);
- Speaker=1;
- DelayMs(1000);
- }
- }
- /******************忙检测函数***************/
- void CheckBusy(void)
- {
- LCD_RS=0;
- LCD_RW=1;
- LCD_E=1;
- LCD_Data=0xff;
- while((LCD_Data&0x80)==0x80);
- LCD_E=0;
- }
- /**********************给LCD写入数据*****************/
- void WriteDataLCD(unsigned char WDLCD)
- {
- CheckBusy(); //检测忙
- LCD_RS = 1; //RS为高电平,DB7----DB0为数据
- LCD_RW = 0; //RW为低电平,E从高电平到低电平,则是把DB7----DB0的数据写到DR或者IR
- LCD_E = 1;
- LCD_Data = WDLCD; //传送数据WDLCD
- Delay(40);
- LCD_E = 0; //E从 高电平 到 低电平
- Delay(40);
- }
- /******************给LCD写入指令**********************/
- void WriteCommandLCD(unsigned char WCLCD) //BuysC为0时忽略忙检测
- {
- CheckBusy(); //检测忙
- LCD_RS = 0; //RS为低,DB7----DB0为指令
- LCD_RW = 0; //RW为低,E从高电平到低电平,则是把DB7----DB0的数据写到DR或者IR
- LCD_E = 1;
- LCD_Data = WCLCD; //传送数据
- Delay(40);
- LCD_E = 0; //E从 高电平到低电平
- Delay(40);
- }
- /***************LCD初始化******************/
- void LCDInit(void)
- {
- WriteCommandLCD(0x30); //显示模式设置,开始要求每次检测忙信号
- WriteCommandLCD(0x01); //显示清屏
- WriteCommandLCD(0x06); // 显示光标移动设置
- WriteCommandLCD(0x0C); // 显示开,无游标,不反白
- }
- /********************清屏***************************/
- void LCDClear(void)
- {
- WriteCommandLCD(0x01); //显示清屏
- WriteCommandLCD(0x34); // 显示光标移动设置
- WriteCommandLCD(0x30); // 显示开及光标设置
- }
- void LCDSendWord(unsigned char *p) //向LCD发送一个字符串,
- {
- while(*p>0) //比如void LCDSendWord('你好');就是让LCD显示"你好"
- {
- WriteDataLCD(*p);
- p++;
- }
- }
-
- /************写数据或者指令***************/
- void LCDTestWord(bit i,unsigned char word)
- {
- if(i==0)
- {
- WriteCommandLCD(word); //i=0;则写入指令
- }
- else
- {
- WriteDataLCD(word); //i=1;则写入数据
- }
- }
- void Displayqt(void)
- {
- LCDTestWord(0,0x80);
- LCDSendWord("如果你还在!");
- }
- void DisplayHour(void) //往LCD上填写小时数据
- {
- hour=ReadDs1302(0x85);
- LCDTestWord(0,0x98);
- LCDTestWord(1,(hour/16)+0x30);
- LCDTestWord(1,hour%16+0x30);
- }
- void DisplayMin(void) //往LCD上填写分钟数据
- {
- min=ReadDs1302(0x83);
- LCDTestWord(0,0x99);
- LCDTestWord(1,0x3a);
- LCDTestWord(1,(min/16)+0x30);
- LCDTestWord(1,min%16+0x30);
- LCDTestWord(1,0x3a);
- }
- void DisplaySec(void) //往LCD上填写秒钟数据
- {
- unsigned char i=0;
- unsigned int a=0,b=0,c=0;
- sec=ReadDs1302(0x81);
- LCDTestWord(0,0x9b);
- LCDTestWord(1,(sec/16)+0x30);
- LCDTestWord(1,sec%16+0x30);
- }
- void DisplayTemp(void)
- {
- unsigned int i;
- unsigned char a,b,c;
- WriteCommandLCD(0x9c);
- LCDTestWord(0,0x9d);
- TempChange();
- i=GetTemp();
- a=i/100;
- LCDTestWord(1,a+0x30);
- b=i/10-a*10;
- LCDTestWord(1,b+0x30);
- LCDTestWord(1,0x2e);
- c=i-a*100-b*10;
- LCDTestWord(1,c+0x30);
- LCDSendWord("度");
- }
- //****************************************************************
- //DS1302部分子程序
- //****************************************************************
- /*********************写入操作*********************/
- void WriteDs1302Byte(unsigned char temp)
- {
- unsigned char i;
- for (i=0;i<8;i++) //循环8次 写入数据
- {
- DS1302_CLK=0;
- DS1302_IO=temp&0x01; //每次传输低字节
- temp>>=1; //右移一位
- DS1302_CLK=1;
- }
- }
- /*********************写入数据*******************/
- void WriteDs1302( unsigned char address,unsigned char dat ) //先写地址,再写数据
- {
- DS1302_RST=0;
- _nop_();
- DS1302_CLK=0;
- _nop_();
- DS1302_RST=1;
- _nop_(); //启动
- WriteDs1302Byte(address); //发送地址
- WriteDs1302Byte(dat); //发送数据
- DS1302_RST=0; //恢复
- }
- /************************************************/
- unsigned char ReadDs1302(unsigned char address) //先送地址,再读数据
- {
- unsigned char i,temp=0x00;
- DS1302_RST=0;
- _nop_();
- DS1302_CLK=0;
- _nop_();
- DS1302_RST=1;
- _nop_();
- WriteDs1302Byte(address); //送地址函数
- for (i=0;i<8;i++) //循环8次 读取数据
- {
- DS1302_CLK=1;
- _nop_();
- if(DS1302_IO)
- temp|=0x80; //每次传输低字节
- DS1302_CLK=0;
- temp>>=1; //右移一位
- }
- DS1302_RST=0;
- _nop_();
- DS1302_CLK=1;
- DS1302_IO=0;
- return (temp); //返回
- }
- /*****************DS1302初始化********************/
- void InitDS1302() //DS1302中秒,分,时,日期,月份,星期,年的地址分别是0x80,0x82,0x84,0x86,0x88,0x8a,0x8c
- { //初始化写入的时间是2010年4月1日15点整,星期六
- WriteDs1302(0x8e,0x00); //控制命令,WP位为0,允许写操作 控制位地址是0x8e
- DelayMs(5);
- WriteDs1302(0x84,0x00); //写入小时 20点
- DelayMs(5);
- WriteDs1302(0x82,0x00); //写入分钟 03分
- DelayMs(5);
- WriteDs1302(0x80,0x00); //写入秒钟 00秒
- DelayMs(5);
- WriteDs1302(0x8e,0x80); //控制命令,WP为1,禁止写操作
- }
- //****************************************************************
- //DS18B20部分子程序
- //****************************************************************
- void DS18B20Init(void) //DS18B20初始化
- {
- unsigned int i;
- DS18B20=0;
- i=103*8;
- while(i>0)i--;
- DS18B20=1;
- i=103;
- while(i>0)i--;
- }
- bit TempReadBit(void) // 读一位
- {
- unsigned int i;
- bit dat;
- DS18B20=0;i++; //小延时一下
- DS18B20=1;i++;i++;
- dat=DS18B20;
- i=32;while(i>0)i--;
- return (dat);
- }
- unsigned char TempRead(void) //读一个字节
- {
- unsigned char i,j,dat;
- dat=0;
- for(i=1;i<=8;i++)
- {
- j=TempReadBit();
- dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
- }
- return(dat); //将一个字节数据返回
- }
- void TempWriteByte(unsigned char dat)
- { //写一个字节到DS18B20里
- unsigned int i;
- unsigned char j;
- bit testb;
- for(j=1;j<=8;j++)
- {
- testb=dat&0x01;
- dat=dat>>1;
- if(testb) // 写1部分
- {
- DS18B20=0;
- i++;i++;
- DS18B20=1;
- i=32;while(i>0)i--;
- }
- else
- {
- DS18B20=0; //写0部分
- i=32;while(i>0)i--;
- DS18B20=1;
- i++;i++;
- }
- }
- }
- void TempChange(void) //发送温度转换命令
- {
- DS18B20Init(); //初始化DS18B20
- delayb(8); //延时
- TempWriteByte(0xcc); // 跳过序列号命令
- TempWriteByte(0x44); //发送温度转换命令
- }
- int GetTemp() //获得温度
- {
- float tt;
- unsigned char a,b;
- DS18B20Init();
- delayb(1);
- TempWriteByte(0xcc);
- TempWriteByte(0xbe); //发送读取数据命令
- a=TempRead(); //连续读两个字节数据
- b=TempRead();
- temp=b;
- temp<<=8;
- temp=temp|a; //两字节合成一个整型变量。
- tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20 可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
- temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位 也转换为可显示数字,同时进行一个四舍五入操作。
- return temp; //返回温度值
- }
- /****************************************************************************/
- void UpDate(void)
- {
- DS18B20=1;
- DisplayHour(); //显示时
- DisplayMin(); //显示分
- DisplaySec(); //显示秒
- DisplayTemp(); //显示温度
- }
- //****************************************************************
- //延时部分子程序
- //****************************************************************
- void delayb(unsigned int count) //delay
- {
- unsigned char i;
- while(count)
- {
- i=200;
- while(i>0)
- i--;
- count--;
- }
- }
- void DelayMs(unsigned int a) //延时 1MS/次
- {
- unsigned char i;
- while(--a!=0)
- {
- for(i=0;i<125;i++)
- ;
- }
- }
- void Delay(unsigned char num)
- {
- while(num--)
- ;
- }
-
- void main()
- {
- LCDInit();
- LCDClear();
- InitDS1302();
- while(1)
- {
- Displayqt();
- UpDate();
- }
- }
复制代码
|