普中开源电子分享网

 找回密码
 立即注册
搜索
查看: 20531|回复: 18

LCD1602不能同时显示温度和时间的问题

 关闭 [复制链接]

1

主题

5

帖子

33

积分

新手上路

Rank: 1

积分
33
发表于 2017-3-29 09:29:15 | 显示全部楼层 |阅读模式
本帖最后由 liujinming 于 2017-3-30 09:15 编辑

程序目标:1602第一行显示温度,第二行显示时间。温度用DS18B20,时间用DS1302。
目前存在问题:用1602单独显示温度和时间都没得问题。合在一起显示就出现温度值为0,时间可以正常显示。初步怀疑是我的main函数写法不对。请大家帮忙分析一下有到底有什么问题。谢谢~ 各个驱动程序都是用的普中的驱动程序,个人只修改了数据处理函数和main函数。板子用的普中51开发板。

以下为程序,只有.C文件,头文件未包含,全部程序附在打包文件里面:

一、主程序  main.c
/**************************************************************************************
*                              LCD1602液晶显示实验                                                                                                  *
实现现象:下载程序后插上LCD1602液晶在开发板上,即可显示
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。                                                                                                                                                                  
***************************************************************************************/

#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"
#include "temp.h"
#include <intrins.h>
#include "DS1302.H"

typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;

//u8 Disp[]="0Pechin Scien0e ";

//u8 Disp[8];
u8 DisplayData[9];
u16 DisplayDataTime[9];
bit TempDs18b20Flag;
bit Ds1302Flag;



/*******************************************************************************
* 函 数 名         : delay
* 函数功能                   : 延时函数
*******************************************************************************/
void delay1ms(void)   //误差 0us 延时1ms
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}

void delayxms(u8 x)//延时X个ms
{
        unsigned char a,b;
        for(b=x;b>0;b--)
        {
                delay1ms();
        }
}
        
/*******************************************************************************
* 函 数 名         : dataprosTime()
* 函数功能                   : 时间读取处理转换函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void dataprosTime()         
{
           Ds1302ReadTime();
        DisplayDataTime[0] = TIME[2]/16+0x30;                                //时
        DisplayDataTime[1] = TIME[2]%16+0x30;                                 
        DisplayDataTime[2] = 0x2d;//0100 0000
        DisplayDataTime[3] = TIME[1]/16+0x30;                                //分
        DisplayDataTime[4] = TIME[1]%16+0x30;        
        DisplayDataTime[5] = 0x2d;
        DisplayDataTime[6] = TIME[0]/16+0x30;                                //秒
        DisplayDataTime[7] = TIME[0]%16+0x30;
}

/*******************************************************************************
* 函 数 名         : datapros()
* 函数功能                   : 温度读取处理转换函数
* 输    入         : temp
* 输    出         : 无
*******************************************************************************/

void datapros(int temp)         
{
        //int temp;        
        //temp=Ds18b20ReadTemp();
        
           float tp;  
        if(temp< 0)                                //当温度值为负数
          {
                DisplayData[0] = 0x2d;           //   - 0010 1101
                //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
                temp=temp-1;
                temp=~temp;
                tp=temp;
                temp=tp*0.0625*100+0.5;        
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。

          }
         else
          {                        
                DisplayData[0] = 0x2b;//第0位数据,正温度第0位+号,00101011
                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
                //如果温度是正的那么,那么正数的原码就是补码它本身
                temp=tp*0.0625*100+0.5;        
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算加上0.5,还是在小数点后面。
          }
                                
        DisplayData[1] = temp / 10000;//开发板左边数第三个数码管,前面扩大100倍,这里除以10000,取百位数字
        DisplayData[2] = temp % 10000 / 1000+0x30;//先取余数,再除以1000,取十位数字
        DisplayData[3] = temp % 1000 / 100+0x30;// | 0x80;//取个位数字,再加上小数点标识0x80
        DisplayData[4] = 0x2e;//小数点
               
        DisplayData[5] = temp % 100 / 10+0x30;//取小数点后1位
        DisplayData[6] = temp % 10+0x30;//取小数点后2位
                DisplayData[7] = 0xdf;//1101 1111 °
                DisplayData[8] = 0x43;//0100 0011 C
        
                if(DisplayData[1]==0)//如果温度没有上百,则显示空白位
                {
                        DisplayData[1]=0x20;//显示空白
                }
                else
                {
                        DisplayData[1] = temp / 10000+0x30;//上百则显示ASCII数字
                }        
               
}


