AVR温度计DS18B20
扫描二维码
随时随地手机看文章
#include
#include
#include
#include
unsigned char data_H, data_L,wendu;
unsigned int data_T;
void main(void)
{
LCD_init(); //lcd初始化
lcd_cls(); //清屏,光标回位
while(1)
{
monobus_init(); //单总线复位
write_monobus(0xCC); //跳过ID码匹配,适用于一个DS18B20
//可以使用8条语句代替上面的那条语句依次写入8个ID码,这样就是ID码匹配了
//如果不知道18B20的ID码,可以在总线上接入单个18B20
//然后参考下面的读取语句,依次读取18B20的8个ID码
//记得使用CRC8校验一下是否正确
write_monobus(0x44); //启动温度转换
delay_ms(500); //等待转换
monobus_init(); //单总线复位
write_monobus(0xCC); //跳过ID码匹配
write_monobus(0xBE); //通知DS18B20,准备读数据
data_L=read_monobus(); //读取第一个数据(温度低字节)
data_H=read_monobus(); //读取第二个数据(温度高字节)
//可以继续读取第三个到第九个RAM数据
lcd_cls();
data_T=data_H*256+data_L; //合并后得到原始温度数据
if(data_H>15) data_T=(~data_T+1)/16; else data_T/=16; //计算实际温度
wendu=data_T;
lcd_gotoxy(16,3);
lcd_putsf("T = ",4); //显示字符串,字符串是保存在Flash的
if(data_H>15) lcd_putchar('-');
lcd_put(wendu); //显示温度
lcd_putchar(' '); //空一个字符
lcd_write(2); //显示C前面上标的一个点
lcd_write(0); //空一小格
lcd_putchar('C');
delay_ms(250);
}
}
/*
如果温度为正,则T的最高位的4位都为0,否则为1
负温度的计算:原始数据取反、加1、再乘以 0.0625
正温度的计算:原始数据乘以 0.0625
CVAVR自带了18B20的库,如果大家不喜欢上面我写的函数,也可以使用自带的
*/
//**********************************************************************************
//**********************************************************************************
//monobus.h文件,用于操作DS18B20/DS2401等单总线器件
//假设软件设计要求的时钟频率是4MHz
//实际上硬件工作在2-8MHz下也很正常,就是说,下面代码的延时取值是很合适的
//CVAVR本身自带单总线的库1wire.h,如果大家不喜欢下面的代码也可以使用它自带的函数(请看帮助文档)
#define monobus_1 DDRC.0=0 //设置单片机IO为输入,由于总线存在上拉电阻,所以此时电平是1
#define monobus_0 DDRC.0=1 //设置 单片机 IO为输出,配合默认的 PORTC.0=0 则输出0电平
#define monobus_inPINC.0 //检测总线(从机)的电平状态
void monobus_init(void) //复位,不检测从机设备是否存在(只要没有虚焊就肯定存在的)
{
monobus_0;
delay_us(480);
monobus_1;
delay_us(480);
}
void write_monobus(unsigned char data) //向单总线的从机写入数据(先写低位再写高位,与SPI相反)
{
unsigned char n=1;
while(n)
{
monobus_0;
delay_us(2); //拉低总线1-3us,通知从机准备收发数据
if(data&n) monobus_1; else monobus_0; //向总线写数据的某一位(1或者0)
delay_us(75); //等待90us,保证从机有足够的时间进行采样(24-210us)
monobus_1; //释放总线
delay_us(2); //释放总线时间要大于1us
n<<=1;
}
}
unsigned char read_monobus(void) //读单总线的从机数据(先传输低位后传输高位,与SPI相反)
{
unsigned char data_18b20=0;
unsigned char n=1;
while(n)
{
monobus_0;
delay_us(2); //拉低总线1-3us,通知从机准备收发数据
monobus_1; //释放总线
delay_us(5); //从机在1-25us内会向总线输出数据的某一位(1或者0)
if(monobus_in) data_18b20+=n; //读取总线数据
delay_us(55); //等待从机释放总线
n<<=1;
}
return data_18b20;
}
//**********************************************************************************
//**********************************************************************************
/*************************************************************
使用者只需把这个nokia3310.h的文件复制到工程目录即可
使用nokia3310库函数时,请先定义3310与MCU的连接
本例子3310LCD与 单片机 的连接如下
RESET PB1
D/C PB2
SDIN PB3
SCLK PB5
SCE GND
英文字库,5*8点阵,每一个字符占用5个字节,共94个可显示字符数据**/
#define RESET PORTB.1 //RESET=0时,LCD复位
#define DC PORTB.2 //DC=0_指令,DC=1_数据
#define SDIN PORTB.3
#define SCLK PORTB.5