大神你好! 我用18B20采集溫度數據然后通過Hc05藍牙模塊把溫度發送到手機上。 我同時使用串口中斷和定時器0中斷,當我把發送溫度數據函數 放在 定時器0中斷里面時,數碼管顯示溫度數據出現了錯位的現象,奇怪的是我在定時器0中斷里面寫一個led燈亮滅程序時并不會出現以上的情況。 后來我把發送溫度數據的函數和數碼管顯示一起放在了main函數里就解決了這個問題。 但是我還是很疑惑,為什么把發送溫度數據的函數放在定時器0中斷里會出錯,很想知道他的原理,求解答, 補充一點: 只有當中斷0開始執行溫度發送數據時才會出現錯誤,一開始定時器計數時并不會錯 PS:問題及程序如下 #include <reg52.h>
#define uchar unsigned char
code unsigned char seg7code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //不帶小數點的共陽數碼管段碼 code unsigned char seg7codeB[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //帶小數點的共陽數碼管段碼 code unsigned char t[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
sbit en=P1^0; sbit DQ=P3^6; sbit s= P2^5; sbit z= P2^7; //數據傳輸線接單片機的相應的引腳 unsigned char tempL=0; //設全局變量 unsigned char tempH=0; typedef unsigned char u8; u8 a; unsigned int sdata; //測量到的溫度的整數部分 unsigned char xiaoshu1; //小數第一位 unsigned char xiaoshu2; //小數第二位 unsigned char xiaoshu; //兩位小數 unsigned char time; // bit fg=1; //溫度正負標志
void delay(unsigned char i) { for(i;i>0;i--); } void delay1(uchar i) { uchar j,k; for(j=i;j>0;j--) { for(k=125;k>0;k--);} } void Init_DS18B20(void) { unsigned char x=0; DQ=1; //DQ先置高 delay(8); //稍延時 DQ=0; //發送復位脈沖 delay(80); //延時(>480us) DQ=1; //拉高數據線 delay(5); //等待(15~60us) x=DQ; //用X的值來判斷初始化有沒有成功,18B20存在的話X=0,否則X=1 delay(20); } //讀一個字節 ReadOneChar(void) //主機數據線先從高拉至低電平1us以上,再使數據線升為高電平,從而產生讀信號 { unsigned char i=0; //每個讀周期最短的持續時間為60us,各個讀周期之間必須有1us以上的高電平恢復期 unsigned char dat=0; for (i=8;i>0;i--) //一個字節有8位 { DQ=1; delay(1); DQ=0; dat>>=1; DQ=1; if(DQ) dat|=0x80; delay(4); } return(dat); }
//寫一個字節 void WriteOneChar(unsigned char dat) { unsigned char i=0; //數據線從高電平拉至低電平,產生寫起始信號。15us之內將所需寫的位送到數據線上, for(i=8;i>0;i--) //在15~60us之間對數據線進行采樣,如果是高電平就寫1,低寫0發生。 { DQ=0; //在開始另一個寫周期前必須有1us以上的高電平恢復期。 DQ=dat&0x01; delay(5); DQ=1; dat>>=1; } delay(4); }
//讀溫度值(低位放tempL;高位放tempH;) void ReadTemperature(void) { Init_DS18B20(); //初始化 WriteOneChar(0xcc); //跳過讀序列號的操作 WriteOneChar(0x44); //啟動溫度轉換 delay(125); //轉換需要一點時間,延時 Init_DS18B20(); //初始化 WriteOneChar(0xcc); //跳過讀序列號的操作 WriteOneChar(0xbe); //讀溫度寄存器(頭兩個值分別為溫度的低位和高位) tempL=ReadOneChar(); //讀出溫度的低位LSB tempH=ReadOneChar(); //讀出溫度的高位MSB if(tempH>0x7f) //最高位為1時溫度是負 { tempL=~tempL; //補碼轉換,取反加一 tempH=~tempH+1; fg=0; //讀取溫度為負時fg=0 } sdata = tempL/16+tempH*16; //整數部分 xiaoshu1 = (tempL&0x0f)*10/16; //小數第一位 xiaoshu2 = (tempL&0x0f)*100/16%10; //小數第二位 xiaoshu=xiaoshu1*10+xiaoshu2; //小數兩位 }
//顯示函數 void Led(unsigned int date) { if(fg==1) { P2=0xfe; //選通第一位 P0=seg7code[date/10]; //十位數,查表,輸出 delay1(1); P0=0xff; //消隱 P2=0xfd; //選通第二位,個位數 P0=seg7codeB[date%10]; delay1(1); P0=0xff; //消隱 P2=0xfb; //選通第三位,小數點第一位 P0=seg7code[xiaoshu1]; delay1(1); P0=0xff; //消隱 P2=0xf7; //選通第四位,小數點第二位 P0=seg7code[xiaoshu2]; delay1(1); P0=0xff; //消隱 } if(fg==0) //溫度為負時顯示的數據 { P2=0xfe; //選通第一位 P0=seg7code[11]; //顯示負號 delay1(1); P0=0xff; //消隱 P2=0xfd; //選通第二位,十位數 P0=seg7code[date/10]; delay1(1); P0=0xff; //消隱 P2=0xfb; //選通第三位,個位數 P0=seg7codeB[date%10]; delay1(1); P0=0xff; //消隱 P2=0xf7; //選通第四位,小數點第一位 P0=seg7code[xiaoshu1]; delay1(1); P0=0xff; //消隱 } } //串口模塊 初始化 + 定時器初始化 void Init_serial(void) { TMOD = 0x21; SCON = 0x50; PCON = 0x00; //串口中斷 TH1 = 0xfd; TL1 = 0xfd; TR1 = 1; //定時器中斷 TH0 = (65536-46083)/256; TL0 = (65536-46083)%256; TR0 = 1; //中斷開關 EA = 1; ES = 1; ET0= 1; en = 1;
}
void serial_s(char dat) //串口發送程序 { // a=0; SBUF = dat; while(!TI); TI = 0; } main() { Init_serial();
while(1) { ReadTemperature(); //讀取溫度 Led(sdata); //溫度顯示在數碼管上
} }
void rxd(void) interrupt 4 //串口中斷 接收程序 { EA=0; if(RI) { RI=0; a=SBUF; if(a=='0') { s=0; delay(20); } if(a=='f') { z=0; delay(20); } } EA=1; }
void txd(void) interrupt 1 //定時器程序,沒10S通過藍牙給手機發送溫度數據 { time++; if(time==20) { serial_s(t[sdata/10]); serial_s(t[sdata%10]); serial_s('.'); serial_s(t[xiaoshu1]); serial_s(t[xiaoshu2]); serial_s('\n'); } TH0=(65536-46083)/256; TL0=(65536-46083)%256; }
|