M16+DS18B20+1602+Proteus新手学AVR,有问题请教
最近在坛子找了些例子,学习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='-'; //显示负号
now_temp&=0x0FFF; //去除高位负号位
now_temp=now_temp>>4; //去除小数位,只取整数温度
now_temp=256-now_temp; //温度为负时要取反加一,也就相当于用256减去
}
else //如果是正数
{
temp_1820='+'; //显示正号
now_temp&=0x0FFF;
now_temp=now_temp>>4;
}
now_temp=now_temp * 10;
temp_1820=now_temp/1000+'0';
now_temp=now_temp % 1000;
temp_1820=now_temp/100+'0';
now_temp=now_temp % 100;
temp_1820=now_temp/10+'0';
temp_1820=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) 提几点个人看法:
1.“temp_1820=now_temp/1000+'0';//小数位还有问题”这一语句已经把小数点后一位的值限定在0了,所以你的仿真电路 时小数点后当然显示0了;
2 “now_temp=now_temp>>4; //去除小数位,只取整数温度”这一语句把小数点后的位数全去掉了,就算在仿真时读出了小数点后的值那也是没有意义的;
3“temphl=(temph<<8)|templ; //数据高低位合并”这一语句中的temphl是char型的,也就是说是8字节的,当其右移8位后其值为0;
我的建议是:保留小数位,利用T=(temph*256+templ)*0.0625得出温度值;若定义T为int型则可以利用T=(temph*256+templ)*625,然后将值分配到temp_1820[]中。 回复【1楼】zhuzhuaman
-----------------------------------------------------------------------
非常感谢! 留个记号回来研究~ 你把小数位给虑掉了 now_temp中没有小数位 晚上我把我修改后的传一分 markk {:smile:}{:smile:}{:smile:} 初学Avr标记学习中! {:smile:}{:smile:}{:smile:}{:smile:}{:smile:} 正在弄DS18B20的制作,不错,受益匪浅 liliuqun 发表于 2010-4-9 20:53 static/image/common/back.gif
回复【1楼】zhuzhuaman
-----------------------------------------------------------------------
楼主,为什么复位函数,写函数,读函数的时候要中断保护呢???不要有什么坏处呢??
还有就是这个时隙的问题,这个是精准的时隙吗??感觉和datasheet上有点点区别,嘿嘿,菜鸟一名,求赐教 学习!初学Avr标记学习中
页:
[1]