谢谢各位大神的指点,是程序有问题,现在修改好了 代码:
- /********************************************************************************************
- 程序名: 1602智能液晶屏时钟
- 硬件支持: LCD1602液晶屏 STC12C5608+外部12MHZ晶振 DS1302+32.768KHZ晶振
- 说明备注: 使用2402液晶屏程序,与1602液晶屏程序完全兼容
- /********************************************************************************************/
- #include <STC12C5630AD.h> // 包含头文件 //
- #include <intrins.h>
- /********************************************************************************************/
- typedef unsigned char uint8; // 无符号8位整型变量 //
- typedef unsigned char uchar; // 无符号8位整型变量 //
- /********************************************************************************************
- // 引脚定义 // (使用者根据实际更改)
- /********************************************************************************************/
- #define LCM2402_DB0_DB7 P2 // 定义LCM2402的数据总线
- sbit LCM2402_RS = P1 ^ 5; // 定义LCM2402的RS控制线
- sbit LCM2402_RW = P1 ^ 6; // 定义LCM2402的RW控制线
- sbit LCM2402_E = P1 ^ 7; // 定义LCM2402的E控制线
- sbit LCM2402_Busy = P2 ^ 7; // 定义LCM2402的测忙线(与LCM2402_DB0_DB7关联)
- sbit DQ = P1 ^ 3; // 定义18B20的数据端
- sbit SCLK = P1 ^ 0; //定义ds1302_clk(1302时钟线)
- sbit DSIO = P1 ^ 1; //定义ds1302_dat(1302数据线)
- sbit RST = P1 ^ 2; //定义ds1302_Rst(1302复位线)
- data unsigned char TIME_WW;//设置星期存放区
- /********************************************************************************************
- // 定义LCM2402指令集 // (详细请见技术手册)
- /********************************************************************************************/
- #define CMD_clear 0x01 // 清除屏幕
- #define CMD_back 0x02 // DDRAM回零位
- #define CMD_dec1 0x04 // 读入后AC(指针)减1,向左写
- #define CMD_add1 0x06 // 读入后AC(指针)加1,向右写
- #define CMD_dis_gb1 0x0f // 开显示_开光标_开光标闪烁
- #define CMD_dis_gb2 0x0e // 开显示_开光标_关光标闪烁
- #define CMD_dis_gb3 0x0c // 开显示_关光标_关光标闪烁
- #define CMD_OFF_dis 0x08 // 关显示_关光标_关光标闪烁
- #define CMD_set82 0x38 // 8位总线_2行显示
- #define CMD_set81 0x30 // 8位总线_1行显示(上边行)
- #define CMD_set42 0x28 // 4位总线_2行显示
- #define CMD_set41 0x20 // 4位总线_1行显示(上边行)
- #define lin_1 0x80 // 4位总线_1行显示(上边行)
- #define lin_2 0xc0 // 4位总线_1行显示(上边行)
- /********************************************************************************************
- // 读LCM忙程序 [底层协议] // (所有底层协议都无需关注)
- // LCM2402测忙,若LCM2402处于忙状态,本函数将等待至非忙状态 //
- /********************************************************************************************/
- void LCM2402_TestBusy(void){
- LCM2402_DB0_DB7 = 0xff; //设备读状态
- LCM2402_RS = 0;
- LCM2402_RW = 1;
- LCM2402_E = 1;
- while(LCM2402_Busy); //等待LCM不忙
- LCM2402_E = 0; //
- }
- /********************************************************************************************
- // 写指令程序 //
- // 向LCM2402写命令 本函数需要1个指令集的入口参数 //
- /********************************************************************************************/
- void LCM2402_WriteCMD(uint8 LCM2402_command) {
- LCM2402_TestBusy();
- LCM2402_RS = 0;
- LCM2402_RW = 0;
- LCM2402_DB0_DB7 = (LCM2402_command/16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- LCM2402_DB0_DB7 = (LCM2402_command%16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- }
- /********************************************************************************************
- // 写数据程序 //
- // 向LCM2402写数据 //
- /********************************************************************************************/
- void LCM2402_WriteData(uint8 LCM2402_data){
- LCM2402_TestBusy();
- LCM2402_RS = 1;
- LCM2402_RW = 0;
- LCM2402_DB0_DB7 = (LCM2402_data/16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- LCM2402_DB0_DB7 = (LCM2402_data%16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- }
- /********************************************************************************************
- // 打印字符串程序 // (本函数调用指针函数)
- // 向LCM发送一个字符串,长度48字符之内
- // 第一行位置 0x00~0x17 第二行位置 0x40~0x57
- // 应用举例:print(0x80,"abc"); //在第一行第一位处从左向右打印abc字符串
- /********************************************************************************************/
- void print(uint8 a,uint8 *str){
- LCM2402_WriteCMD(a | 0x80);
- while(*str != '\0'){
- LCM2402_WriteData(*str++);
- }
- *str = 0;
- }
- /********************************************************************************************
- // 打印单字符程序 //
- // 第一行位置 0x00~0x17 第二行位置 0x40~0x57
- // 向LCM发送一个字符,以十六进制(0x00)表示
- // 应用举例:print(0xc0,0x30); //在第二行第一位处打印字符“0”
- /********************************************************************************************/
- void print2(uint8 a,uint8 t){
- LCM2402_WriteCMD(a | 0x80);
- LCM2402_WriteData(t);
- }
- /********************************************************************************************
- // 定义小汉字 //
- // 可写入8个自字义字符,写入后可用其CGRAM代码直接提取显示。
- // 字符定义方法请参考技术手册
- /********************************************************************************************/
- uint8 code Xword[]={
- 0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //℃,代码 0x00
- 0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00, //一,代码 0x01
- 0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00, //二,代码 0x02
- 0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00, //三,代码 0x03
- 0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00, //四,代码 0x04
- 0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00, //五,代码 0x05
- 0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00, //六,代码 0x06
- 0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00, //日,代码 0x07
- };
- void CgramWrite(void) { // 装入CGRAM //
- uint8 i;
- LCM2402_WriteCMD(0x06); // CGRAM地址自动加1
- LCM2402_WriteCMD(0x40); // CGRAM地址设为00处
- for(i=0;i<64;i++) {
- LCM2402_WriteData(Xword[i]);// 按数组写入数据
- }
- }
- /********************************************************************************************
- // LCM2402初始化 //(使用者可自定义,加 * 号程序行必须保留但可修改)
- /********************************************************************************************/
- void LCM2402_Init(void){
- LCM2402_WriteCMD(CMD_set42); //* 显示模式设置:显示2行,每个字符为5*7个像素
- LCM2402_WriteCMD(CMD_set42); //* 显示模式设置:显示2行,每个字符为5*7个像素
- LCM2402_WriteCMD(CMD_clear); // 显示清屏
- LCM2402_WriteCMD(CMD_back); //* 数据指针指向第1行第1个字符位置
- LCM2402_WriteCMD(CMD_add1); // 显示光标移动设置:文字不动,光标右移
- LCM2402_WriteCMD(CMD_dis_gb3); // 显示开及光标设置:显示开,光标开,闪烁开
- CgramWrite(); // 向CGRAM写入自定义字符
- }
- /******************************************************************************/
- // 以上是LCM2402驱动程序 //
- /*****************************************************************************/
- //---DS1302写入和读取时分秒的地址命令---//
- //---秒分时日月周年 最低位读写位;-------//
- uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
- uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
- //---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---//
- //---存储顺序是秒分时日月周年,存储格式是用BCD码---//
- uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};
- /*******************************************************************************
- * 函 数 名 : Ds1302Write
- * 函数功能 : 向DS1302命令(地址+数据)
- * 输 入 : addr,dat
- * 输 出 : 无
- *******************************************************************************/
- void Ds1302Write(uchar addr, uchar dat)
- {
- uchar n;
- RST = 0;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//先将SCLK置低电平。
- _nop_();_nop_();_nop_();_nop_();
- RST = 1; //然后将RST(CE)置高电平。
- _nop_();_nop_();_nop_();_nop_();
- for (n=0; n<8; n++)//开始传送八位地址命令
- {
- DSIO = addr & 0x01;//数据从低位开始传送
- addr >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;
- _nop_();_nop_();_nop_();_nop_();
- }
- for (n=0; n<8; n++)//写入8位数据
- {
- DSIO = dat & 0x01;
- dat >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;
- _nop_();_nop_();_nop_();_nop_();
- }
-
- RST = 0;//传送数据结束
- _nop_();_nop_();_nop_();_nop_();
- }
- /*******************************************************************************
- * 函 数 名 : Ds1302Read
- * 函数功能 : 读取一个地址的数据
- * 输 入 : addr
- * 输 出 : dat
- *******************************************************************************/
- uchar Ds1302Read(uchar addr)
- {
- uchar n,dat,dat1;
- RST = 0;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//先将SCLK置低电平。
- _nop_();_nop_();_nop_();_nop_();
- RST = 1;//然后将RST(CE)置高电平。
- _nop_();_nop_();_nop_();_nop_();
- for(n=0; n<8; n++)//开始传送八位地址命令
- {
- DSIO = addr & 0x01;//数据从低位开始传送
- addr >>= 1;
- SCLK = 1;//数据在上升沿时,DS1302读取数据
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//DS1302下降沿时,放置数据
- _nop_();_nop_();_nop_();_nop_();
- }
- _nop_();_nop_();_nop_();_nop_();
- for(n=0; n<8; n++)//读取8位数据
- {
- dat1 = DSIO;//从最低位开始接收
- dat = (dat>>1) | (dat1<<7);
- SCLK = 1;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//DS1302下降沿时,放置数据
- _nop_();_nop_();_nop_();_nop_();
- }
- RST = 0;
- _nop_();_nop_();_nop_();_nop_(); //以下为DS1302复位的稳定时间,必须的。
- SCLK = 1;
- _nop_();_nop_();_nop_();_nop_();
- DSIO = 0;
- _nop_();_nop_();_nop_();_nop_();
- DSIO = 1;
- _nop_();_nop_();_nop_();_nop_();
- return dat;
- }
- /*******************************************************************************
- * 函 数 名 : Ds1302Init
- * 函数功能 : 初始化DS1302.
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Ds1302Init()
- {
- uchar n;
- Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
- for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
- {
- Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
- _nop_();_nop_();
- }
- Ds1302Write(0x8E,0x80); //打开写保护功能
- }
- /*******************************************************************************
- * 函 数 名 : Ds1302ReadTime
- * 函数功能 : 读取时钟信息
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Ds1302ReadTime()
- {
- uchar n;
- for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
- {
- TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
- _nop_();_nop_();
- }
-
- }
- /******************************************************************************/
- //DS18B20温度传感器驱动(显示0至60度)
- /******************************************************************************/
- void Delay(int num){//延时函数
- while(num--) ;
- }
- /******************************************************************************/
- void Init_DS18B20(void){//初始化ds1820
- unsigned char x=0;
- DQ = 1; //DQ复位
- Delay(35); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delay(480); //精确延时 大于 480us
- DQ = 1; //拉高总线
- Delay(70);
- x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
- Delay(90);
- }
- /******************************************************************************/
- unsigned char ReadOneChar(void){//读一个字节
- 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(30);
- }
- return(dat);
- }
- /******************************************************************************/
- void WriteOneChar(unsigned char dat){//写一个字节
- unsigned char i=0;
- for (i=8; i>0; i--){
- DQ = 0;
- DQ = dat&0x01;
- Delay(30);
- DQ = 1;
- dat>>=1;
- }
- }
- /******************************************************************************/
- unsigned int ReadTemperature(void){//读取温度
- 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;
- tt=t*0.0625;
- t= tt*10+0.5; //放大10倍输出并四舍五入
- return(t);
- }
- /*****************************************************************************/
- //显示项目 时间部分 在第一行全行显示时间
- /*********************************************************************************************/
- // 测试用函数 //
- void main (void){
- LCM2402_Init();//LCD初始化
- Ds1302Init();//DS1302初始化
- while(1){ //主线程//
- unsigned int i=0,o=0,o2=0;
- unsigned char a=0,b=0,c=0;
- i=ReadTemperature();
- a=i/100;
- print2(0x40,a+0x30);
- b=i/10-a*10;
- print2(0x41,b+0x30);
- print(0x42,".");
- c=i-a*100-b*10;
- print2(0x43,c+0x30); //显示温度
- print2(0x44,0x00); //显示℃
- //
- Ds1302ReadTime();
- print(0x00,"20");
- print2(0x02,TIME[6]/16+0x30);
- print2(0x03,(TIME[6]&0x0f)+0x30); //个位要打括号(先算)
- print(0x04,"/"); // 显示年
- //
- print2(0x05,TIME[4]/16+0x30);
- print2(0x06,(TIME[4]&0x0f)+0x30);
- print(0x07,"/"); // 显示月
- //
- print2(0x08,TIME[3]/16+0x30);
- print2(0x09,(TIME[3]&0x0f)+0x30);
- print2(0x0b,TIME[2]/16+0x30);
- print2(0x0c,(TIME[2]&0x0f)+0x30);
- print(0x0d,":");
- ////小时
- print2(0x0e,TIME[1]/16+0x30);
- print2(0x0f,(TIME[1]&0x0f)+0x30);
- print(0x10,":");
- ////分钟
- print2(0x11,TIME[0]/16+0x30);
- print2(0x12,(TIME[0]&0x0f)+0x30);
- ////秒
- TIME_WW=TIME[5]&0x0f;
- print(0x46,"[");
- switch (TIME_WW){
- case 1:print(0x47,"Mon");break;
- case 2:print(0x47,"Tues");break;
- case 3:print(0x47,"Wed");break;
- case 4:print(0x47,"Thur");break;
- case 5:print(0x47,"Fri");break;
- case 6:print(0x47,"Sat");break;
- case 7:print(0x47,"Sun");break;
- default: print(0x47,"Error");break;
- } //显示星期
- if(TIME_WW==2||TIME_WW==4)
- print(0x4b,"]");
- else print(0x4a,"]");
-
- }
- }
- /*********************************************************************************************/
复制代码
|