?? main.c
字號:
/******************** 2011電子科技協會 ********************
;名稱 :1602液晶屏顯示溫度
;作者 : 鄭品洪
;日期 : 07/25/2011
;描述 : 利用1602顯示實時溫度
;說明 :由于stm8IO口作為輸出還是輸入都要進行設置,而18B20 既需要輸出又需要輸入,查詢資料上說把
IO口設置為開漏輸出并外面加上拉電阻,我嘗試過,但沒有成功,所以這里采用輸入輸出來回切換的方法
,因此,此程序僅作參考。 閱讀此程序時請參考18B20資 料
;***********************************************************/
#include <stm8s105s4.h>
#define uchar unsigned char
#define uint unsigned int
_Bool RS @PA_ODR:4;
_Bool RW @PA_ODR:5; //定義1602和18B20IO口
_Bool E @PA_ODR:6;
_Bool DQ @PG_ODR:1;
uchar temp,q,a[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0x7f};
void init_Ds18B20(void);
void delay(uchar);
void delay_1ms(uint);
void write_byte(uchar);
uchar read_byte(void);
void readtemperature(void);
void display1(void);
/*********************************/
uchar table0[]="The temperature";
uchar table1[]="is:";
uchar table2[8];
uchar i;
void init_stm8(void)
{
PA_DDR=0x70;
PA_CR1=0x70;
PA_CR2=0x00;
PB_DDR=0xff;
PB_CR1=0xff;
PB_CR2=0x00;
/* PG_DDR=0x02;
PG_CR1=0x00; //嘗試把IO口設為開漏輸出,未成功
PG_CR2=0x00; */
CLK_SWR = 0xE1;
CLK_CKDIVR = 0x19; //頻率設為1MHz
}
//1602寫指令函數,請參考“1602”的程序
void write_com(uchar com)
{
RS=0;
RW=0;
PB_ODR=com;
delay_1ms(5);
E=1;
E=0;
}
//1602寫數據函數, 請參考“1602”的程序
void write_data(uchar date)
{
RS=1;
RW=0;
PB_ODR=date;
delay_1ms(5);
E=1;
E=0;
}
//1602初始化函數
void init(void)
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80+0x00);
}
//顯示子函數
void display(uchar *s)
{
while(*s>0)
{
write_data(*s++);
delay_1ms(90);
}
}
/**********************************/
void main()
{
init_stm8();
init(); //初始化1602
init_Ds18B20(); //初始化18B20
write_byte(0xcc);
write_byte(0x44);
delay(300);
display(table0);
write_com(0x80+0x40+0x02);
display(table1); //以上語句為顯示字符"The temperature is:"
while(1)
{
readtemperature(); //讀溫度數據
write_com(0x80+0x40+0x05); //把1602地址指針指向第二行第6列
for(i=0;i<8;i++) //顯示溫度數據,包括一個正負溫度符號位,一個小數點,四個數據,還有兩位顯示℃
{
write_data(table2[i]);
}
}
}
//延時一條指令子函數,用于18B20時序操作
void delay(uchar t)
{
while(t--);
}
void delay_1ms(uint a)
{
char i;
while(a--)
for(i=0;i<120;i++);
}
//18B20初始化函數
void init_Ds18B20(void)
{
uchar n;
PG_DDR=0x02;
PG_CR1=0x02; //設置IO口為推挽輸出模式
PG_CR2=0x00;
DQ=1;
delay(2);
DQ=0;
delay(200);
DQ=1;
delay(50);
n=DQ;
delay(100); //以上語句為檢查是否存在18B20,若n=0說明 18B20存在
}
//18B20寫子函數
void write_byte(uchar date)
{
uchar i;
PG_DDR=0x02;
PG_CR1=0x02; //設置IO口為推挽輸出
PG_CR2=0x00;
delay_1ms(2);
for(i=0;i<8;i++) //請參考18B20時序圖
{
DQ=0;
delay(1);
DQ=date&0x01;
delay(10);
DQ=1;
date>>=1;
}
delay(4);
}
//18B20讀子函數
uchar read_byte(void)
{
uchar i,value;
delay_1ms(2);
for(i=0;i<8;i++)
{
PG_DDR=0x02;
PG_CR1=0x02; //設置IO口為推挽輸出
PG_CR2=0x00;
DQ=0;
value>>=1; //先讀地位,因此沒讀一次數向左移動 一位
DQ=1;
PG_DDR=0x00;
PG_CR1=0x02; //讀數據時設置IO口為上拉輸入
PG_CR2=0x00;
if((PG_IDR&0x02)==0x02) //如果IO口電壓為高,則value中對應的位為1,否則為0
value|=0x80;
delay(4);
}
return value; //將讀的數返回
}
//讀溫度數據并處理子函數
void readtemperature(void)
{
uchar a,b,p;
init_Ds18B20(); //初始化18B20
write_byte(0xcc); //逃過ROM,一個IO口有多個 18B20時需 要讀ROM
write_byte(0x44); //啟動溫度檢測
DQ=1;
delay(200); //延時,等待溫度檢測完成
init_Ds18B20(); //每次操作前要初始化18B20
write_byte(0xcc); //跳過ROM
write_byte(0xbe); //從儲存器讀數據
a=read_byte(); //讀地位溫度數據
b=read_byte(); //讀高位溫度數據
if(b>0x07) //如果溫度為負數,b會大于0x07,故當b大于0x07時,讓1602在溫度前面顯示“-”
q=1;
p=(a&0x0f)*625/100; //小數部分數據處理,由于小數部分有 四位,故分辨率為1/16,16×625剛好為10000,這里再除于100是精確到小數點后兩位
//理論上18B20可以精確到小數點后四位,但由于分辨率只有1/16,即0.06左右,小數點后第三第四位已經沒有實際意義
b=(b<<4)+(a>>4); //將低位溫度數據的高四位和高位溫度 數據的 低四位拼成溫度數據的整數部分
table2[7]=0x43; //攝氏度中“C” 的代碼
table2[6]=0xdf; //攝氏度中“。“ 的代碼
table2[5]=p%10+0x30; //小數點后第二位數據,加上30是為了和1602中字符代碼一致
table2[4]=p/10+0x30;
table2[3]=0x2e; //小數點代碼
table2[2]=b%10+0x30;
table2[1]=b/10+0x30; //整數部分
table2[0]=0x80; //空字符代碼,就是不顯示任何字符
if(q==1)
table2[0]=0x2d; //”-“代碼,若溫度為-,則顯示
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -