luck2009 发表于 2009-11-30 09:58:02

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

频率为外部晶振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;

//端口初始化
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;
ds1820_reset();
ds1820_write_byte(0xCC); //勿略ROM
ds1820_write_byte(0xBE); //读温度
for (i = 0; i < 8; i++)
{
buf = ds1820_read_byte();
}
i = buf;
i <<= 8;
i |= buf;
return i;
}
三、1602液晶

   这个就不用了吧!

caep1986 发表于 2009-11-30 14:13:07

沙发

gxy508 发表于 2009-11-30 21:48:04

楼主的18b20是否能长线高温工作?

luck2009 发表于 2009-12-7 10:22:54

回复:【2楼】 gxy508

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

12fen 发表于 2009-12-7 11:37:29

mark

lwliuming063 发表于 2011-11-30 11:01:43

能不能把1602的也贴上啊!!!!!

似水、流年 发表于 2012-8-20 19:35:49

{:2_35:}能不能用!能的话赞一个!

xqn2012 发表于 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++;
        }
       
}

andyw 发表于 2012-11-6 11:00:28

学习了,最近也想做个。

jz701209李 发表于 2013-4-7 17:15:35

学习一下....
页: [1]
查看完整版本: 我也晒一下,mega16+1602+18b20的温度测量,可以显负温度!--自己写的,又不对的地方请各位