这个实验,在上一个的基础上,增加了对DS1302的支持.其实就是一个时钟+温度计.源码如下:
#include <mega16.h>
#include<delay.h>
#define DQ PORTD.0//set appoint bit low
#define DDQ DDRD.0//set appoint bit high
#define GDQ PIND.0//get appoint bit level
#define LCD_DATA_PORT PORTA //the next three port should be the same
#define LCD_DATA_DDR DDRA //must use the high 4bit
#define LCD_DATA_PIN PINA
#define LCD_RS PORTA.0 //RS lcd
#define LCD_WR PORTA.1//WR lcd
#define LCD_EN PORTA.2 //EN lcd
#define LCD_DRS DDRA.0 //WR direction define
#define LCD_DWR DDRA.1 //RS direction define
#define LCD_DEN DDRA.2 //EN direction define
#define LCD_DATA 0xf0 //DATA PORT
#define uchar unsigned char
#define uint unsigned int
#define DS1302_PORT PORTC
#define DS1302_DDR DDRC
#define DS1302_PIN PINC
#define T_RST 2 //pc0
#define T_IO 1 //pc1
#define T_CLK 0 //pc2
#define SETBIT(x,y) (x|=(1<<y))//set appoint bit high
#define CLRBIT(x,y) (x&=(~(1<<y)))//set appoint bit low
#define CHKBIT(x,y) (x&(1<<y))//get appoint bit level
uchar right;
//write one byte data to ds1302
void ds1302_write_a_byte(unsigned char ucDa)
{
unsigned char i;
for(i=8; i>0; i--)
{
CLRBIT(DS1302_PORT,T_CLK);//set PC2 low
if (ucDa&1) SETBIT(DS1302_PORT,T_IO);//set PC1 high
else CLRBIT(DS1302_PORT,T_IO);//set PC1 low
SETBIT(DS1302_PORT,T_CLK);//set PC2 high
ucDa>>=1;
}
}
//read one byte data from ds1302
unsigned char ds1302_read_a_byte(void)
{
unsigned char i,t=0;
CLRBIT(DS1302_DDR,T_IO);//set pc1 input
CLRBIT(DS1302_PORT,T_IO);//set PC1 low(high resistance)
for(i=8; i>0; i--)
{
t>>=1;
SETBIT(DS1302_PORT,T_CLK);
delay_us(1);//can't remove!
CLRBIT(DS1302_PORT,T_CLK);
delay_us(1);//can't remove!
if(CHKBIT(DS1302_PIN,T_IO))t|=0x80;
}
SETBIT(DS1302_DDR,T_IO);//set pc1 OUTPUT
return(t);
}
//write data to appoint address
void write_1302(unsigned char ucAddr, unsigned char ucDa)
{
CLRBIT(DS1302_PORT,T_RST);
CLRBIT(DS1302_PORT,T_CLK);
SETBIT(DS1302_PORT,T_RST);
ds1302_write_a_byte(ucAddr);
CLRBIT(DS1302_PORT,T_CLK);
ds1302_write_a_byte(ucDa);
CLRBIT(DS1302_PORT,T_CLK);
CLRBIT(DS1302_PORT,T_RST);
}
//read data from appoint address
unsigned char read_1302(unsigned char ucAddr)
{
unsigned char ucDa;
CLRBIT(DS1302_PORT,T_RST);
CLRBIT(DS1302_PORT,T_CLK);
SETBIT(DS1302_PORT,T_RST);
ds1302_write_a_byte(ucAddr);
ucDa = ds1302_read_a_byte();
CLRBIT(DS1302_PORT,T_CLK);
CLRBIT(DS1302_PORT,T_RST);
return(ucDa);
}
//get data from ds1302
void v_Get1302(unsigned char ucCurtime[])
{
unsigned char i;
unsigned char ucAddr = 0x81;
for (i=0;i<7;i++)
{
ucCurtime = read_1302(ucAddr);
ucAddr += 2;
}
CLRBIT(DS1302_PORT,T_CLK);
}
//init ds1302
void initialize_1302(void)
{
SETBIT(DS1302_PORT,T_CLK);
SETBIT(DS1302_PORT,T_IO);
SETBIT(DS1302_PORT,T_RST);
SETBIT(DS1302_DDR,T_CLK);
SETBIT(DS1302_DDR,T_IO);
SETBIT(DS1302_DDR,T_RST);
delay_us(1);//can't remove!
write_1302(0x8e,0x00);
write_1302(0x90,0xA5);
write_1302(0x80,0x00);
}
//only 24 hours system
//change data from bin to dec
void revise(unsigned char t[7])
{
unsigned char t1,t2,temp,i;
for(i=0;i<7;i++)
{
temp=t;
temp<<=4;
temp>>=4;
t1=temp;
temp=t;
if(i!=2)temp>>=4;
else
{
temp<<=1;
temp>>=5;
}
t2=temp;
t=t1+t2*10;
}
}
/*
LCD_Write(1,command)
1602 command:0x0f show cursor and flash
0x0c do now show cursor
*/
void LCD_en_write(void) //enable LCD
{
LCD_DEN=1;//SET LCD_EN OUTPUT
LCD_EN=1;//EN=1
delay_us(10);
LCD_EN=0;//EN=0
}
//cord:when 1,write command when 0,write data
//data:command or data you want to write to 1602
void LCD_Write(char cord,unsigned char data) //write data
{
delay_us(25);
LCD_DRS=1;//SET RS OUTPUT
if(cord==0)LCD_RS=1; //RS=1,write data
else LCD_RS=0;//RS=0,write command
LCD_DATA_PORT&=0X0f; //clr high 4bit
LCD_DATA_PORT|=data&0xf0; //wirte high 4bit
LCD_en_write();
data=data<<4; //turn the low 4bit to high 4bit
LCD_DATA_PORT&=0X0f; //clr high 4bit
LCD_DATA_PORT|=data&0xf0; //write low 4bit
LCD_en_write();
}
void LCD_init(void) //lcd init
{
LCD_DWR=1;//set en output
LCD_WR=0;//write enable
LCD_DATA_DDR|=LCD_DATA; //set data port out
LCD_EN=1;// set EN out
LCD_RS=1;// set RS out
delay_us(40);
LCD_Write(1,0x28); //4bit show
LCD_Write(1,0x0c); //do now show cursor
LCD_Write(1,0x01); //clr
delay_ms(2);
}
//orientation a dress
//x:0 or 1
//y:0-15
void LCD_set_xy( unsigned char x, unsigned char y ) //write address funcation
{
unsigned char address;
if (y==0) address=0x80+x;
else address=0xc0+x;
LCD_Write(1,address);
}
//from a appointed address write string to 1602
//col x=0~15,row y=0,1
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char flash *s)
{
LCD_set_xy(X,Y); //write address
while (*s) // write the char to show
{
LCD_Write(0,*s);
s++;
}
}
//write a char to appointed address
void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data) //col x=0~15,row y=0,1
{
LCD_set_xy(X,Y); //write address
LCD_Write(0,data);
}
//reset ds1820
void res1820 (void) // Reset TX
{
DDQ=1;//SET PA0 OUTPUT
DQ=0;//PA0 0
delay_us(750); // Approx 750 uS
DQ=1;//PA0 1
delay_us(15);//15US
}
//wait for presence of 1820
void check1820 (void) // Wait for Presence RX 'ó?úó|'e
{
DDQ=0;//SET PA0 INPUT
while (GDQ==1);
while (GDQ==0);
delay_us(45);//??
}
//read bit data from 1820
unsigned char read1820bit (void) // read one bit
{
unsigned char dat;
DDQ=1;//SET PA0 OUTPUT
DQ=0;
delay_us(1);
DQ=1;
DDQ=0;//SET PA0 INPUT
delay_us(2);
dat=GDQ;
delay_us(45);
return (dat);
}
//read one byte from 1820
unsigned char read1820byte (void) // read one byte
{
unsigned char i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=read1820bit();
dat=(j<<7)|(dat>>1);
}
return (dat);
}
//write one byte to 1820
void write1820byte (unsigned char dat) // write one byte
{
unsigned char j;
unsigned char testb;
DDQ=1;//SET PA0 OUTPUT;
for (j=1;j<=8;j++) {
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DQ=0; // Write 1
delay_us(2);
DQ=1;
delay_us(45);
}
else
{
DQ=0; // Write 0
delay_us(45);
DQ=1;
delay_us(2);
}
}
}
//start conver temperature
void start1820 (void) // ds1820 start convert
{
res1820 ();
check1820 ();
//delay_ms(1);
write1820byte (0xcc); // skip rom
write1820byte (0x44); // convert
}
//read temperature from1820
//TH,high 4 bit of temperature
//TL,low 8 bit of temperature
void read1820 (unsigned char *TH,unsigned char *TL) // read temp
{
res1820 ();
check1820 ();
//delay_ms(1);
write1820byte (0xcc); // skip rom
write1820byte (0xbe); // convert
*TL=read1820byte(); // LSB
*TH=read1820byte(); // MSB
}
//x^y function,do not beyond the range!
long pow(unsigned char x,unsigned char y)
{
long ans;
unsigned char i;
ans=x;
if(y==0)return 1;//x^0=1
for(i=0;i<y-1;i++)ans*=x;
return ans;
}
//get data from 1820
//return temperture range:-55.0~+125.9
int get1820temp(void)
{
unsigned char TL,TH,j,jud;
float t;
start1820 ();// ds1820 start convert
read1820 (&TH,&TL);// read temperature
jud=TH;//juder weather temperature is >0 or <0
for(j=0;j<11;j++)//get the temperature
{
if((jud>>4)==0)//T>0
{
if(j<8)//low 8 bit
{
t+=(TL&0x01)*pow(2,j);
TL>>=1;
}
else //high 3 bit
{
t+=(TH&0x01)*pow(2,j);
TH>>=1;
}
}
else //t<0
{
if(j<8)//low 8 bit
{
t+=(!(TL&0x01))*pow(2,j);
TL>>=1;
}
else //high 3 bit
{
t+=(!(TH&0x01))*pow(2,j);
TH>>=1;
}
}
}
t*=0.625;//change
if(jud>>4)return -t;//T<0
else return t;//T>0
}
unsigned char hextodec(unsigned char num)
{
unsigned char res=0;
res=num%10+((num/10)%10)*16;
return res;
}
unsigned char key_scan() //check if key pressed
{
uchar juder;
uchar which; //scan which row
uchar juder1=0; //juder whether key-press undo
DDRB=0X0F;//set low 4 output high 4 input
PORTB=0XFF;//output high leve
for(which=0;which<4;which++)
{
juder=0;
switch(which)//choice key row
{
case 0:{PORTB=0Xfe;break;} //11111110
case 1:{PORTB=0Xfd;break;} //11111101
case 2:{PORTB=0Xfb;break;} //11111011
case 3:{PORTB=0Xf7;break;} //11110111
}
if(right)//get key number
{
while((PINB&0x80)==0)
{
juder++;
if(juder>250){right=0;return(0+4*which);}
}
juder=0;
while((PINB&0x40)==0)
{
juder++;
if(juder>250){right=0;return(1+4*which);}
}
juder=0;
while((PINB&0x20)==0)
{
juder++;
if(juder>250){right=0;return(2+4*which);}
}
juder=0;
while((PINB&0x10)==0)
{
juder++;
if(juder>250){right=0;return(3+4*which);}
}
}
else if((PINB&0x10)!=0&&(PINB&0x20)!=0&&(PINB&0x40)!=0&&(PINB&0x80)!=0)juder1++;
else delay_us(300);//compensate
}
if(juder1==4)right=1;
return 16; //if no key pull down return 16
}
/*
void main(void)
{
unsigned char conv[10]={'0','1','2','3','4','5','6','7','8','9'};
int tem;
unsigned char temp[7];
initialize_1302();
write_1302(0x8e,0x00);//set vialib
write_1302(0x80,0x33);//second set
write_1302(0x82,0x55);//minute set
write_1302(0x84,0x11);//hour set
write_1302(0x86,0x30);//day set
write_1302(0x88,0x05);//month set
write_1302(0x8a,0x03);//week set
write_1302(0x8c,0x07);//year set
write_1302(0x8e,0x80);//set unvialib
delay_ms(200);//delay 4s
LCD_init();
LCD_write_string(0,0,"TIME: - -");
while(1)
{
v_Get1302(temp);
revise(temp);
LCD_write_char(6,0,conv[temp[2]%10]);
LCD_write_char(5,0,conv[(temp[2]/10)%10]);
LCD_write_char(9,0,conv[temp[1]%10]);
LCD_write_char(8,0,conv[(temp[1]/10)%10]);
LCD_write_char(12,0,conv[temp[0]%10]);
LCD_write_char(11,0,conv[(temp[0]/10)%10]);
tem=get1820temp();
LCD_write_char(11,1,'C');
LCD_write_char(10,1,223);
LCD_write_char(8,1,conv[tem%10]);
LCD_write_char(7,1,'.');
LCD_write_char(6,1,conv[(tem/10)%10]);
LCD_write_char(5,1,conv[(tem/100)%10]);
}
}
*/
void main(void)
{
unsigned char t,t1,t2,key;
unsigned char temp[7];
long tem;
unsigned char cor[10]={'0','1','2','3','4','5','6','7','8','9'};
initialize_1302();
write_1302(0x82,0x51);//59min
write_1302(0x80,0x02);//40sec
write_1302(0x84,0x11);//23h
write_1302(0x86,0x30);//31d
write_1302(0x88,0x05);//12m
write_1302(0x8a,0x03);//7x
write_1302(0x8c,0x07);//06y
write_1302(0x8e,0x80);
delay_ms(200);
LCD_init();
LCD_write_string(1,0,"20 - -");
LCD_write_string(2,1,"- -");
//temp0 sec,temp1 min,temp2 hour,temp3 day,temp4 month,temp5 week,temp6 year
while(1)
{
v_Get1302(temp);
revise(temp);
key=key_scan();
if(key!=16)
{
write_1302(0x8e,0x00);
switch(key)
{
case 0:temp[0]++;write_1302(0x80,hextodec(temp[0]));break;//set second
case 1:temp[0]--;write_1302(0x80,hextodec(temp[0]));break;
case 2:temp[1]++;write_1302(0x82,hextodec(temp[1]));break;//set miniute
case 3:temp[1]--;write_1302(0x82,hextodec(temp[1]));break;
case 4:temp[2]++;write_1302(0x84,hextodec(temp[2]));break;//set hour
case 5:temp[2]--;write_1302(0x84,hextodec(temp[2]));break;
case 6:temp[3]++;write_1302(0x86,hextodec(temp[3]));break;//set day
case 7:temp[3]--;write_1302(0x86,hextodec(temp[3]));break;
case 8:temp[4]++;write_1302(0x88,hextodec(temp[4]));break;//set month
case 9:temp[4]--;write_1302(0x88,hextodec(temp[4]));break;
case 10:temp[5]++;write_1302(0x8a,hextodec(temp[5]));break;//set week
case 11:temp[5]--;write_1302(0x8a,hextodec(temp[5]));break;
case 12:temp[6]++;write_1302(0x8c,hextodec(temp[6]));break;//set week
case 13:temp[6]--;write_1302(0x8c,hextodec(temp[6]));break;
}
write_1302(0x8e,0x80);
}
//display time
t1=temp[0]%10;
t2=(temp[0]/10)%10;
LCD_write_char(7,1,cor[t1]);
LCD_write_char(6,1,cor[t2]);
t1=temp[1]%10;
t2=(temp[1]/10)%10;
LCD_write_char(4,1,cor[t1]);
LCD_write_char(3,1,cor[t2]);
t1=temp[2]%10;
t2=(temp[2]/10)%10;
LCD_write_char(1,1,cor[t1]);
LCD_write_char(0,1,cor[t2]);
//display temprature
tem=get1820temp();
LCD_write_char(15,1,'C'); //degree
LCD_write_char(14,1,223); //degree
LCD_write_char(13,1,cor[tem%10]);
LCD_write_char(12,1,'.');
t=(tem/10)%10;
LCD_write_char(11,1,cor[(tem/10)%10]);
//t=(tem/100)%10;
LCD_write_char(10,1,cor[(tem/100)%10]);
// LCD_write_char(9,1,'T');
//LCD_write_char(10,1,'=');
//display date
t1=temp[3]%10;
t2=(temp[3]/10)%10;
LCD_write_char(10,0,cor[t1]);
LCD_write_char(9,0,cor[t2]);
t1=temp[4]%10;
t2=(temp[4]/10)%10;
LCD_write_char(7,0,cor[t1]);
LCD_write_char(6,0,cor[t2]);
t1=temp[5]%10;
t2=(temp[5]/10)%10;
LCD_write_char(14,0,cor[t1]);
LCD_write_char(13,0,cor[t2]);
t1=temp[6]%10;
t2=(temp[6]/10)%10;
LCD_write_char(4,0,cor[t1]);
LCD_write_char(3,0,cor[t2]);
}
}
|