搜索
bottom↓
回复: 9

我也晒一下,mega16+1602+18b20的温度测量,可以显负温度!--自己写的,又不对的地方请各位

[复制链接]

出0入0汤圆

发表于 2009-11-30 09:58:02 | 显示全部楼层 |阅读模式
频率为外部晶振16M,我实验通过了!挺高兴的,但是始终觉得有点不理想,所以拿来跟大家分享一下,希望各位给点意见!

一、主程序
  //温度传感器DS18B20试验
//间隔2s采集一次温度值
//使用1602的液晶作为显示
#include <iom16v.h>     
#include <macros.h>
#include "18B20.h"
#include "1602.h"

uchar adc_0[]={"wendu:"};
uchar adc_1[]={0xdf,0x43};
uchar adc_2[]={0x2b};//正号
uchar adc_3[]={0x2d};//负号
uchar adc_4[]={0x2e};//小数点
//延时函数在16M时延时1ms
void s_1ms(unsigned int ms)
{
    unsigned int aa;
        for(;ms>=1;ms--)
        {
        for(aa=0;aa<=2000;aa++)
        {;}
        }
}       


void main()
{
unsigned int i,j,tem3,tem2,tem1,tem0;
         //int TCC;
         //float TC,t;
unsigned char buffer3[5];

//端口初始化
DDRA = 0xff;      
PORTA = 0x00;      
DDRB = 0xFF;   
PORTB = 0xF0;      
DDRC = 0x00;
PORTC = 0xFF;
DDRD = 0xff;
PORTD = 0xff;

//延时200ms
s_1ms(200);
//DS18B20复位
ds1820_reset();      
//1602 初始化
LcdInit();   
WriteChar(1,0,6,adc_0);
WriteChar(1,11,2,adc_1);

WriteChar(1,9,1,adc_4);
while (1)
  {
    ds1820_start();    //进行一次转换
    s_1ms(2);     
    i = ds1820_read_temp();   //读取温度数值f
    j=i&0xf000;
  if(j)
  {
    i=~i+1;
        WriteChar(1,6,2,adc_3);
  }
  else
  {
    WriteChar(1,6,2,adc_2);
  }
  i = (i * 10) / 16;        //数值处理  
  //第3位没有显示
  i = i % 1000;  
  //显示第2位
  tem2= i / 100;
  WriteNum(1,7,tem2);
  i = i % 100;  
  //显示第1位
  tem1= i / 10;
  WriteNum(1,8,tem1);
  tem0= i % 10;
  WriteNum(1,10,tem0);
}
  
}

二、18B20
//DS18B20连接在端口C的第7引脚

//设置成输入
#define DQ_INPUT DDRC &= ~(1 << PC7)   
//设置成输出
#define DQ_OUT DDRC |= (1 << PC7)   
//设置成低电平
#define DQ_LO PORTC &= ~(1 << PC7)  
//设置成高电平
#define DQ_HI PORTC |= (1 << PC7)   
//读出
#define DQ_R PINC & (1 << PC7)      

//中断标志
unsigned char init_f;     

//延时函数
void s_10us(unsigned int ms)
{
    unsigned int aa;
        for(;ms>=1;ms--)
        {
        for(aa=0;aa<=17;aa++)
        {;}
        }
}       

//DS18B20复位
void ds1820_reset(void)
{
unsigned char i;
//中断保护
init_f = SREG;   
//关中断
CLI();      
DQ_OUT;
DQ_LO;
s_10us(50);    //延时500us
DQ_HI;
DQ_INPUT;
s_10us(8);     //延时80us
i = DQ_R;
s_10us(50);    //延时500us
if (init_f & 0x80)  //恢复中断状态
  {   
  SEI();        
  }
}

//DS18B20字节读取
unsigned char ds1820_read_byte(void)
{
unsigned char i;
unsigned char value = 0;
//中断保护
init_f = SREG;
//关中断   
CLI();      
for (i = 8; i != 0; i--) {
  value >>= 1;
  DQ_OUT;
  DQ_LO;
  s_10us(1);
  DQ_HI;
  DQ_INPUT;
  s_10us(1);
  if (DQ_R) {
   value|=0x80;
   }
  s_10us(5);   //延时60us
  }
if (init_f & 0x80) //恢复中断状态
{   
  SEI();
  }
return(value);
}

