#include
#include
#define uchar unsigned char
#define uint unsigned int
#include "1602LCD_drive.h" //包含LCD驱动程序软件包
#include "DS18B20_drive.h" //DS18B20驱动程序软件包
#define beep_0 (PORTD=PORTD&0xbf) //PD6上的蜂鸣器发声
#define beep_1 (PORTD=PORTD|0x40) //PD6上的蜂鸣器不发声
uchar temp_flag ; //判断DS18B20是否正常标志位,正常时为1,不正常时为0
uchar temp_comp; //用来存放测量温度的整数部分
uchar disp_buf[8]={0}; //显示缓冲
uchar temp_data[2] = {0x00,0x00}; //用来存放温度数据的高位和低位
uchar line1_data[] = " DS18B20 OK "; //DS18B20正常时第1行显示的信息
uchar line2_data[] = " TEMP: "; //DS18B20正常时第2行显示的信息
uchar menu1_error[] = " DS18B20 ERR "; //DS18B20出错时第1行显示的信息
uchar menu2_error[] = " TEMP: ---- "; //DS18B20出错时第2行显示的信息
/********以下是函数声明,由于本例采用的函数较多,应加入函数声明部分********/
void port_init(void);
void TempDisp(void); //温度值显示函数声明
void beep(void); //蜂鸣器响一声函数声明
void MenuError(void); //DS18B20出错菜单函数声明
void MenuOk(void); //DS18B20正常菜单函数声明
void GetTemperture(void); //读取温度值函数声明
void TempConv(void); //温度值转换函数声明
/********端口设置函数********/
void port_init(void)
{
PORTA = 0xFF; //输出高电平
DDRA = 0xFF; //设为输出
PORTC = 0xff; //输出高电平
DDRC = 0xFF; //设为输出
//DDRD =(1<
PORTB=0xff;
}
/*********蜂鸣器响一声函数********/
void beep()
{
uint bb;
for(bb=0;bb<10;bb++)
{
beep_0; //蜂鸣器响
Delay_ms(100);
beep_1; //关闭蜂鸣器
Delay_ms(100);
}
}
/********温度值显示函数,负责将测量温度值显示在LCD上********/
void TempDisp()
{
LocateXY(6,1); //从第1行第6列开始显示温度值
lcd_wdat(disp_buf[3]); //百位数显示
lcd_wdat(disp_buf[2]); //十位数显示
lcd_wdat(disp_buf[1]); //个位数显示
lcd_wdat('.'); //显示小数点
lcd_wdat(disp_buf[0]); //小数位数显示
lcd_wdat(0xdf); //0xdf是圆圈°的代码,以便和下面的C配合成温度符号℃
lcd_wdat('C'); //显示C
}
/********DS18B20正常时的菜单函数********/
void MenuOk()
{
LCD_write_str(0,0,line1_data); //在第0行的第0列显示" DS18B20 OK "
LCD_write_str(0,1,line2_data); //在第1行的第0列显示" TEMP: "
}
/********DS18B20出错时的菜单函数********/
void MenuError()
{
lcd_clr(); //LCD清屏
LCD_write_str(0,0,menu1_error); //在第0行的第0列显示" DS18B20 ERR "
LCD_write_str(0,1,menu2_error); //在第1行的第0列显示" TEMP: "
LocateXY(11,1); //从第1行第11列开始显示
lcd_wdat(0xdf); //0xdf是圆圈°的代码,以便和下面的C配合成温度符号℃
lcd_wdat('C'); //显示C
}
/********读取温度值函数********/
void GetTemperture(void)
{
SREG=0x00; //禁止全局中断; //关中断,防止读数错误
Init_DS18B20(); //DS18B20初始化
if(yes0==0) // yes0为Init_DS18B20函数的返回值,若yes0为0,说明DS18B20正常
{
WriteOneByte(0xCC); // 跳过读序号列号的操作
WriteOneByte(0x44); // 启动温度转换
Delay_ms(1000); //延时1s,等待转换结束
Init_DS18B20();
WriteOneByte(0xCC); //跳过读序号列号的操作
WriteOneByte(0xBE); //读取温度寄存器
temp_data[0] = ReadOneByte(); //温度低8位
temp_data[1] = ReadOneByte(); //温度高8位
//temp_TH = ReadOneByte(); //温度报警TH
//temp_TL = ReadOneByte(); //温度报警TL
temp_flag=1;
}
else temp_flag=0; //否则,出错标志置0
SREG=0x80; //温度数据读取完成后再开中断
}
/********温度数据转换函数,将温度数据转换为适合LCD显示的数据********/
void TempConv()
{
uchar sign=0; //定义符号标志位
uchar temp; //定义温度数据暂存
if(temp_data[1]>127) //大于127即高4位为全1,即温度为负值
{
temp_data[0]=(~temp_data[0])+1; //取反加1,将补码变成原码
if((~temp_data[0])>=0xff) //若大于或等于0xff
temp_data[1]=(~temp_data[1])+1; //取反加1
else temp_data[1]=~temp_data[1]; //否则只取反
sign=1; //置符号标志位为1
}
temp =temp_data[0]&0x0f; //取小数位
disp_buf[0]=(temp *10/16)+0x30; //将小数部分变换为ascii码
temp_comp =((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//取温度整数部分
disp_buf[3]= temp_comp /100+0x30; //百位部分变换为ascii码
temp = temp_comp%100; //十位和个位部分
disp_buf[2]= temp /10+0x30; //分离出十位并变换为ascii码
disp_buf[1]= temp %10+0x30; //分离出个位并变换为ascii码
if(disp_buf[3]==0x30) //百位ascii码为0x30(即数字0),不显示
{
disp_buf[3]=0x20; //0x20为空字符码,即什么也不显示
if(disp_buf[2]==0x30) //十位为0,不显示
disp_buf[2]=0x20;
}
if(sign) disp_buf[3]=0x2d; //如果符号标志位为1,则显示负号(0x2d为负号的字符码)
}
/********主函数********/
void main(void)
{
port_init();
PortDS18B20_Init();
lcd_init(); //初始化LCD
lcd_clr(); //LCD清屏
while(1)
{
GetTemperture(); //读取温度数据
if(temp_flag==0)
{
beep(); //若DS18B20不正常,蜂鸣器报警
MenuError(); //显示出错信息函数
}
if(temp_flag==1) //若DS18B20正常,则往下执行
{
TempConv(); //将温度转换为适合LCD显示的数据
MenuOk(); //显示温度值菜单
TempDisp(); //调用LCD显示函数
}
}
}
上一篇:AVR的模拟比较器功能实验
下一篇:基于AVR单片机的mega16内部EEPROM操作C语言程序设计
推荐阅读最新更新时间:2024-03-16 15:17