OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 14616|回复: 1

我的AVR资料[程序篇] AVR驱动1602液晶+DS18B20+DS1302(源码6)

[复制链接]

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2010-12-21 01:04:42 | 显示全部楼层 |阅读模式

      这个实验,在上一个的基础上,增加了对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]);    
     }
}

我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-2-2
在线时间
0 小时
发表于 2012-11-1 20:47:30 | 显示全部楼层
好长啊,我看看1302的时序。现在时钟启动不了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-3-1 00:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表