//DS18B20字节写入
void ds1820_write_byte(unsigned char value)
{
unsigned char i;
//中断保护
init_f = SREG;   
//关中断
CLI();      
for (i = 8; i != 0; i--) {
  DQ_OUT;
  DQ_LO;
  s_10us(1);
  if (value & 0x01) {
   DQ_HI;
   }
  s_10us(8);   //延时80us
  DQ_HI;     
  value >>= 1;
  }
if (init_f & 0x80)//恢复中断状态
  {   
  SEI();
  }
}
//启动ds1820转换
void ds1820_start(void)
{
ds1820_reset();
ds1820_write_byte(0xCC); //勿略ROM
ds1820_write_byte(0x44); //启动转换
}

//读温度
unsigned int ds1820_read_temp(void)
{
unsigned int i;
unsigned char buf[9];
ds1820_reset();
ds1820_write_byte(0xCC); //勿略ROM
ds1820_write_byte(0xBE); //读温度
for (i = 0; i < 8; i++)
{
  buf = ds1820_read_byte();
  }
i = buf[1];
i <<= 8;
i |= buf[0];
return i;
}
三、1602液晶

   这个就不用了吧!

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2009-11-30 14:13:07 | 显示全部楼层
沙发

出0入0汤圆

发表于 2009-11-30 21:48:04 | 显示全部楼层
楼主的18b20是否能长线高温工作?

出0入0汤圆

 楼主| 发表于 2009-12-7 10:22:54 | 显示全部楼层
回复:【2楼】 gxy508

实验中,呵呵!应该没有问题的!

出0入0汤圆

发表于 2009-12-7 11:37:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-30 11:01:43 | 显示全部楼层
能不能把1602的也贴上啊!!!!!

出0入0汤圆

发表于 2012-8-20 19:35:49 | 显示全部楼层
能不能用!能的话赞一个!

出0入0汤圆

发表于 2012-8-20 22:03:12 | 显示全部楼层
我来贴这个1602吧
#define uchar unsigned char
#define uint unsigned int

#define RS 5
#define RW 6
#define EN 7

void s_ms(uint ms)
{
        for(;ms>1;ms--);
}       

//查忙
void busy(void)
{
    uchar temp;
        s_ms(500);
        PORTA&=~(1<<RS);    //RS=0
        s_ms(500);
        PORTA|=(1<<RW);     //RW=1
        s_ms(500);
        while(temp)
        {
                PORTA|=(1<<EN); //EN=1
                s_ms(500);
                DDRD=0x00;      //A口变输入
                PORTD=0xff;     //上拉使能
                s_ms(500);
                temp = PIND&0x80;    //读取A口
                s_ms(500);      
                DDRD=0xff;      
                PORTD=0xff;        //A口变输出
                s_ms(500);
                PORTA&=~(1<<EN);   //EN=0
                s_ms(500);
        }
}

//写指令
void writecom(uchar        com)
{
        busy();
        s_ms(500);
        PORTA&=~(1<<RS);   //RS=0
        s_ms(500);
        PORTA&=~(1<<RW);   //RW=0
        s_ms(500);
        PORTA|=(1<<EN);    //EN=1
        s_ms(500);
        PORTD = com;       //输出指令
        s_ms(500);
        PORTA&=~(1<<EN);   //EN=0
        s_ms(500);
}

//1602初始化
void        LcdInit(void)
{
    DDRD = 0xff;
    PORTD = 0x00;
        writecom(0x38);
        s_ms(1000);
        writecom(0x01);
        s_ms(1000);
        s_ms(1000);
        s_ms(1000);
        s_ms(1000);
        s_ms(1000);
        s_ms(1000);
        s_ms(1000);
        writecom(0x02);
        s_ms(1000);
        writecom(0x06);
        s_ms(1000);
        writecom(0x0c);
        s_ms(1000);
        writecom(0x38);       
        s_ms(1000);
}       

//写数据
void        writedata(uchar data)
{
        busy();
        s_ms(500);
        PORTA|=(1<<RS);   //RS=1
        s_ms(500);
        PORTA&=~(1<<RW);   //RW=0
        s_ms(500);
        PORTA|=(1<<EN);    //EN=1
        s_ms(500);
        PORTD = data;      //输出数据
        s_ms(500);
        PORTA&=~(1<<EN);   //EN=0
        s_ms(500);
}


