搜索
bottom↓
回复: 13

M16+DS18B20+1602+Proteus新手学AVR,有问题请教

[复制链接]

出0入0汤圆

发表于 2010-3-23 01:35:22 | 显示全部楼层 |阅读模式
最近在坛子找了些例子,学习DS1820,现在可以显示温度的正负以及百,十,个位,但小数后的温度始终显示0,在仿真上只有步进1度的没发现,下载到目标板上,小数后始终显示0无变化,我猜问题可能出在数值的处理上,本人是刚学AVR的新手,现附上代码,请老师修改,最好附上注释,帮助我们这些初学者,不胜感激!

附:仿真效果图
(原文件名: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, 杜汶泽)

出0入0汤圆

发表于 2010-3-27 18:36:27 | 显示全部楼层
提几点个人看法:
1.“temp_1820[5]=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[]中。

出0入0汤圆

 楼主| 发表于 2010-4-9 20:53:48 | 显示全部楼层
回复【1楼】zhuzhuaman
-----------------------------------------------------------------------

非常感谢!

出0入0汤圆

发表于 2010-4-23 17:18:47 | 显示全部楼层
留个记号回来研究~

出0入0汤圆

发表于 2010-4-29 08:16:20 | 显示全部楼层
你把小数位给虑掉了

出0入0汤圆

发表于 2010-4-29 08:17:06 | 显示全部楼层
now_temp中没有小数位

出0入0汤圆

发表于 2010-4-29 08:18:02 | 显示全部楼层
晚上我把我修改后的传一分

出0入0汤圆

发表于 2011-4-15 10:35:54 | 显示全部楼层
markk

出0入0汤圆

发表于 2012-10-19 16:34:06 | 显示全部楼层

出0入0汤圆

发表于 2012-10-24 00:17:14 来自手机 | 显示全部楼层
初学Avr标记学习中!

出0入0汤圆

发表于 2012-11-4 18:02:08 | 显示全部楼层

出0入0汤圆

发表于 2012-11-9 23:25:32 | 显示全部楼层
正在弄DS18B20的制作,不错,受益匪浅

出0入0汤圆

发表于 2012-11-9 23:30:08 | 显示全部楼层
liliuqun 发表于 2010-4-9 20:53
回复【1楼】zhuzhuaman
-----------------------------------------------------------------------

楼主,为什么复位函数,写函数,读函数的时候要中断保护呢???不要有什么坏处呢??
还有就是这个时隙的问题,这个是精准的时隙吗??感觉和datasheet上有点点区别,嘿嘿,菜鸟一名,求赐教

出0入0汤圆

发表于 2013-1-24 16:32:02 | 显示全部楼层
学习!初学Avr标记学习中
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表