代碼如下:
#include <pic.h> //調用PIC16F87XA單片機的頭文件
__CONFIG(HS&WDTDIS&LVPDIS);
unsigned char temp1;
unsigned char temp2;
unsigned char buf,buf1,buf2;
//轉換后的溫度值小數點部分查表
const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};
//---------------------------------------
//數碼管字形表,供顯示時查詢
const unsigned char LED[11]=
{ //定義表格一定要使用const,這樣會做到程序存儲區中
0B00111111, //"0"的字形表,0x3F
0B00000110, //"1"的字形表,0x06
0B01011011, //"2"的字形表,0x5B
0B01001111, //"3"的字形表,0x4F
0B01100110, //"4"的字形表,0x66
0B01101101, //"5"的字形表,0x6D
0B01111101, //"6"的字形表,0x7D
0B00000111, //"7"的字形表,0x07
0B01111111, //"8"的字形表,0x7F
0B01101111, //"9"的字形表,0x6F
0B10000000, //.
};
//---------------------------------------
//4位數碼管相關I/O設置
#define U5A RB0 //4位數碼管單元的U5(74HC138)的A腳接在RB0口上
#define U5B RB1 //4位數碼管單元的U5(74HC138)的B腳接在RB1口上
#define U5C RB2 //4位數碼管單元的U5(74HC138)的C腳接在RB2口上
//名稱:復位DS18B20函數
unsigned char Reset(void)
{
unsigned int i;
unsigned char k;
TRISA4=0; //設置RA4位輸出口
RA4=0; //拉低DQ總線開始復位
i=67; //保持DQ低大約870uS,符合不低于480US的要求
while(i>0) //保持DQ低大約870uS,符合不低于480US的要求
i--; //保持DQ低大約870uS,符合不低于480US的要求
TRISA4=1; //設置RA4為輸入口,以釋放總線等電阻拉高總線
i=6; //大約78uS后,判斷是否復位成功
while(i>0) //大約78uS后,判斷是否復位成功
i--; //大約78uS后,判斷是否復位成功
if(RA4==0) //讀出數據并保存
k=0;
else
k=1;
i=31; //維持約400US,符合總讀時隙不低于480US的要求
while(i>0) //維持約400US,符合總讀時隙不低于480US的要求
i--; //維持約400US,符合總讀時隙不低于480US的要求
return k; //k=0為復位成功,k=1為復位失敗
}
//名稱:寫字節函數
void WriteByte(unsigned char dat)
{
unsigned int i;
unsigned char j;
for(j=0;j<8;j++)
{
if(dat&0x01) //如果寫1
{
TRISA4=0; //設置RA4位輸出口
RA4=0; //拉低
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
TRISA4=1; //設置RA4為輸入口,以釋放總線等電阻拉高總線
i=5; //維持約63US,符合不低于60US的要求
while(i>0) //維持約63US,符合不低于60US的要求
i--; //維持約63US,符合不低于60US的要求
}
else //如果寫0
{
TRISA4=0; //設置RA4位輸出口
RA4=0; //拉低
i=5; //維持約63US,符合不低于60US的要求
while(i>0) //維持約63US,符合不低于60US的要求
i--; //維持約63US,符合不低于60US的要求
TRISA4=1; //設置RA4為輸入口,以釋放總線等電阻拉高總線
NOP(); //維持2US,符合大于1US的規范
NOP(); //維持2US,符合大于1US的規范
}
dat=dat>>1; //寫入字節右移1位
}
}
//名稱:讀字節函數
unsigned char ReadByte(void)
{
unsigned int i;
unsigned char j,buf=0;
for(j=1;j<=8;j++) //接收8次還原一個字節數據
{
buf=buf>>1; //接收前,先將接收緩沖區右移
TRISA4=0; //設置RA4位輸出口
RA4=0; //拉低
NOP(); //維持2US,符合大于1US小于15US的規范
NOP(); //維持2US,符合大于1US小于15US的規范
TRISA4=1; //設置RA4為輸入口,以釋放總線等電阻拉高總線 準備讀
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
NOP(); //維持6US,符合大于1US小于15US的規范
if(RA4==1) buf|=0x80; //讀出1位數據保存于buf中最高位
i=4; //維持約52US,符合總讀時隙不低于60US的要求
while(i>0) //維持約52US,符合總讀時隙不低于60US的要求
i--; //維持約52US,符合總讀時隙不低于60US的要求
}
return buf; //退出的同時將接收緩沖區參數返回
}
//名稱:啟動讀溫度函數
unsigned char Convert(void)
{
unsigned int i;
if(Reset()==0) //如果復位成功
{
i=77; //延時約1000US
while(i>0) //延時約1000US
i--; //延時約1000US
WriteByte(0xcc); // 跳過多器件識別
WriteByte(0x44); // 啟動溫度轉換
return 1;
}
else
{
return 0;
}
}
//名稱:讀溫度函數
void ReadFlash(void)
{
unsigned int i;
unsigned char Lsb,Msb;
if(Reset()==0)
{
i=77; //延時約1000US
while(i>0) //延時約1000US
i--; //延時約1000US
WriteByte(0xcc); // 跳過多器件識別
WriteByte(0xbe); // 讀暫存器
Lsb=ReadByte(); // 低字節
Msb=ReadByte(); // 高字節
temp2=Lsb&0x0f; //LSB的低4位為小數部分
temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整數部分
}
else
{
temp1=0;
temp2=0;
}
}
void tempture()
{
if(Convert()==1) //啟動轉換
{
ReadFlash(); //讀取溫度
if(temp1>99) temp1=99;
if(temp2>15) temp2=0;
buf=temp1/10;
buf1=temp1%10;
buf2=table[temp2&0x0f];
}
}
//---------------------------------------
//名稱: 主函數
//---------------------------------------
void main(void) //主函數,單片機開機后就是從這個函數開始運行
{
unsigned int c=0; //定義一個char型變量,做延時用
unsigned char d=0; //定義一個char型變量,控制顯示位置
TRISB=0B11111000; //初始化RB7-RB0的輸入輸出方向
TRISD=0B00000000; //初始化RD7-RD0的輸入輸出方向
PORTB=0B00000000; //初始化RB7-RB0的數值
PORTD=0B00000000; //初始化RD7-RD0的數值
while(1) //死循環,單片機初始化后,將一直運行這個死循環
{
tempture();
for(c=0;c<20;c++);//做一個0-250的循環,不執行其他操作,只為延時
PORTD=0; //關一次顯示,以免顯示出鬼影
if(++d>3) d=0; //先將d加1,然后判斷是否大于3,大于3歸零
if(d==0) //如果d=0,顯示千位
{
U5A=0; //U5A=0,U5B=0,U5C=0,選通數碼管的千位進行顯示
U5B=0; //U5A=0,U5B=0,U5C=0,選通數碼管的千位進行顯示
U5C=0; //U5A=0,U5B=0,U5C=0,選通數碼管的千位進行顯示
PORTD=LED[buf]; //溫度整數部分十位
}
else if(d==1) //如果d=1,顯示百位
{
U5A=1; //U5A=1,U5B=0,U5C=0,選通數碼管的百位進行顯示
U5B=0; //U5A=1,U5B=0,U5C=0,選通數碼管的百位進行顯示
U5C=0; //U5A=1,U5B=0,U5C=0,選通數碼管的百位進行顯示
PORTD=LED[buf1]; //溫度整數部分個位
}
else if(d==2) //如果d=2,顯示十位
{
U5A=0; //U5A=0,U5B=1,U5C=0,選通數碼管的十位進行顯示
U5B=1; //U5A=0,U5B=1,U5C=0,選通數碼管的十位進行顯示
U5C=0; //U5A=0,U5B=1,U5C=0,選通數碼管的十位進行顯示
PORTD=LED[10]; //十位顯示"2"
}
else if(d==3) //如果d=3,顯示個位
{
U5A=1; //U5A=1,U5B=1,U5C=0,選通數碼管的個位進行顯示
U5B=1; //U5A=1,U5B=1,U5C=0,選通數碼管的個位進行顯示
U5C=0; //U5A=1,U5B=1,U5C=0,選通數碼管的個位進行顯示
PORTD=LED[buf2]; //溫度小數部分
}
}
}
我用四位數碼管顯示實時溫度,顯示的現象有微小閃爍,跪求大神們如何解決,幫忙改一下代碼。
|