//读数据
uchar        readdata(void)
{
        uchar temp;
        busy();
        s_ms(500);
        PORTA|=(1<<RS);  //RS=1
        s_ms(500);
        PORTA|=(1<<RW);  //RW=1
        s_ms(500);
        PORTA|=(1<<EN);  //EN=1
        s_ms(500);
        DDRD=0x00;       //A端口变输入
        s_ms(500);
        temp = PIND;     //读A端口
        s_ms(500);
        DDRD=0xff;       //A端口变输出
        s_ms(500);
        PORTA&=~(1<<EN); //EN=0
        s_ms(500);
        return temp;       
}

//=================================================
// 描述: 写LCD内部CGRAM函数
// 入口: ‘num’要写的数据个数
//        ‘pbuffer’要写的数据的首地址
// 出口: 无
//================================================
void        WriteCGRAM(uint        num, const uint        *pBuffer)
{
        uint        i,t;
        writecom(0x40);
        PORTA|=(1<<RS);
        PORTA&=~(1<<RW);
        for(i=num;i!=0;i--)
        {
                t = *pBuffer;
                PORTA|=(1<<EN);
                PORTD = t;
                PORTA&=~(1<<EN);                               
                pBuffer++;
        }
       
}

//=================================================
//描述:写菜单函数,本程序使用的LCD规格为 16 * 2
//入口:菜单数组首地址
//出口:无
//=================================================
void        WriteMenu(const uchar *pBuffer)
{
        uchar        i,t;
        writecom(0x80);   //数据地址
       
        PORTA|=(1<<RS);
        PORTA&=~(1<<RW);
        s_ms(50);
        for(i=0;i<16;i++)
        {
                t = *pBuffer;
                PORTD = t;
                PORTA|=(1<<EN);
                s_ms(50);
                PORTA&=~(1<<EN);                               
                pBuffer++;
        }
        writecom(0xC0);

        PORTA|=(1<<RS);
        PORTA&=~(1<<RW);
        s_ms(50);       
        for(i=0;i<16;i++)
        {
                t = *pBuffer;
                PORTD = t;
                PORTA|=(1<<EN);
                s_ms(50);
                PORTA&=~(1<<EN);                               
                pBuffer++;
        }
}
//====================================================
// 描述:在任意位置写数字函数
// 入口:’row‘表示要写数字所在的行地址,只能为1或2
//       ’col‘表示要写数字所在的列地址,只能为0--15
//                 ‘num’表示要写的数字,只能为0--9
// 出口:无
//===================================================
void        WriteNum(uint        row,uint        col,uint         num)
{
        if (row == 1)        row = 0x80 + col;
        else        row = 0xC0 + col;
        writecom(row);
        if (num<=0 | num>9)        num =0x30;
        else        num = 0x30 + num;

        PORTA|=(1<<RS);
        s_ms(500);
        PORTA&=~(1<<RW);
        s_ms(500);
        PORTD = num;
        s_ms(500);
        PORTA|=(1<<EN);
        s_ms(500);
        PORTA&=~(1<<EN);       
        s_ms(500);                       
}
//================================================================
// 描述:在任意位置写任意多个字符
// 入口:’row‘要写的字符所在的行,只能为1或2;
//       ‘col’要写的字符所在的列,只能为0---15
//       ‘num’要写字符的个数
//       ‘pbuffer’要写字符的首地址
//==================================================================
void        WriteChar(uchar row,uchar col,uint num,uchar *pBuffer)
{
        uchar i,t;
        if (row == 1)        row = 0x80 + col;
        else        row = 0xC0 + col;
        writecom(row);
        //if (num<=0 | num>9)        num =0x30;
        //else        num = 0x30 + num;

        PORTA|=(1<<RS);
        s_ms(500);
        PORTA&=~(1<<RW);
        s_ms(500);
        for(i=num;i!=0;i--)
        {
                t = *pBuffer;
                s_ms(500);
                PORTD = t;
                s_ms(500);
                PORTA|=(1<<EN);
                s_ms(500);
                PORTA&=~(1<<EN);               
                s_ms(500);               
                pBuffer++;
        }
       
}

出0入0汤圆

发表于 2012-11-6 11:00:28 | 显示全部楼层
学习了,最近也想做个。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-8-27 01:20

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

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