1、题目:
2、DS18B20温度传感器原理图:
DQ引脚P14
3、DS18B20读温度的基本代码
修改onewire.c:
1、加头文件
2、定义引脚sbit DQ=P1^4;
3、添加读取温度函数
// add: reading the temperature function
unsigned int read_temp()
{
unsigned int temp;
unsigned char tempH, tempL;
init_ds18b20();
// Skip ROM operations and send commands directly to the DS18B20
// Since there is only one temperature sensor
Write_DS18B20(0xcc);
// Start the temperature conversion command
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
// Send read temperature command
Write_DS18B20(0xbe);
// Firstly read the low byte of the temperature value
tempL = Read_DS18B20();
// Secondly the high byte
tempH = Read_DS18B20();
// combination
temp = tempH<<8|tempL;
// integer value: 0.0625
// one decimal: 0.0625*10
// two decimal: 0.0625*100
temp = 0.0625*temp;
return temp;
}
注意:
- 精度是0.0625,如果想要显示1位小数,就扩大10倍,乘以0.625;显示2位小数,就扩大100倍,乘以6.25。
- 函数返回值是unsigned int
主函数操作:
1、extern外部调用onewire.c中我们自己定义的这个读取温度的函数
2、定义全局变量temperature,接收读温度函数的返回值。
3、数码管段选表增添带有小数点的数字:将0~9的段选高4位减去8即可,也就是让最高一位置0。0~9(带小数点)紧挨着放到0~9(无小数点)的后面。这样0~9(带小数点)的索引就是10~19,也就是原始数字索引值0~9的基础上+10。
4、温度传感器读取温度需要一定的时间,可以设置500ms(或其他时间间隔)读一次温度。这个时候需要再定义一个全局的温度的计时变量time_temp。计时变量time_temperature的自增操作则放在定时器1的中断服务程序中,即每过1ms自增1。然后放到main函数的while循环去判断有没有自增到500,如果自增到500,就调用一次读温度函数,同时将计时变量time_temp归零。
5、使用数码管显示功能正常显示温度即可,记得在对应位置加上小数点,+10即可。
4、学习心得
① 稳定按键的while循环
第一遍写完代码,测试的时候,发现按键很不稳定,按一下切换的时候总是闪烁,或者切换不成功。后来发现是延迟10ms判断按键按下,做了状态变量的切换以后,还必须写一个while循环直到按键被释放。
void key()
{
P44=1; P42=0 ;P35=1 ;P34=1;
if(P32==0){
Delay10ms();
if(P32==0) state=!state;
//while循环不可省!
while(!P32);
}
}
② 学会用全局状态变量来辅助按键判断
由于本题只有2种状态,1位小数和2位小数。所以设bit型的全局状态变量state,每当按键S9被按下,就将state逻辑取反,从而达到使用S9一个按键切换两种状态的目的。
5、完整main代码
#include <STC15F2K60S2.H>
#define Y4C P2=P2&0X1F|0X80;
#define Y5C P2=P2&0X1F|0Xa0;
#define Y6C P2=P2&0X1F|0Xc0; //位选
#define Y7C P2=P2&0X1F|0Xe0; //段选
#define Y0C P2=P2&0X1F|0X00;
typedef unsigned char u8;
typedef unsigned int u16;
code unsigned char Seg_Table[] =
{
//数字
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
//带小数点(高位减去8)
0x40, //0
0x79, //1
0x24, //2
0x30, //3
0x19, //4
0x12, //5
0x02, //6
0x78, //7
0x00, //8
0x10, //9
//字符
0xff, //空 20
0xbf, // - 21
//字母
0x88, //A 22
0x83, //b 23
0xc6, //C 24
0xa1, //d 25
0x86, //E 26
0x8e //F 27
};
code unsigned char com[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 seg_index[8] = {0};
u16 temp=0; //温度变量接收读取到的温度
u16 time_temp=0; //温度的计时变量
bit state=0;
//外部调用读取温度函数
extern unsigned int read_temperature10();
extern unsigned int read_temperature100();
void init()
{
Y4C;P0=0XFF;Y0C;
Y5C;P0=0X00;Y0C;
Y6C;P0=0XFF;Y0C;
Y7C;P0=0XFF;Y0C;
}
void seg_display()
{
static u8 num = 0;
//关段选
Y7C;P0=0XFF;Y0C;
//选位选
Y6C;P0=com[num];Y0C;
//开段选
Y7C;P0=Seg_Table[seg_index[num]];Y0C;
if(++num==8) num=0;
}
void set_index(u8 d0,d1,d2,d3,d4,d5,d6,d7)
{
seg_index[0]=d0;
seg_index[1]=d1;
seg_index[2]=d2;
seg_index[3]=d3;
seg_index[4]=d4;
seg_index[5]=d5;
seg_index[6]=d6;
seg_index[7]=d7;
}
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初值
TH1 = 0xD1; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器0中断
EA = 1;
}
void tm1_isr() interrupt 3
{
seg_display();
time_temp++;
}
void key()
{
P44=1; P42=0 ;P35=1 ;P34=1;
if(P32==0){
Delay10ms();
if(P32==0) state=!state;
while(!P32);
}
}
main()
{
init();
Timer1Init();
while(1)
{
key();
//每500ms读取一次温度
if(time_temp >= 500)
{
time_temp=0;
if(!state)
temp = read_temperature10();
else if(state)
temp = read_temperature100();
}
//1位小数
if(!state)
set_index(20,20,20,20,temp/100,(temp%100/10)+10,temp%10,24);
//2位小数
else if(state)
set_index(20,20,20,temp/1000,(temp%1000/100)+10,temp%100/10,temp%10,24);
}
}
6、完整onewire.c代码
#include <STC15F2K60S2.H>
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//增写:读取温度的函数(1位小数)
unsigned int read_temperature10()
{
//注意:温度是int类型
unsigned int temp;
unsigned char teH,teL;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
teL = Read_DS18B20();
teH = Read_DS18B20();
temp= teH<<8|teL;
temp= temp*0.625;
return temp;
}
//增写:读取温度的函数(2位小数)
unsigned int read_temperature100()
{
//注意:温度是int类型
unsigned int temp;
unsigned char teH,teL;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
teL = Read_DS18B20();
teH = Read_DS18B20();
temp= teH<<8|teL;
temp= temp*6.25;
return temp;
}