void main()//主函數
{
delay1ms(1000);
lcd_init();//液晶顯示初始化
init_play();
while(1)
{
EA=0; //因DS18B20對時序要求高且受中斷影響,故先關閉總中斷
read_temp();//讀取溫度
ds1820disp();//顯示
CT_init();//定時計數器初始化
EA=1;//開總中斷
EX0=1;//允許外部中斷
IT0=1;//設置外部中斷方式為下降沿觸發
P3=0xff;
t0=(u*65536+x)*(12/22.1);//計算脈沖時間寬度(單位:ms)
f=1000000/(2*t0);//計算頻率
if(f>8000&&tflag==1)
init_play1(); //顯示Frozen
else init_play2(); //顯示Not frozen
}
}
這是主函數,初步懷疑是中斷測頻率時和溫度傳感器讀取數據相影響,怎么解決 ?
方法1:讀頻率實時性要求不高的話,就開這個關那個,輪流來,其他沒招了
先測1秒溫度,然后測1秒頻率,再測一秒溫度?
方法2:我給你個參考程序,也是單總線的數據采集(時鐘11.0592)。
在你的主循環中不要關閉中斷,調用讀溫度時,有校驗碼確定數據的有效性(如果讀溫度程序中間有中斷,數據可能會是無效的)。
#include <INTRINS.H>
#include "public.h"
sbit DS2401Bus = P3^5;
//DS2401.c
// 首先對單總線發復位:
// 總線保持低電平超過480us;總線上的所有器件將復位
// 主機釋放總線,并進入接收模式
// 從機等待15-60us,接著拉低總線60-240us,以產生應答脈沖
// 寫0x33H命令: 僅適合于單節點(讀ROM[0x33]命令)
// 所有寫(0或1)時隙至少需要60us 且在兩次獨立的寫時隙之間至少需要1us的恢復時間
// 兩種寫時隙均起始于主機拉低總線
// 寫1時隙: 主機在拉低總線后接著必須在15us之內釋放總線,由5k上拉電阻將總線拉至高電平
// 寫0時隙: 主機拉低總線后只需在整個時隙期間保持低電平即可至少60us
// -- 在寫時隙起始后15-60us期間,單總線器件采樣總線電平狀態(0或1)
// 讀時隙
// 器件僅在主機發出讀時隙時才向主機傳輸數據。所以在主機發出讀數據命令后必須馬上產生讀時隙
// 所有讀時隙至少需要60us 且在兩次獨立的讀時隙之間至少需要1us的恢復時間
// 每個讀時隙都由主機發起,至少拉低總線1us
// 在主機發起讀時隙之后單總線器件才開始在總線上發送0或1
// 從機發出的數據在起始時隙之后保持有效時間15us
// 因而,主機在讀時隙期間必須釋放總線并且在時隙起始后的15us之內采樣總線狀態
//
#pragma ot(4,SPEED)
void delay_500us(void)
{
unsigned char data i;
for(i = 0; i < 56; i++) ;
}
void delay_250us(void)
{
unsigned char data i;
for(i = 0; i < 28; i++) ;
}
void delay_90us(void)
{
unsigned char data i;
for(i = 0; i < 9; i++) ;
}
void delay_60us(void)
{
unsigned char data i;
for(i = 0; i < 6; i++) ;
}
unsigned char InitDS2401(void) //復位DS2401
{
unsigned char tmp;
DS2401Bus = 0; // 輸出:0;總線保持低電平超過480us
delay_500us(); // 498us
DS2401Bus = 1; // 釋放總線,由5k上拉電阻將總線拉至高電平
delay_60us(); // 64us,等待器件發出應答脈沖
tmp = DS2401Bus; // 檢查應答脈沖
delay_250us(); // 255us,延時240us以上
if(tmp) // 讀取數據
return 0;
else
return 1;
}
void WriteDS2401(unsigned char d)//寫2401命令
{
unsigned char i;
for(i=0;i<8;i++) {
DS2401Bus = 0; // 主機在拉低總線后接著必須在15us之內釋放總線
_nop_(); _nop_(); _nop_(); // 每個nop估計耗時 1.085us
if(d & 1) { // 輸出:數據位
DS2401Bus = 1;
}
d >>= 1;
delay_60us(); // 至少保持60us
DS2401Bus = 1; // 將總線拉至高電平, 至少需要1us的恢復時間
_nop_();_nop_();_nop_();
}
}
unsigned char ReadDS2401() //讀2401數據
{
unsigned char i,d;
for(i=0;i<8;i++) {
d >>= 1;
DS2401Bus = 0; // 至少拉低總線1us
_nop_();_nop_();_nop_();
DS2401Bus = 1; // 釋放總線
_nop_();_nop_();_nop_();_nop_();_nop_();
if(DS2401Bus == 1) d |= 0x80; // 讀取數據
delay_90us(); // 90us
}
return d;
}
unsigned char crctest() //進行CRC校驗
{
unsigned char i1, i2, crc=0;
for(i1=0; i1<8; i1++) {
crc ^= DS2401IDBuf[i1];
for(i2=0; i2<8; i2++) {
if (crc & 0x01)
crc = (crc >> 1) ^ 0x8C;
else
crc >>= 1;
}
}
return (crc);
}
unsigned char ReadRS2401ID() //讀出DS2401的
{
unsigned char i;
if (!InitDS2401()) return(0);
WriteDS2401(0x33);
for(i=0;i<8;i++) DS2401IDBuf[i]=ReadDS2401();
if (crctest() != 0) return(0);
return(1); //CRC校驗成功
}
|