/*******************************************************************************
* 函 数 名         : main
* 函数功能                   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void main(void)
{
                u8 i;        

        LcdInit();//LCD初始化

        Ds1302Init();//1302初始化

        while(1)
        {        

                datapros(Ds18b20ReadTemp());//温度数据处理函数
                  LcdWriteCom(0x80); //显示第1行
                for(i=0;i<9;i++)
        {
                LcdWriteData(DisplayData[ i ]);        //温度数据送LCD显示
        }


/*························································································*/        

        dataprosTime();//DS1302时间数据处理
        LcdWriteCom(0xC0); //显示第2行

        for(i=0;i<8;i++)
        {
                LcdWriteData(DisplayDataTime[ i ]);        //时间数据送LCD显示
        }

        delayxms(100);//延时100ms        
        LcdWriteCom(0x02);  //撤回左上角  0000 0010

                }

}

/////////////////////////////////////////////////////////////////////////////////////////


二、驱动程序DS1302.C

//长度超了,具体程序见附件

三、温度驱动程序 DS18B20.C
//长度超了,具体见打包附件




四、LCD驱动程序 1602.C

//长度超了,具体见打包附件


//程序结束



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

20

主题

1344

帖子

8383

积分

论坛元老

Rank: 8Rank: 8

积分
8383
发表于 2017-4-28 10:17:04 | 显示全部楼层
liujinming 发表于 2017-4-5 09:19
只有以上教程语句也是不够的,仍然不能同时显示。你们可以实测一下。

同学们,我只需要修改一个地方就可以了!!!!
首先,要感谢你,试验出了正确的结果!
在你的结果基础之上,我反复阅读程序,注意到,你的红色部分程序,其实就是1302的使能为高电平。
所以,最终的结果是:
在1302读数据之后,将原程序中的使能为低电平去掉,就可以了。
即:
原程序:
unsigned char Ds1302Read(unsigned char addr)//从DS1302读单字节数据
{
        unsigned char n,dat,dat1;//n为8位计数,dat为最终返回的数据
                                                        //dat1为接收的一位数据
        CE = 0;
        _nop_();

        SCLK = 0;//先将SCLK置低电平。
        _nop_();
        CE = 1;//然后将CE置高电平。
        _nop_();

        for(n=0; n<8; n++)//开始传送八位地址命令
        {
                DSIO = addr & 0x01;//数据从低位开始传送
                addr >>= 1;
                SCLK = 1;//数据在上升沿时,DS1302读取数据
                _nop_();
                SCLK = 0;//DS1302下降沿时,放置数据
                _nop_();
        }
        _nop_();
        for(n=0; n<8; n++)//读取8位数据
        {
                dat1 = DSIO;//从最低位开始接收
                dat = (dat>>1) | (dat1<<7);//此处可以用595的方法判断是0或是1
                SCLK = 1;
                _nop_();
                SCLK = 0;//DS1302下降沿时,放置数据
                _nop_();
        }

//        CE = 0;
        _nop_();//以下为DS1302复位的稳定时间,必须的。
        SCLK = 1;
        _nop_();
        DSIO = 0;
        _nop_();
        DSIO = 1;
        _nop_();

        return dat;       
}

红色那一条语句,原来有,现在我将它去掉,就好了。其它的什么都不用改。

究其原因,可能是两器件使能冲突。
回复 支持 1 反对 0

使用道具 举报

6

主题

24

帖子

106

积分

注册会员

Rank: 2

积分
106
发表于 2017-3-29 21:45:24 | 显示全部楼层
从程序来看,你定义的DisplayData[9] 为存放温度值的数组,
将LcdWriteData(DisplayData);        //温度数据送LCD显示
修改为LcdWriteData(DisplayData[i]); 即可
回复 支持 反对

使用道具 举报

1

主题

5

帖子

33

积分

新手上路

Rank: 1

积分
33
 楼主| 发表于 2017-3-30 09:13:03 | 显示全部楼层
本帖最后由 liujinming 于 2017-3-30 09:14 编辑
远征之路 发表于 2017-3-29 21:45
从程序来看,你定义的DisplayData[9] 为存放温度值的数组,
将LcdWriteData(DisplayData);        //温 ...

