目前共有1篇帖子。
【程序】AVR单片机数码管显示温度版本2(2014年3月16日版)
1樓 巨大八爪鱼 2014-9-30 23:06
#include <iom8v.h>
#include <macros.h>

//DS18B20
#define DQ (PIND&BIT(3))
#define DQ_0 PORTD&=~BIT(3)
#define DQ_1 PORTD|=BIT(3)
#define DQ_IN DDRD&=~BIT(3)
#define DQ_OUT DDRD|=BIT(3)

//keys
#define K1 (PINC&BIT(0))
#define K2 (PINC&BIT(1))
#define K3 (PINC&BIT(2))
#define K4 (PINC&BIT(3))

flash char const SEG8[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
#define NEG 4
#define CNT 5
#define CE 6
#define LTEN 7 //less than -10
unsigned char SA=0x00;
unsigned char SB=0x00;

unsigned int number=989;

void delay_250us(void)
{
    unsigned int i;
    for (i=0;i<285;i++);
}

void delay_us(unsigned int n)
{
    if (n==0)
        return;
    while (--n);
}

void delay(unsigned int n)
{
    unsigned int i;
    while (n--)
        for (i=0;i<1140;i++);
}

void DS18B20_Error(void)
{
    PORTB=0x86;
    PORTD&=~BIT(4);
    while (1);
}

void DS18B20_Init(void)
{
    DQ_OUT;
    DQ_1;
    delay_us(6);
    DQ_0;
    delay_us(600);
    DQ_1;
    delay_us(120);
    if (DQ)
        DS18B20_Error();
    delay_us(620);
}

unsigned char DS18B20_Read(void)
{
    unsigned char i,dat;
    for (i=0;i<8;i++)
    {
        DQ_OUT;
        DQ_1;
        delay_us(2);
        DQ_0;
        delay_us(4);
        DQ_1;
        delay_us(6);
        dat>>=1;

        if (DQ)
            dat|=0x80;
        else
            dat|=0x00;
        delay_us(60);
    }
    return dat;
}

void DS18B20_Write(unsigned char dat)
{
    unsigned char i;
    for (i=0;i<8;i++)
    {
        DQ_OUT;
        DQ_1;
        delay_us(2);
        DQ_0;
        if (dat&0x01)
            DQ_IN;
        else
            DQ_OUT;

        delay_us(30);
        DQ_1;
        delay_us(3);
        dat>>=1;
    }
    delay_us(10);
}

void DS18B20_ReadyReadTemp(void)
{
    DS18B20_Init();
    DS18B20_Write(0xcc);
    DS18B20_Write(0x44);
    delay_us(20);

    DS18B20_Init();
    DS18B20_Write(0xcc);
    DS18B20_Write(0xbe);
}

void seg8_scan(unsigned char n)
{
    unsigned char d[3];
    unsigned char p;
    while (n--)
    {
        if (SB<35)
        {
            PORTB=0xbf;
            PORTD&=0x0f; //clear the high 4 bits
            PORTD|=0x90; //1001xxxx
            delay(1);
            continue;
        }

        d[0]=number/1000;
        d[1]=number%1000/100;
        d[2]=number%100/10;
        d[3]=number%10;
        SA&=~BIT(LTEN); //clear LTEN
        p=1;
        PORTD|=0xf0; //set the high 4 bits to switch off all the LEDs

        if (SA&BIT(CE))
        {
            PORTB=SEG8[d[0]];
            if (d[0]>0)
            {
                PORTD&=~BIT(4);
                SA|=BIT(LTEN);
            }
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[1]];
            if (d[1]>0 || (SA&BIT(LTEN)))
            {
                PORTD&=~BIT(5);
                SA|=BIT(LTEN);
            }            
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[2]];
            if (d[2]>0 || (SA&BIT(LTEN)))
                PORTD&=~BIT(6);
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[3]];
            PORTD&=~BIT(7);
            delay_250us();
        }
        else
        {
            if (SA&BIT(NEG))
            {
                PORTB=0xbf;
                if (d[0]>0)
                {
                    SA|=BIT(LTEN); //set LTEN
                    p=0;
                }
            }
            else if (d[0]>0)
                PORTB=SEG8[d[0]];
            else
                PORTB=0xff;
            PORTD&=~BIT(4);
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[p]]+((SA&BIT(LTEN))?0x00:0x80);
            PORTD&=~BIT(5);
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[p+1]]+((SA&BIT(LTEN))?0x80:0x00);
            PORTD&=~BIT(6);
            delay_250us();

            PORTD|=0xf0;
            PORTB=SEG8[d[p+2]];
            PORTD&=~BIT(7);
            delay_250us();
        }
    }
    PORTD|=0xf0;
}

