#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). }
|