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