📄 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 + -