一、原理分析
DS18B20温度传感器:http://t.csdnimg.cn/fFZlz
HC573/HC138:http://t.csdnimg.cn/W0a0U
数码管:http://t.csdnimg.cn/kfm9Y
独立键盘:http://t.csdnimg.cn/YPInc
二、示例题目
在CT107D单片机综合训练平台上,新建工程并以I/O模式编写代码,实现以下功能:
- 将DS18B20的底层驱动代码文件正确移植到工程中。
- 配置J5为BTN模式,将S4设置为独立按键,用于切换温度的显示格式。
- 系统上电后,单片机循环启动DS18B20温度转换,并读取温度转换结果,进行适当的换算后,在数码管的右侧显示。
- 系统上电后,默认显示格式为保留2位小数;按下S4按键后松开,显示格式切换为保留1位小数;再次按下S4按键后松开,显示格式切换为只保留整数部分;再次按下S4按键后松开,显示格式重新恢复为保留2位小数;按键控制如此循环。
三、特别提醒
移植onewire.c时,要把它的延时函数改为
void Delay_OneWire(unsigned int t)
{
t = t * 10;
while(t--);
}
四、示例代码
#include "stc15.h"
#include "onewire.h"
#define TKEY 200
#define TSMG 500
unsigned char mode = 1; //模式
float temp = 0; //读取到的温度
sbit s4 = P3^3;
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
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
};
code unsigned char Seg_DotTable[] =
{
0x40, //0.
0x79, //1.
0x24, //2.
0x30, //3.
0x19, //4.
0x12, //5.
0x02, //6.
0x78, //7.
0x00, //8.
0x10 //9.
};
void hc573(unsigned char channel, unsigned char dat)
{
P2 = (P2 & 0x1f) | 0x00;
P0 = dat;
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void delay_smg(unsigned int t)
{
while(t--);
}
void delay_key(unsigned int t)
{
while(t--);
}
//控制所有数码管
void smg_all(unsigned char dat)
{
hc573(6, 0xff);
hc573(7, dat);
}
//控制单个数码管
void smg_bit(unsigned char pos, unsigned char dat)
{
hc573(6, 0x01 << pos);
hc573(7, dat);
delay_smg(TSMG);
hc573(6, 0x01 << pos);
hc573(7, 0xff);
}
void smg_display()
{
unsigned int smg_one = 0; //数码管显示温度
if(mode == 1) //模式1
{
smg_one = temp * 100;
smg_bit(4, Seg_Table[smg_one / 1000]);
smg_bit(5, Seg_DotTable[(smg_one / 100) % 10]);
smg_bit(6, Seg_Table[(smg_one / 10) % 10]);
smg_bit(7, Seg_Table[smg_one % 10]);
}
else if(mode == 2) //模式2
{
smg_one = temp * 10;
smg_bit(5, Seg_Table[smg_one / 100]);
smg_bit(6, Seg_DotTable[(smg_one / 10) % 10]);
smg_bit(7, Seg_Table[smg_one % 10]);
}
else //模式3
{
smg_one = temp;
smg_bit(6, Seg_Table[smg_one / 10]);
smg_bit(7, Seg_Table[smg_one % 10]);
}
}
//完成首次温度转换
void init_one()
{
unsigned int MSB = 0;
unsigned int LSB = 0;
init_ds18b20();
Write_DS18B20(0xcc); //忽略ROM
Write_DS18B20(0x44); //启动温度转化
do
{
init_ds18b20();
Write_DS18B20(0xcc); //忽略ROM
Write_DS18B20(0xbe); //读取暂存
LSB = Read_DS18B20(); //读取低八位
MSB = Read_DS18B20(); //读取高八位
MSB = (MSB << 8) | LSB; //合成16位
}while(MSB == 85);
}
//读取温度
void read_one()
{
unsigned int MSB = 0;
unsigned int LSB = 0;
smg_display();
init_ds18b20();
Write_DS18B20(0xcc); //忽略ROM
Write_DS18B20(0x44); //启动温度转化
smg_display();
init_ds18b20();
smg_display();
Write_DS18B20(0xcc); //忽略ROM
Write_DS18B20(0xbe); //读取暂存
LSB = Read_DS18B20(); //读取低八位
MSB = Read_DS18B20(); //读取高八位
MSB = (MSB << 8) | LSB; //合成16位
smg_display();
if((MSB & 0xf800) == 0x0000) //如果温度为正
{
temp = MSB * 0.0625;
}
smg_display();
//上述程序中插入多处数码管刷新,可使显示亮度充足
}
void scan_key()
{
unsigned char key_mode = 1; //暂时保存模式值,以便实现按完按键后才改变模式值
key_mode = mode; //获取当前模式
if(s4 == 0)
{
delay_key(TKEY);
if(s4 == 0)
{
key_mode++;
if(key_mode== 4)
{
key_mode = 1;
}
while(s4 == 0)
{
smg_display();
}
}
}
mode = key_mode;
}
void init_sys()
{
hc573(5, 0x00);
hc573(4, 0xff);
smg_all(0xff);
init_one(); //初始化温度读取
}
void main()
{
init_sys();
while(1)
{
scan_key(); //键盘扫描
read_one(); //刷新温度读取
}
}
void hc573(unsigned char channel, unsigned char dat)
:定义了一个函数hc573,用于控制74HC573锁存器芯片,根据通道和数据写入数据。void delay_smg(unsigned int t)
:定义了一个延时函数delay_smg,用于实现数码管的延时控制。void delay_key(unsigned int t)
:定义了一个延时函数delay_key,用于按键的延时控制。void smg_all(unsigned char dat)
:定义了一个函数smg_all,用于控制所有数码管显示相同的数据。void smg_bit(unsigned char pos, unsigned char dat)
:定义了一个函数smg_bit,用于控制单个数码管显示特定位置的数据。void smg_display()
:定义了一个函数smg_display,根据当前模式和温度值控制数码管显示。void init_one()
:定义了一个函数init_one,用于首次温度转换,初始化DS18B20传感器并获取温度值。void read_one()
:定义了一个函数read_one,用于读取温度值,启动温度转换并获取温度数据。void scan_key()
:定义了一个函数scan_key,用于扫描按键状态并根据按键切换显示模式。void init_sys()
:定义了一个函数init_sys,用于系统初始化,包括数码管初始化和温度传感器初始化。void main()
:定义了主函数,程序入口,初始化系统后进入主循环,循环中进行按键扫描和温度读取。