久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3136|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

當(dāng)用DS1302讀取時間的時候,DHT11讀溫度時始終是0

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:120008 發(fā)表于 2016-5-11 11:59 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
我做了一個程序,要求顯示溫度濕度,記錄溫度的最大值以及溫度達(dá)到最大值的時間(年月日時分秒)。但是當(dāng)我不讀取時間的時候(也就是沒有DS1302Init()和DS1302ReadTime()的時候)溫度和濕度能正常刷新,但是一加入讀取時間的函數(shù)就發(fā)現(xiàn)溫度濕度全都變?yōu)?,而且一直都是零。球大神幫我看看代碼錯在哪了,是不是加入時間函數(shù)后讀取溫濕度的時序出了問題?該如何修改?



一共有三個文件,其中ds1302的兩個文件都是買單片機(jī)的時候自帶的,不會出問題,所以問題應(yīng)該出在tem.c和ds1302結(jié)合的時候tem.c的時序出了問題。
//DS1302.H
#ifndef __DS1302_H_
#define __DS1302_H_
//---包含頭文件---//
#include<reg51.h>
#include<intrins.h>
//---重定義關(guān)鍵詞---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//---定義ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;
//---定義全局函數(shù)---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局變量--//
extern uchar TIME[7]; //加入全局變量
#endif