我查了keil里面程序:“LcdWriteData(DisplayData[ i ]);    //温度数据送LCD显示”  main函数里面是有“ [ i] ”,不知道怎么复制上来就没有了。。
昨天晚上再次调试了一下,发现只要屏蔽  DS1302初始化函数 ,温度值就可以正常显示。
回复 支持 反对

使用道具 举报

1

主题

5

帖子

33

积分

新手上路

Rank: 1

积分
33
 楼主| 发表于 2017-3-30 22:52:31 | 显示全部楼层
有木有伙伴用普中板子LCD1602 做过DS1302和 DS18B20的综合程序呀  
回复 支持 反对

使用道具 举报

1

主题

5

帖子

33

积分

新手上路

Rank: 1

积分
33
 楼主| 发表于 2017-4-4 23:06:42 | 显示全部楼层
本帖最后由 liujinming 于 2017-4-4 23:09 编辑

问题终于解决了,虽然不知道为什么,现在总算实现了同时显示温度和时间了。
关键点是写地址读数据函数,多添加几条指令,加粗红色字体代码,如下:

uint8 read_1302(uint8 addr)//先向1302写地址,再读数据
{
uint8  dat;
RST=0;
_nop_();
CLCK=0;
_nop_();
RST=1;
_nop_();
DS1302WriteByte(addr);//写地址
dat=DS1302RradByte();//读数据
CLCK=1;
_nop_();
CLCK=0;
_nop_();

RST=0;
_nop_();
  RST=1;
_nop_();
  _nop_();
IO = 0;
_nop_();
IO = 1;
_nop_();

return dat;

}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

20

主题

1344

帖子

8383

积分

论坛元老

Rank: 8Rank: 8

积分
8383
发表于 2017-4-5 09:13:35 | 显示全部楼层
liujinming 发表于 2017-4-4 23:06
问题终于解决了,虽然不知道为什么,现在总算实现了同时显示温度和时间了。
关键点是写地址读数据函数,多 ...

教程中是说清楚了的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

1

主题

5

帖子

33

积分

新手上路

Rank: 1

积分
33
 楼主| 发表于 2017-4-5 09:19:04 | 显示全部楼层
HC6800-ES-V2.0 发表于 2017-4-5 09:13
教程中是说清楚了的。

只有以上教程语句也是不够的,仍然不能同时显示。你们可以实测一下。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2017-4-27 12:37:06 | 显示全部楼层
找了好久的错误,没找出来  按照你的改完就好了  确实语句问题,教程上的温度时间不能同时显示 谢谢
回复 支持 反对

使用道具 举报

1

主题

8

帖子

37

积分

新手上路

Rank: 1

积分
37
发表于 2017-9-25 19:33:11 | 显示全部楼层
HC6800-ES-V2.0 发表于 2017-4-28 10:17
同学们,我只需要修改一个地方就可以了!!!!
首先,要感谢你,试验出了正确的结果!
在你的结果基础 ...

您好,终于找到这个帖子,解决了我那么长时间的困惑,好激动啊!

我这里还要一个问题请帮忙看下是否是硬件的bug。

当给1302初始化的时候,如果将秒和分中的至少一个初始化为30,那么将会对显示的文字产生影响,导致乱码。具体如我照片中所示,乱码的文字本来对应的应该是一个固定显示的Temper:。

不知是否有人碰到过这个问题。

void DS1302Init()
{
        DS1302write(0x8E,0x00);                //关闭写保护
        DS1302write(0x8C,0x17);                //设置年为17
        DS1302write(0x8A,0x07);                //设置星期为7
        DS1302write(0x88,0x09);                //设置月份为09
        DS1302write(0x86,0x24);                //设置日期为24
        DS1302write(0x84,0x12);                //设置小时为17,24小时制
        DS1302write(0x82,0x00);                //设置分钟为0                                          //***** 这一位不能设置为3,LCD显示会乱码
        DS1302write(0x80,0x30);                //设置秒为00,并启动计时                //***** 这一位不能设置为3,LCD显示会乱码
        DS1302write(0x8e,0x80);                //打开写保护
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

Archiver|手机版|小黑屋|普中开源电子分享网 粤ICP备16123577号-2

GMT+8, 2024-4-30 10:18 , Processed in 0.124459 second(s), 32 queries .

Powered by 论坛搭建 X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表