|
最近在坛子找了些例子,学习DS1820,现在可以显示温度的正负以及百,十,个位,但小数后的温度始终显示0,在仿真上只有步进1度的没发现,下载到目标板上,小数后始终显示0无变化,我猜问题可能出在数值的处理上,本人是刚学AVR的新手,现附上代码,请老师修改,最好附上注释,帮助我们这些初学者,不胜感激!
附:仿真效果图![](http://cache.amobbs.com/bbs_upload782111/files_27/ourdev_540340.jpg)
(原文件名:Snap1ttt.jpg)
#include <iom16v.h> /*包含相关头文件*/
#include "1602.h"
#include "delay.h"
/*******************ds18b20端口**************************/
#define DQ_DDR DDRA
#define DQ_PORT PORTA
#define DQ_PIN PINA
#define DQ_IO PA3
/*******************************************************/
#define DQ_IN DQ_DDR&=~(1<<DQ_IO) /*设置输入*/
#define DQ_OUT DQ_DDR|=(1<<DQ_IO) /*设置输出*/
#define DQ_CLR DQ_PORT&=~(1<<DQ_IO) /*置低电平*/
#define DQ_SET DQ_PORT|=(1<<DQ_IO) /*置高电平*/
#define DQ_R DQ_PIN&(1<<DQ_IO) /*读了电平*/
#define delay4us {NOP();NOP();NOP();NOP();}
#define delay10us {NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();}
//--------函数声明----------------------
void ds1820_start(void);
unsigned char ds1820_reset(void);
unsigned int ds1820_read_temp(void);
void ds1820(void);
//--------------------------------------
unsigned char flag; /*中断标志缓存*/
unsigned char temp_1820[]={0,0,0,0,'.',0,'C',0};//温度数据
/*
延时函数
延时时间:i X 10 + 16uS。
CPU频率为:1MHz。
*/
void delay_10us(unsigned char i) {
if (i == 0) {
return ;
}
while (i--) {
delay4us;
}
}
/*DS18B20复位函数*/
unsigned char ds1820_reset(void) {
unsigned char i;
flag = SREG; /*中断保护*/
CLI(); /*关中断*/
DQ_OUT;
DQ_CLR;
delay_10us(49); /*延时500uS(480-960)*/
DQ_SET;
DQ_IN;
delay_10us(7); /*延时80uS*/
i = DQ_R;
delay_10us(49); /*延时500uS(保持>480uS)*/
if (flag & 0x80) { /*恢复中断状态*/
SEI();
}
if (i) {
return 0x00;
}
else {
return 0x01;
}
}
/*DS18B20字节读取函数*/
unsigned char ds1820_read_byte(void) {
unsigned char i;
unsigned char value = 0;
flag = SREG; /*中断保护*/
CLI(); /*关中断*/
for (i = 8; i != 0; i--) {
value >>= 1;
DQ_OUT;
DQ_CLR;
delay4us; /*延时4uS*/
DQ_SET;
DQ_IN;
delay10us; /*延时10uS*/
if (DQ_R) {
value|=0x80;
}
delay_10us(5); /*延时60uS*/
}
if (flag & 0x80) { /*恢复中断状态*/
SEI();
}
return(value);
}
/*DS18B20字节写入函数*/
void ds1820_write_byte(unsigned char value) {
unsigned char i;
flag = SREG; /*中断保护*/
CLI(); /*关中断*/
for (i = 8; i != 0; i--) {
DQ_OUT;
DQ_CLR;
delay4us; /*延时4uS*/
if (value & 0x01) {DQ_SET;}
//每次都只写最低位,如果最低位是1的话输出高电平作为写1信号,否则无动作即为0
delay_10us(7); /*延时80uS*/
DQ_SET; /*位结束*/
value >>= 1;
}
if (flag & 0x80) { /*恢复中断状态*/
SEI();
}
}
/*启动ds1820转换*/
void ds1820_start(void) {
ds1820_reset();
ds1820_write_byte(0xCC); /*勿略地址*/
ds1820_write_byte(0x44); /*启动转换*/
}
/*DS8B20读取温度信息*/
unsigned int ds1820_read_temp(void) {
unsigned int temphl;
unsigned char templ,temph;
ds1820_reset();
ds1820_write_byte(0xCC); /*勿略地址*/
ds1820_write_byte(0xBE); /*读取温度*/
templ=ds1820_read_byte();//读数据低位
temph=ds1820_read_byte(); //读数据高位
temphl=(temph<<8)|templ; //数据高低位合并
return temphl;
}
void ds1820(void)
{unsigned int now_temp;
ds1820_start(); /*启动一次转换*/
delay_nms(200); /*等待转换结束*/
now_temp=ds1820_read_temp(); /*读取温度数值*/
if(now_temp>4095) //如果值大于0x0FFF的话说明符号位有值,就是负数
{
temp_1820[0]='-'; //显示负号
now_temp&=0x0FFF; //去除高位负号位
now_temp=now_temp>>4; //去除小数位,只取整数温度
now_temp=256-now_temp; //温度为负时要取反加一,也就相当于用256减去
}
else //如果是正数
{
temp_1820[0]='+'; //显示正号
now_temp&=0x0FFF;
now_temp=now_temp>>4;
}
now_temp=now_temp * 10;
temp_1820[1]=now_temp/1000+'0';
now_temp=now_temp % 1000;
temp_1820[2]=now_temp/100+'0';
now_temp=now_temp % 100;
temp_1820[3]=now_temp/10+'0';
temp_1820[5]=now_temp/1000+'0';//小数位还有问题
}
void main(void) {
DDRA = 0x00; /*方向输入*/
PORTA = 0xFF; /*打开上拉*/
DDRB = 0xFF; /*方向输出*/
PORTB = 0xF0; /*电平设置*/
DDRC = 0x00;
PORTC = 0xFF;
DDRD = 0x00;
PORTD = 0xFF;
delay_nms(100);
ds1820_reset(); /*复位D18B20*/
LCD_init(); /*启动显示任务*/
LCD_write_string(2,0,"Temperature");
while (1) {
ds1820();
LCD_write_string(4,1,temp_1820);
}
}
所有源码点击此处下载 ourdev_540339.rar(文件大小:63K) (原文件名:18b20.rar) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|