//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時鐘初始化2013年1月1日星期二12點(diǎn)00分00秒。---//
//---存儲順序是秒分時日月周年,存儲格式是用BCD碼---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
//---定義ds1302使用的IO口---//
/*******************************************************************************
* 函 數(shù) 名         : Ds1302Write
* 函數(shù)功能     : 向DS1302寫命令(地址(控制字)+數(shù)據(jù),兩個字節(jié))
* 輸    入         : 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;//數(shù)據(jù)從低位開始傳送
  addr >>= 1;
  SCLK = 1;//數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  _nop_();
  SCLK = 0;
  _nop_();
}
for (n=0; n<8; n++)//寫入8位數(shù)據(jù)
{
  DSIO = dat & 0x01;
  dat >>= 1;
  SCLK = 1;//數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  _nop_();
  SCLK = 0;
  _nop_();
}
   
RST = 0;//傳送數(shù)據(jù)結(jié)束
_nop_();
}
/*******************************************************************************
* 函 數(shù) 名         : Ds1302Read
* 函數(shù)功能     : 讀取一個地址的數(shù)據(jù)
* 輸    入         : 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;//數(shù)據(jù)從低位開始傳送
  addr >>= 1;
  SCLK = 1;//數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  _nop_();
  SCLK = 0;//DS1302下降沿時,放置數(shù)據(jù)
  _nop_();
}
_nop_();
for(n=0; n<8; n++)//讀取8位數(shù)據(jù)
{
  dat1 = DSIO;//從最低位開始接收
  dat = (dat>>1) | (dat1<<7);
  SCLK = 1;
  _nop_();
  SCLK = 0;//DS1302下降沿時,放置數(shù)據(jù)
  _nop_();
}
RST = 0;
_nop_(); //以下為DS1302復(fù)位的穩(wěn)定時間,必須的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
* 函 數(shù) 名         : Ds1302Init
* 函數(shù)功能     : 初始化DS1302.
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00);   //禁止寫保護(hù),就是關(guān)閉寫保護(hù)功能
for (n=0; n<7; n++)//寫入7個字節(jié)的時鐘信號:分秒時日月周年
{
  Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80);   //打開寫保護(hù)功能
}
/*******************************************************************************
* 函 數(shù) 名         : Ds1302ReadTime
* 函數(shù)功能     : 讀取時鐘信息
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//讀取7個字節(jié)的時鐘信號:分秒時日月周年
{
  TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
  
}




//tem.c
#include"intrins.h"   //包含含有_nop_()的頭文件
#include"stdio.h"    //包含printf函數(shù)
#include"ds1302.h"
#define  uint   unsigned int
#define  uchar  unsigned char
uchar DHT11[5];
uchar FLAG;    //超時標(biāo)志位,工作原理是++至溢出256(uchar型)
uchar RTflag=0;
uchar display_flag=0;
sbit  dat=P3^7; //DHT11
sbit  RS=P2^6;
sbit  RW=P2^5;
sbit  EN=P2^7;  //LCD1602
sbit  k1=P3^0;  //k1,k2用來在攝氏度與華氏度之間切換
sbit  k2=P3^1;
sbit  k3=P3^2;
sbit  k4=P3^3;
uchar table[5];
uint  wd,sd;
uchar max_tem_time[7];
uchar min_tem_time[7];
uchar max_hum_time[7];
uchar min_hum_time[7];
uint  temperature ,tem_F;      
uint  humidity;
uint  max_tem = 0,max_tem_F = 0,min_tem = 99,min_tem_F = 0;
uint i = 0;
uint test = 0;

void UsartConfiguration()
{
SCON=0X50;   //設(shè)置串口為工作方式1
TMOD=0X20;   //設(shè)置計(jì)數(shù)器為工作方式2
PCON=0X80;   //波特率加倍
TH1=0XF3;   //計(jì)數(shù)器初始值設(shè)置,注意波特率是4800的
TL1=0XF3;
// ES=1;    //打開接收中斷
// EA=1;    //打開總中斷
TR1=1;    //打開計(jì)數(shù)器
}
void Delay_10us(void) //10us延時函數(shù)
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void delay(uint z)   // z毫秒延時函數(shù)
{
uint x,y;
for(x=z;x>0;x--)
     for(y=110;y>0;y--);
}
void lcd_write_com(uchar com) //1602寫指令
{
RS=0;
RW=0;
EN=1;
P0=com;
delay(1);   //延時1ms
EN=0;
}
void lcd_init() //1602初始化
{
lcd_write_com(0x38);   //設(shè)置16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
delay(1);
lcd_write_com(0x80);  //設(shè)置數(shù)據(jù)指針地址
delay(1);
lcd_write_com(0x01);  //1602清屏指令
delay(1);
lcd_write_com(0x06);  //當(dāng)讀或?qū)懸粋字符后,地址指針加1;當(dāng)寫一個字符,整屏顯示不移動
delay(1);
lcd_write_com(0x0C);  //開顯示,但不顯示光標(biāo)
delay(1);
}
void lcd_write_data(uchar date)//1602寫數(shù)據(jù)
{
RS=1;
RW=0;
EN=1;
P0=date;
delay(1);   //延時1ms
EN=0;
}
void write_str(uchar x,uchar y,uchar *s)//在LCD任意地址寫符號字母或數(shù)字,y是行,共兩行,x是該行的具體位置
{
if(y==0)            
  lcd_write_com(0x80+x);   //將數(shù)據(jù)寫在LCD的第一行
else
  lcd_write_com(0xc0+x);    //將數(shù)據(jù)寫在LCD的第二行
while(*s)
{
  lcd_write_data(*s);
  s++;
}
}
void write_shu(uchar x,uchar y,uchar num)//十位個位顯示函數(shù)
{
uchar s,g;   //s代表十位,g代表個位
if(y==0)
  lcd_write_com(0x80+x);
else
  lcd_write_com(0xc0+x);
s=num/10;     // 數(shù)據(jù)分離顯示
lcd_write_data(0x30+s);  //數(shù)據(jù)以ASCII碼寫入
g=num%10;     // 數(shù)據(jù)分離顯示
lcd_write_data(0x30+g);     //數(shù)據(jù)以ASCII碼寫入
}
void write_p(uchar x,uchar y,uchar num)//小數(shù)位顯示函數(shù)
{
uchar p;   //p代表小數(shù)   
if(y==0)
  lcd_write_com(0x80+x);
else
  lcd_write_com(0xc0+x);
p=num/10;   // 數(shù)據(jù)分離顯示
lcd_write_data(0x30+p);
}
uchar  write_byte1() //讀一個字節(jié)
{
uchar i,comdata,temp1;
for(i=0;i<8;i++)   
{
  FLAG=2;
  while((!dat)&&FLAG++);//判斷1bit開始數(shù)據(jù)的12-14us是否結(jié)束,當(dāng)dat為1時跳出while循環(huán)
  Delay_10us();
  Delay_10us();
  Delay_10us();
  Delay_10us();
  temp1=0;  //假設(shè)讀出的1bit數(shù)據(jù)是0                        
  if(dat)   //當(dāng)dat是1時,讀出的1bit數(shù)據(jù)是1
   temp1=1;  
  
  FLAG=2;   //FLAG設(shè)置成2是因?yàn)楸WCdat一直為1,不接受數(shù)據(jù)時,一直++,不至于一開始就break
     //等待下1bit開始
  while((dat)&&FLAG++);//flag先與后加1 如果dat一直為1 uchar型變量 flag 溢出變?yōu)?  再自加1  
  if(FLAG==1)break;  //超時則跳出for循環(huán)  
  comdata<<=1;//左移一位   高位在前  低位在后
  comdata|=temp1;    //comdata=(comdata|temp1)
}
return (comdata);  
}
void chuankou()
{
write_str(1,0,"Humi "); //第一行顯示濕度
write_shu(6,0,DHT11[0]);//顯示濕度十位個位   
write_str(8,0,".");  //顯示小數(shù)點(diǎn)     
write_p(9,0,DHT11[1]); //顯示濕度小數(shù)     
write_str(11,0,"RH"); //顯示濕度單位"RH"

if(k3==0)
{  
  Ds1302ReadTime();
     lcd_write_com(0x80);
     lcd_write_data('0'+TIME[2]/16);    //時
     lcd_write_data('0'+(TIME[2]&0x0f));     
     lcd_write_data('-');
     lcd_write_data('0'+TIME[1]/16);    //分
     lcd_write_data('0'+(TIME[1]&0x0f));
     lcd_write_data('-');
     lcd_write_data('0'+TIME[0]/16);    //秒
     lcd_write_data('0'+(TIME[0]&0x0f));
     lcd_write_data('2');
     lcd_write_data('0');
     lcd_write_data('0'+TIME[6]/16);   //年
     lcd_write_data('0'+(TIME[6]&0x0f));
     lcd_write_data('-');
     lcd_write_data('0'+TIME[4]/16);   //月
     lcd_write_data('0'+(TIME[4]&0x0f));
     lcd_write_data('-');
     lcd_write_data('0'+TIME[3]/16);   //日
     lcd_write_data('0'+(TIME[3]&0x0f));
   
  write_str(1,1,"maxT "); //第二行為顯示攝氏溫度  
  write_shu(6,1,max_tem);  
  write_str(8,1,".");     
  write_p(9,1,max_tem_F);      
  write_str(11,1,"^C");

  write_shu(14,1,test);
  delay(5000);
}

if(k1==0)     //讀取k1按鍵按下
{
  delay(5);     //延時10ms消抖動
  if(k1==0)     //確保k1按鍵按下
  {
   display_flag=1;
   //temperature=(int)(DHT11[2]*1.8+32);  //按下,顯示華氏溫度的整數(shù)位
   //tem_F=(int)((DHT11[2]*1.8+32)*10)%10; //按下,顯示華氏溫度的小數(shù)位
  }
  while(k1==0);//松手檢測
  delay(10);
  while(k1==0);
}
if(k2==0)
{
  delay(5);
  if(k2==0)
  {
   display_flag=0;
   //temperature=DHT11[2];     //不按,顯示攝氏溫度的整數(shù)位
   //tem_F=DHT11[3];       //不按,顯示攝氏溫度的小數(shù)位
  }
  while(k2==0);//松手檢測
  delay(10);
  while(k2==0);
}
if(display_flag==0)   //k1按鍵不按下
{
  write_str(1,1,"Temp "); //第二行為顯示攝氏溫度  
  write_shu(6,1,temperature);  
  write_str(8,1,".");     
  write_p(9,1,tem_F);      
  write_str(11,1,"^C");
}
else if(display_flag==1) //k1按鍵按下
{
  write_str(1,1,"Temp "); //第二行為顯示華氏溫度  
  write_shu(6,1,temperature);  
  write_str(8,1,".");     
  write_p(9,1,tem_F);      
  write_str(11,1,"^F");
}
}
void DHT11_Read_Data() //讀5個字節(jié)數(shù)據(jù)  兩個字節(jié)為溫度數(shù)據(jù)  兩個字節(jié)為濕度數(shù)據(jù) 最后一個字節(jié)為校驗(yàn)
{
uchar i,temp;
dat=0;   //dat為主機(jī)(單片機(jī))信號,可編程控制
delay(20);  //主機(jī)至少拉低18ms
dat=1;   //主機(jī)開始信號結(jié)束后拉高電平
//總線由上拉電阻拉高 主機(jī)拉高20-40us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主機(jī)設(shè)為輸入 判斷從機(jī)響應(yīng)信號(因?yàn)镈HT11的響應(yīng)電平無法編程控制,只能被動等待,被動檢測)
//檢測方法為:公用總線,dat同時表示單片機(jī)指令電平以及DHT11響應(yīng)電平
dat=1;
//判斷從機(jī)是否有低電平響應(yīng)信號 如不響應(yīng)則跳出,響應(yīng)則向下運(yùn)行   
if(!dat)   //dat=0時有低電平響應(yīng),進(jìn)入if函數(shù)  
{
  FLAG=2;    //超時標(biāo)志位  
  while((!dat)&&FLAG++);//判斷從機(jī)DHT發(fā)出的40-50us的低電平響應(yīng)信號是否結(jié)束
  /*FLAG的作用為防止響應(yīng)超時,理解如下:根據(jù)時序圖,此時dat應(yīng)該是低電平,
  如果dat變成高電平,那么之后開始記錄數(shù)據(jù),F(xiàn)LAG++是while循環(huán)的判斷條件
  幫助跳出這個循環(huán),F(xiàn)LAG是uchar類型,正常是最多到255就溢出,單步執(zhí)行一次是6us,
  若DHT11死機(jī),則此次數(shù)據(jù)讀取失敗,若不加這個超時標(biāo)志位,則永遠(yuǎn)死在while循環(huán)
  但是加了這個FLAG,DHT11死機(jī)后,F(xiàn)LAG在1500us=1.5ms后就溢出,溢出則為0*/
  FLAG=2;  
  while((dat)&&FLAG++); //判斷從機(jī)DHT11拉高40-50us是否結(jié)束
  //開始接收數(shù)據(jù)
  for(i=0;i<5;i++)//數(shù)據(jù)接收狀態(tài)
  {
   DHT11[i]=write_byte1();
  }   
  dat=1; //釋放數(shù)據(jù)總線  為下一次讀取做好準(zhǔn)備
  
  temp=(DHT11[0]+DHT11[1]+DHT11[2]+DHT11[3]);
  test = DHT11[2];
  if(DHT11[2] + DHT11[3]/10 > max_tem + max_tem_F/10)
  {
   max_tem = DHT11[2];      
   max_tem_F = DHT11[3];
   //Ds1302ReadTime();
  }
  if(DHT11[2] + DHT11[3]/10 < min_tem + min_tem_F/10)
  {
   min_tem = DHT11[2];      
   min_tem_F = DHT11[3];
   //Ds1302ReadTime();
  }
  if (display_flag == 0)
  {
   humidity   =DHT11[0];
   temperature=DHT11[2];
   tem_F      =DHT11[3];
  }
  else
  {
   humidity   =DHT11[0];
   temperature=(int)(DHT11[2]*1.8+32);  //按下,顯示華氏溫度的整數(shù)位
   tem_F=(int)((DHT11[3]*1.8+32)*10)%10;
  }

  if(temp==DHT11[4]) //數(shù)據(jù)校驗(yàn)         
   RTflag=1;
  if(RTflag==1) //如果RTflag=1 說明讀取到得數(shù)據(jù)正確
  {     
   RTflag=0;  //為下次進(jìn)行數(shù)據(jù)校驗(yàn)做準(zhǔn)備  
   chuankou();
  }
}
}
void main()
{   
UsartConfiguration();
lcd_init();  //1602初始化
k1 = 1;
k2 = 1;
k3 = 1;
k4 = 1;
Ds1302Init();
delay(3000); //等待DHT11溫濕度傳感器數(shù)據(jù)穩(wěn)定  開始激活DHT11
while(1)//循環(huán)讀取  并更新數(shù)據(jù)顯示
{
     delay(100);//等待DHT11溫濕度傳感器數(shù)據(jù)穩(wěn)定  開始激活DHT11
  DHT11_Read_Data(); //讀數(shù)據(jù)  
  delay(100); //延時等待  
}
}

評分

參與人數(shù) 1黑幣 +30 收起 理由
admin + 30

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 欧美 中文字幕 | 成人一区二区在线 | 免费同性女女aaa免费网站 | 欧美二区三区 | 精品一区二区三区在线观看国产 | 91久久婷婷| 韩日视频在线观看 | 亚洲精品久久国产高清情趣图文 | 色天天综合 | 91精产国品一二三区 | 国产视频第一页 | 91操操操 | 久久久高清 | 最新中文字幕 | 日韩成人久久 | 欧美国产日韩在线观看 | 福利国产| 99国产精品久久久久 | 91精品中文字幕一区二区三区 | 国产一区二区久久 | 97超碰成人| 99久久精品免费看国产高清 | 免费a大片| 欧美日本在线观看 | 丁香五月网久久综合 | 日日拍夜夜 | 夜久久 | 成人av网站在线观看 | 午夜免费在线电影 | 综合欧美亚洲 | 精品久久久久久红码专区 | 在线观看 亚洲 | 91豆花视频| 亚洲人成免费 | 国产免费视频在线 | 久久综合久 | 91久久精品日日躁夜夜躁国产 | av大片在线| 在线观看亚洲 | 九九色综合 | 欧美一区二区三区在线观看 |