mega8和ds18b20的温度采集程序
2012-06-30

本程序为采用mega8 和ds18b20的温度采集程序

选用mega8内部8M RC震荡,ds18b20 数据线接pd6,数据线和vcc间接一4.7k上拉电阻

感谢dfgeoff 嗜血蜗牛提供的资料*/

#include < avr / io.h >
#include <timer.h>
#define uchar unsigned char
#define uint unsigned int
void init_1820();
write_1820(uchar x);
uchar read_1820();
void send_byte(uchar x);
void delay(uint x);
void disp_led(uchar buffer, uchar control);

uchardisp_table[16] = {
    0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
    0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};
uchar dp;
long count;

void main(void) //主函数
{
    disp_led(0, 0);
    delay(2000);
    OSCCAL = 0X9d; //系统时钟校准,不同的芯片和不同的频率,
    DDRC = 0xff;
    DDRD = 0XFF;
    PORTD = 0XFF;
    WDR();//看门狗计数清零
    WDTCR = 0x0F;
    PORTC = 0xff;

    while (1) {
        uchar i, temh, teml;
        init_1820();//复位18b20
        write_1820(0xcc);// 发出转换命令
        write_1820(0x44);
        delay(400);
        init_1820();
        WDR();
        write_1820(0xcc);//发出读命令
        write_1820(0xbe);
        teml = read_1820(); //读数据
        temh = read_1820();
//for(i=0;i<7;i++)//测试用
//{
//send_byte(0x40);
//send_byte(disp_table[0&0x0f]);
//}
//send_byte(disp_table[temh>>4]);
//send_byte(disp_table[temh&0x0f]);
//send_byte(disp_table[teml>>4]);
//send_byte(disp_table[teml&0x0f]);
        count = (temh * 256 + teml) * 6.25; //计算具体温度
        WDR();
        disp_led(0, 1); //显示温度
        for (i = 0; i < 100; i++) { //每次转换需要延时200ms以上
            delay(1000);
        }
    }
}

void delay(uint x)//1.5us左右
{
    while (x) {
        x--;
    }
}

void init_1820()
{
    PORTD |= (1 << 6);
    PORTD &= ~(1 << 6);
    delay(3000);//480us以上
    PORTD |= (1 << 6);
    DDRD &= ~(1 << 6);
    delay(40);//15~60us
    while (PIND & (1 << 6)) {
// disp_led(3,0);
// for(;;)
//{}
    }
    DDRD |= (1 << 6);
    PORTD |= (1 << 6);
    delay(150);//60~240us
}

write_1820(uchar x)
{
    uchar m;
    for (m = 0; m < 8; m++) {
        PORTD &= ~(1 << 6);
        if (x & (1 << m)) {
            PORTD |= (1 << 6);
        }
        else {
            PORTD &= ~(1 << 6);
        }
        delay(40);//15~60us
        PORTD |= (1 << 6);
    }
    PORTD |= (1 << 6);
}

uchar read_1820()
{
    uchar temp, k, n;
    temp = 0;
    for (n = 0; n < 8; n++) {
        PORTD &= ~(1 << 6);
//delay(2);
        PORTD |= (1 << 6);
//delay(3);
        DDRD &= ~(1 << 6);
        k = (PIND & (1 << 6)); //读数据,从低位开始
        if (k) {
            temp |= (1 << n);
        }
        else {
            temp &= ~(1 << n);
        }
        delay(50); //60~120us
        DDRD |= (1 << 6);
    }
    return (temp);
}
void send_byte(uchar x)//以下为显示程序
{
    uchar i;
    for (i = 0; i < 8; i++) {
        PORTC &= ~(1 << 5); // PC5为底为164提供时钟信号
        if ((x & (1 << (7 - i))) || ((dp == 1) && (i == 0))) { //判断每位数据的电平,及小数点判断
            PORTC |= (1 << 4);    //若为高着PC4输出高电平
        }
        else {
            PORTC &= ~(1 << 4);    //若为低着输出低电平
        }
        PORTC |= (1 << 5); //PC5 提供始终信号
    }
//PORTC|=((1<<0)|(1<<1)|(1<<2));
}

//显示程序 CONTROL为控制显示 BUFFER为显示数据
void disp_led(uchar buffer, uchar control)
{
    uchar i, temp[6];
    uint tempcount;
    dp = 0;
    switch (control) {
    case 0: { //CONTROL为零全部数码管显示buffer
        for (i = 0; i < 11; i++) {
            send_byte(disp_table[buffer % 10]);    //显示数字
        }
        break;
    }
    case 1: { //control为1,显示count中的数据为6位
        tempcount = count;
        for (i = 0; i < 6; i++) { //取出每位中的数据
            temp[i] = tempcount % 10;
            tempcount /= 10;
        }
        send_byte(disp_table[buffer / 10]); //最开始显示buffer数据
        send_byte(disp_table[buffer % 10]);
        send_byte(0x00);
        send_byte(0x00);
        send_byte(0x00);
        for (i = 0; i < 6; i++) {
            if (i == 3) {
                dp = 1;    //小数点控制位
            }
            send_byte(disp_table[temp[5 - i]]);
            dp = 0;
        }
        break;
    }
    }

    PORTC |= (1 << 4);
}


可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号