運行程序 15f104e是1T運行速度,晶體速度11.0529M 使用12T芯片延時降低10倍 #include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
bit flag1s = 0; //1s 定時標志
unsigned char T0RH = 0; //T0 重載值的高字節
unsigned char T0RL = 0; //T0 重載值的低字節
void ConfigTimer0(unsigned int ms);
unsigned char code disp1[]={0xfe,0xb0,0xed,0xf9,0xb3,0xdb,0xdf,0xf0,0xff,0xfb}; //數字帶點
unsigned char code disp2[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b}; //數字不帶點
unsigned char code disp3[]={0x0}; //不顯示
unsigned char code disp4[]={0x4f}; //顯示E
unsigned char code disp5[]={0x01}; //顯示-
sbit Max7219_pinCLK = P3^2;
sbit Max7219_pinCS = P3^5;
sbit Max7219_pinDIN = P3^4;
sbit IO_18B20 = P3^3; //DS18B20 通信引腳
/* 軟件延時函數,延時時間(t*10)us */
void DelayX10us(unsigned char t)
{
do {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
while (--t);
}
//向MAX7219(U3)寫入字節
void Write_Max7219_byte(uchar DATA)
{
uchar i;
Max7219_pinCS=0; //CS=0有效,CS=1鎖存
for(i=8;i>=1;i--)
{
Max7219_pinCLK=0;
Max7219_pinDIN=DATA&0x80; //&10000000, 編譯器對位操作的理解:非0即為1
DATA=DATA<<1;
Max7219_pinCLK=1; //上升沿把數據送出去
}
}
/*向M第一片MAX7219寫入數據*/
void Write_Max7219(uchar add1,uchar dat1)
{
Max7219_pinCS=0;
Write_Max7219_byte(add1); //寫入地址,即數碼管編號
Write_Max7219_byte(dat1); //寫入數據,即數碼管顯示數字
Max7219_pinCS=1;
}
/*初始化芯片*/
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //譯碼方式:BCD碼
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //掃描界限;8個數碼管顯示
Write_Max7219(0x0c, 0x01); //掉電模式:0,普通模式:1
Write_Max7219(0x0f, 0x00); //顯示測試:1;測試結束,正常顯示:0
Write_Max7219(1,disp3[0]);
Write_Max7219(2,disp3[0]);
Write_Max7219(3,disp3[0]);
Write_Max7219(4,disp3[0]);
}
/* 復位總線,獲取存在脈沖,以啟動一次讀寫操作 */
bit Get18B20Ack()
{
bit ack;
EA = 0; //禁止總中斷
IO_18B20 = 0; //產生 500us 復位脈沖
DelayX10us(500);//50
IO_18B20 = 1;
DelayX10us(60); //延時 60us 6
ack = IO_18B20; //讀取存在脈沖
while(!IO_18B20); //等待存在脈沖結束
EA = 1; //重新使能總中斷
return ack;
}
/* 向 DS18B20 寫入一個字節,dat-待寫入字節 */
void Write18B20(unsigned char dat)
{
unsigned char mask;
EA = 0; //禁止總中斷
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次移出 8 個 bit
{
IO_18B20 = 0; //產生 2us 低電平脈沖
_nop_();
_nop_();
if ((mask&dat) == 0) //輸出該 bit 值
IO_18B20 = 0;
else
IO_18B20 = 1;
DelayX10us(60); //延時 60us
IO_18B20 = 1; //拉高通信引腳
}
EA = 1; //重新使能總中斷
}
/* 從 DS18B20 讀取一個字節,返回值-讀到的字節 */
unsigned char Read18B20()
{
unsigned char dat;
unsigned char mask;
EA = 0; //禁止總中斷
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次采集 8 個 bit
{
IO_18B20 = 0; //產生 2us 低電平脈沖
_nop_();
_nop_();
IO_18B20 = 1; //結束低電平脈沖,等待 18B20 輸出數據
_nop_(); //延時 2us
_nop_();
if (!IO_18B20) //讀取通信引腳上的值
dat &= ~mask;
else
dat |= mask;
DelayX10us(60); //再延時 60us
}
EA = 1; //重新使能總中斷
return dat;
}
/* 啟動一次 18B20 溫度轉換,返回值-表示是否啟動成功 */
bit Start18B20()
{
bit ack;
ack = Get18B20Ack(); //執行總線復位,并獲取 18B20 應答
if (ack == 0) //如 18B20 正確應答,則啟動一次轉換
{
Write18B20(0xCC); //跳過 ROM 操作
Write18B20(0x44); //啟動一次溫度轉換
}
return ~ack; //ack==0 表示操作成功,所以返回值對其取反
}
/* 讀取 DS18B20 轉換的溫度值,返回值-表示是否讀取成功 */
bit Get18B20Temp(int *temp)
{
bit ack;
unsigned char LSB, MSB; //16bit 溫度值的低字節和高字節
ack = Get18B20Ack(); //執行總線復位,并獲取 18B20 應答
if (ack == 0) //如 18B20 正確應答,則讀取溫度值
{
Write18B20(0xCC); //跳過 ROM 操作
Write18B20(0xBE); //發送讀命令
LSB = Read18B20(); //讀溫度值的低字節
MSB = Read18B20(); //讀溫度值的高字節
*temp = ((int)MSB << 8) + LSB; //合成為 16bit 整型數
}
return ~ack; //ack==0 表示操作應答,所以返回值為其取反值
}
/*****************************main.c 文件程序源代碼******************************/
void main()
{
bit res;
int temp; //讀取到的當前溫度值
// int intT, decT; //溫度值的整數和小數部分
unsigned char qian,bai,shi,ge;
float tp;
Init_MAX7219();
EA = 1; //開總中斷
ConfigTimer0(10); //T0 定時 10ms
Start18B20(); //啟動 DS18B20
while (1)
{
if (flag1s) //每秒更新一次溫度
{
flag1s = 0;
res = Get18B20Temp(&temp); //讀取當前溫度
if (res) //讀取成功時,刷新當前溫度顯示
{
if(temp< 0) //溫度低于0度
{
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
qian = temp % 10000 / 1000;
bai = temp % 1000 / 100;
shi = temp % 100 / 10;
ge = temp % 10;
Write_Max7219(1,disp5[0]); // 顯示 "-"
Write_Max7219(2,disp2[qian]);
Write_Max7219(3,disp1[bai]);
Write_Max7219(4,disp2[shi]);
}
else // 溫度大于0度
{
tp=temp;
temp=tp*0.0625*100+0.5;
qian = temp % 10000 / 1000;
bai = temp % 1000 / 100;
shi = temp % 100 / 10;
ge = temp % 10;
if(qian>0) // 溫度10度顯示十位
{
Write_Max7219(1,disp2[qian]);
Write_Max7219(2,disp1[bai]);
Write_Max7219(3,disp2[shi]);
Write_Max7219(4,disp2[ge]);
}
if(qian<=0) // 溫度10度以下顯示個位不顯示十位
{
Write_Max7219(1,disp3[qian]);
Write_Max7219(2,disp1[bai]);
Write_Max7219(3,disp2[shi]);
Write_Max7219(4,disp2[ge]);
}
}
}
else //讀取失敗時,提示錯誤信息
{
Write_Max7219(1,disp4[0]);
Write_Max7219(2,disp3[0]);
Write_Max7219(3,disp3[0]);
Write_Max7219(4,disp3[0]);
}
Start18B20(); //重新啟動下一次轉換
}
}
}
/* 配置并啟動 T0,ms-T0 定時時間 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數頻率
tmp = (tmp * ms) / 1000; //計算所需的計數值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 12; //補償中斷響應延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 為模式 1
TH0 = T0RH; //加載 T0 重載值
TL0 = T0RL;
ET0 = 1; //使能 T0 中斷
TR0 = 1; //啟動 T0
}
/* T0 中斷服務函數,完成 1 秒定時 */
void InterruptTimer0() interrupt 1
{
static unsigned char tmr1s = 0;
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
tmr1s++;
if (tmr1s >= 100) //定時 1s
{
tmr1s = 0;
flag1s = 1;
}
}
|