lcd和服务器同时显示温度,为什么LCD1602不能同时显示温度和时间?
程序目標:1602第一行顯示溫度,第二行顯示時間。溫度用DS18b20,時間用DS1302。
目前存在問題:用1602單獨顯示溫度和時間都沒得問題。合在一起顯示就出現溫度值為0,時間可以正常顯示。
初步懷疑是我的main函數寫法不對。請大家幫忙分析一下有到底有什么問題。謝謝~
硬件電路:用的51單片機STC89C52,LCD1602,DS18B20,DS1302。后門附圖。
以下為程序,只有.C文件,頭文件未包含,全部程序附在打包文件里面:
一、主程序??main.c
/**************************************************************************************
*? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?LCD1602液晶顯示實驗? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???*
實現現象:下載程序后插上LCD1602液晶在開發板上,即可顯示
注意事項:如果不想讓點陣模塊顯示,可以將74HC595模塊上的JP595短接片拔掉。
***************************************************************************************/
#include "reg52.h"? ?? ?? ?? ?? ?? ?? ?? ? //此文件中定義了單片機的一些特殊功能寄存器
#include "lcd.h"
#include "temp.h"
#include
#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
#include "ds1302.h"
//---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_();
SCLK = 0;//先將SCLK置低電平。
_nop_();
RST = 1; //然后將RST(CE)置高電平。
_nop_();
for (n=0; n<8; n++)//開始傳送八位地址命令
{
DSIO = addr & 0x01;//數據從低位開始傳送
addr >>= 1;
SCLK = 1;//數據在上升沿時,DS1302讀取數據
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//寫入8位數據
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//數據在上升沿時,DS1302讀取數據
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//傳送數據結束
_nop_();
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds1302Read
* 函數功能? ?? ?? ?? ?? ?? ? : 讀取一個地址的數據
* 輸? ? 入? ?? ?? ?: addr
* 輸? ? 出? ?? ?? ?: dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先將SCLK置低電平。
_nop_();
RST = 1;//然后將RST(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);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿時,放置數據
_nop_();
}
RST = 0;
_nop_();? ?? ???//以下為DS1302復位的穩定時間,必須的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_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]);
}
Ds1302Write(0x8E,0x80);? ?? ?? ?? ?? ???//打開寫保護功能
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds1302ReadTime
* 函數功能? ?? ?? ?? ?? ?? ? : 讀取時鐘信息
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//讀取7個字節的時鐘信號:分秒時日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
三、溫度驅動程序 DS18B20.C
#include "temp.h"
/*******************************************************************************
* 函 數 名? ?? ?? ?: Delay1ms
* 函數功能? ?? ?? ?? ?? ?? ? : 延時函數
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
void Delay1ms(uint y)
{
uint x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20Init
* 函數功能? ?? ?? ?? ?? ?? ? : 初始化
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 初始化成功返回1,失敗返回0
*******************************************************************************/
uchar Ds18b20Init()
{
uchar i;
DSPORT = 0;? ?? ?? ?? ?? ?? ?? ?? ? //將總線拉低480us~960us
i = 70;
while(i--);//延時642us
DSPORT = 1;? ?? ?? ?? ?? ?? ?? ?? ?//然后拉高總線,如果DS18B20做出反應會將在15us~60us后總線拉低
i = 0;
while(DSPORT)? ?? ???//等待DS18B20拉低總線
{
Delay1ms(1);
i++;
if(i>5)//等待>5MS
{
return 0;//初始化失敗
}
}
return 1;//初始化成功
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20WriteByte
* 函數功能? ?? ?? ?? ?? ?? ? : 向18B20寫入一個字節
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
void Ds18b20WriteByte(uchar dat)
{
uint i, j;
for(j=0; j<8; j++)
{
DSPORT = 0;? ?? ?? ?? ?? ?? ?? ???//每寫入一位數據之前先把總線拉低1us
i++;
DSPORT = dat & 0x01;??//然后寫入一個數據,從最低位開始
i=6;
while(i--); //延時68us,持續時間最少60us
DSPORT = 1;? ?? ???//然后釋放總線,至少1us給總線恢復時間才能接著寫入第二個數值
dat >>= 1;
}
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20ReadByte
* 函數功能? ?? ?? ?? ?? ?? ? : 讀取一個字節
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
uchar Ds18b20ReadByte()
{
uchar byte, bi;
uint i, j;
for(j=8; j>0; j--)
{
DSPORT = 0;//先將總線拉低1us
i++;
DSPORT = 1;//然后釋放總線
i++;
i++;//延時6us等待數據穩定
bi = DSPORT;? ?? ?? ?//讀取數據,從最低位開始讀取
/*將byte左移一位,然后與上右移7位后的bi,注意移動之后移掉那位補0。*/
byte = (byte >> 1) | (bi << 7);
i = 4;? ?? ?? ?? ?? ? //讀取完之后等待48us再接著讀取下一個數
while(i--);
}
return byte;
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20ChangTemp
* 函數功能? ?? ?? ?? ?? ?? ? : 讓18b20開始轉換溫度
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
void??Ds18b20ChangTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);? ?? ?? ?? ?? ? //跳過ROM操作命令
Ds18b20WriteByte(0x44);? ?? ?? ?? ?//溫度轉換命令
//Delay1ms(100);? ?? ???//等待轉換成功,而如果你是一直刷著的話,就不用這個延時了
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20ReadTempCom
* 函數功能? ?? ?? ?? ?? ?? ? : 發送讀取溫度命令
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
void??Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc);? ?? ?? ?//跳過ROM操作命令
Ds18b20WriteByte(0xbe);? ?? ?? ?//發送讀取溫度命令
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: Ds18b20ReadTemp
* 函數功能? ?? ?? ?? ?? ?? ? : 讀取溫度
* 輸? ? 入? ?? ?? ?: 無
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
int Ds18b20ReadTemp()
{
int temp = 0;
uchar tmh, tml;
Ds18b20ChangTemp();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//先寫入轉換命令
Ds18b20ReadTempCom();? ?? ?? ?? ?? ?? ?? ?? ?//然后等待轉換完后發送讀取溫度命令
tml = Ds18b20ReadByte();? ?? ?? ?? ?? ? //讀取溫度值共16位,先讀低字節
tmh = Ds18b20ReadByte();? ?? ?? ?? ?? ? //再讀高字節
temp = tmh;
temp <<= 8;
temp |= tml;
return temp;
}
四、lcd驅動程序 1602.C
#include "lcd.h"
/*******************************************************************************
* 函 數 名? ?? ?? ?: Lcd1602_Delay1ms
* 函數功能? ?? ?? ?? ?? ?? ? : 延時函數,延時1ms
* 輸? ? 入? ?? ?? ?: c
* 輸? ? 出? ?? ?? ?: 無
* 說? ? 名? ?? ?? ?: 該函數是在12MHZ晶振下,12分頻單片機的延時。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c)? ?//誤差 0us??1ms延時
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 數 名? ?? ?? ?: LcdWriteCom
* 函數功能? ?? ?? ?? ?? ?? ? : 向LCD寫入一個字節的命令
* 輸? ? 入? ?? ?? ?: com
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
#ifndef? ?? ?? ?LCD1602_4PINS? ?? ?? ?//當沒有定義這個LCD1602_4PINS時,執行八位數據線,寫入程序
void LcdWriteCom(uchar com)? ?? ?? ? //寫入命令
{
LCD1602_E = 0;? ???//使能
LCD1602_RS = 0;? ?? ?? ???//選擇發送命令
LCD1602_RW = 0;? ?? ?? ???//選擇寫入
LCD1602_DATAPINS = com;? ???//放入命令
Lcd1602_Delay1ms(1);? ?? ?? ?? ?? ? //等待數據穩定
LCD1602_E = 1;? ?? ?? ?? ?? ?? ?//寫入時序
Lcd1602_Delay1ms(5);? ?? ?? ? //保持時間
LCD1602_E = 0;
}
#else //有定義這個LCD1602_4PINS時,執行以下四位數據線寫入程序,以下未執行
void LcdWriteCom(uchar com)? ?? ?? ? //寫入命令
{
LCD1602_E = 0;? ?? ?? ?//使能清零
LCD1602_RS = 0;? ?? ?? ?//選擇寫入命令
LCD1602_RW = 0;? ?? ?? ?//選擇寫入
LCD1602_DATAPINS = com;? ?? ???//由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1;? ?? ?? ?//寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //發送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1;? ?? ?? ?//寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名? ?? ?? ?: LcdWriteData
* 函數功能? ?? ?? ?? ?? ?? ? : 向LCD寫入一個字節的數據
* 輸? ? 入? ?? ?? ?: dat
* 輸? ? 出? ?? ?? ?: 無
*******************************************************************************/
#ifndef? ?? ?? ?LCD1602_4PINS? ?? ?? ?? ?? ?? ? //四位數據,開發板用的八位數據
void LcdWriteData(uchar dat)? ?? ?? ?? ?? ?? ?? ?? ?//寫入數據
{
LCD1602_E = 0;? ?? ???//使能清零
LCD1602_RS = 1;? ?? ???//選擇輸入數據
LCD1602_RW = 0;? ?? ???//選擇寫入
LCD1602_DATAPINS = dat; //寫入數據
Lcd1602_Delay1ms(1);
LCD1602_E = 1;? ?//寫入時序
Lcd1602_Delay1ms(5);? ?//保持時間
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)? ?? ?? ?? ?? ?? ?? ?? ?//寫入數據 8位數據 以下未執行
{
LCD1602_E = 0;? ?? ?? ? //使能清零
LCD1602_RS = 1;? ?? ?? ? //選擇寫入數據
LCD1602_RW = 0;? ?? ?? ? //選擇寫入
LCD1602_DATAPINS = dat;? ?? ???//由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1;? ?? ?? ? //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //寫入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1;? ?? ?? ? //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名? ?? ? : LcdInit()
* 函數功能? ?? ?? ?? ?? ???: 初始化LCD屏
* 輸? ? 入? ?? ? : 無
* 輸? ? 出? ?? ? : 無
*******************************************************************************/
#ifndef? ?? ?? ?? ?? ? LCD1602_4PINS
void LcdInit()? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//LCD初始化子程序 開發板是八位數據
{
LcdWriteCom(0x38);??//功能設置指令 0011 1000,采用幾位數據線
LcdWriteCom(0x0c);??//開顯示不顯示光標 0000 1100
LcdWriteCom(0x06);??//寫一個指針加1 0000 0110
LcdWriteCom(0x01);??//清屏??0000 0001
//LcdWriteCom(0x80);??//設置數據指針起點 1000 0000,顯示位置起點默認增加00H+80H表示第一行。40H+80H=C0H表示第二行
}
#else
void LcdInit()? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//LCD初始化子程序四位數據線,開發板是八位數據,以下未執行
{
LcdWriteCom(0x32);? ?? ?? ?//將8位總線轉為4位總線
LcdWriteCom(0x28);? ?? ?? ?//在四位線下的初始化
LcdWriteCom(0x0c);??//開顯示不顯示光標
LcdWriteCom(0x06);??//寫一個指針加1
LcdWriteCom(0x01);??//清屏
LcdWriteCom(0x80);??//設置數據指針起點
}
#endif
//程序結束
LCD1602不帶轉接板 8位 -溫度和時間.zip (74.96 KB )
0
總結
以上是生活随笔為你收集整理的lcd和服务器同时显示温度,为什么LCD1602不能同时显示温度和时间?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css长图如何展示局部,css可以设置图
- 下一篇: ajax 返回数组某个属性值,js中so