void DS18B20_Measure(void)
{
    unsigned char tl,th,tltemp;
    unsigned char tn,td;
    DS18B20_ReadyReadTemp();
    tl=DS18B20_Read();
    th=DS18B20_Read();

    if ((th&0xf8)!=0x00)
    {
        SA|=BIT(NEG);
        tl=~tl;
        th=~th;
        tltemp=tl+1;
        tl=tltemp;
        if (tltemp>=255)
            th++;
        
        //tn=th*16+tl/16;
        //td=(tl%16)*10/16;
    }
    else
        SA&=~BIT(NEG);

    tn=th*16+tl/16;
    td=(tl&0x0f)*625/100; //*6.25

    number=tn*100+td%100;

    if (SB!=255)
        SB++;

    seg8_scan(10);
}

void key_scan(void)
{
    if (SB<40)
        return;

    if (!K1)
    {
        seg8_scan(3);
        if (!K1)
        {
            if (SA&BIT(CE))
            {
                if (TCCR1B==0x00)
                {
                    //Start Timer 1
                    TCNT1H=0x85;
                    TCNT1L=0xee; //1s
                    TCCR1B=0x04;
                }
                else
                    TCCR1B=0x00; //Stop Timer 1
            }
            else
            {
                SA|=BIT(CE);
                number=0;
            }
            while (!K1)
                seg8_scan(3);
            seg8_scan(20);
        }
    }

    if (SA&BIT(CE))
    {
        if (!K2)
        {
            seg8_scan(3);
            if (!K2)
            {
                number++;
                if (number>9999)
                    number=0;
                while (!K2)
                    seg8_scan(1);
                seg8_scan(2);
            }
        }
        if (!K3)
        {
            seg8_scan(3);
            if (!K3)
            {
                if (number==0)
                    number=9999;
                else
                    number--;
                while (!K3)
                    seg8_scan(1);
                seg8_scan(2);
            }
        }

        if (!K4)
        {
            seg8_scan(3);
            if (!K4)
            {
                TCCR1B=0x00; //stop timer and exit
                SA&=~BIT(CE);
                while (!K4)
                    seg8_scan(1);
                seg8_scan(2);
            }
        }
    }
}

void main(void)
{
    PORTB=DDRB=0xff;
    DDRC=0x00;
    PORTC=0xff;
    PORTD=DDRD=0xff;

    SEI();
    TIMSK|=BIT(TOIE1); //allow Timer 1 overflow interrupt
    DS18B20_Init();

    while (1)
    {
        seg8_scan(1);
        DS18B20_Measure();
        key_scan();

        while (SA&BIT(CE))
        {
            key_scan();
            seg8_scan(1);
        }
    }
}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
    TCNT1H=0x85;
    TCNT1L=0xee; //1s

    if (number>=9999)
        number=0;
    else
        number++;

    //Note: If you use a crystal of 7.3728MHz, the timer will not be as accurate as 8MHz (internal RC oscillator).
}

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
 
 
©2010-2024 Arslanbar [手機版] [桌面版]
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。