⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds3231.c

📁 Atmega128 学习板的详细制作资料
💻 C
字号:
/**********************************
晶振:11.0592M
模拟I2C总线操作DS3231
2007/11/08
编写:fjh
/**********************************/
#include <iom128v.h>
#include <macros.h>
#include "lcd.c"
#define uchar unsigned char 
#define uint  unsigned int 

#define SCL_H  PORTD|=(1<<0)
#define SCL_L  PORTD&=~(1<<0)

#define SDA_H  PORTD|=(1<<1)
#define SDA_L  PORTD&=~(1<<1)

uchar year,month,date,hour,minute,second;
/******************应用程序********************/
void timer1_init(void);
uchar BCD2HEX(uchar val);
uchar B_BCD(uchar val);
void delay(uchar us);
void Start(void);
void Stop(void);
void SendByte(uchar Dat);
uchar ReceiveByte(uchar b);
void I2cByteWrite(uchar device,uint addr,uchar bytedata);
uchar I2cByteRead(uchar device,uint addr);
void get_show_time(void);
/**********************************************/
void port_init(void)
{
 PORTA = 0xff;
 DDRA  = 0xff;
 
 PORTB = 0xff;
 DDRB  = 0xff;
 
 PORTC = 0xff; 
 DDRC  = 0xff;
 
 PORTD = 0x00;
 DDRD  = 0xff;
 
 PORTE = 0xff;
 DDRE  = 0xff;
 
 PORTF = 0xff;
 DDRF  = 0xff;
 
 PORTG = 0x00;
 DDRG  = 0x00;
}

// actual value:  1.000Sec (0.0%)
void timer1_init(void)
{
 TCCR1B = 0x00; //stop
 TCNT1H = 0xD5; //setup
 TCNT1L = 0xD1;
 OCR1AH = 0x2A;
 OCR1AL = 0x2F;
 OCR1BH = 0x2A;
 OCR1BL = 0x2F;
 OCR1CH = 0x2A;
 OCR1CL = 0x2F;
 ICR1H  = 0x2A;
 ICR1L  = 0x2F;
 TCCR1A = 0x00;
 TCCR1B = 0x05; //start Timer
 TIMSK  = 0x04; //timer interrupt sources
}

#pragma interrupt_handler timer1_ovf_isr:15
void timer1_ovf_isr(void)
{
  //TIMER1 has overflowed
  TCNT1H = 0xD5; //reload counter high value
  TCNT1L = 0xD1; //reload counter low value
  PORTF=~PORTF;
  get_show_time();
}

uchar BCD2HEX(uchar val)   //BCD转换为Byte
{
    unsigned char i;
    i= val&0x0f;
    val >>= 4;
    val &= 0x0f;
    val *= 10;
    i += val;
    
    return i;
}

uchar B_BCD(uchar val)//B码转换为BCD码
{
  uchar i,j,k;
  i=val/10;
  j=val%10;
  k=j+(i<<4);
  return k;
}

void delay(uchar us)
{
   while(us--);
}
/************************START***************************/
void Start(void)
{
  SDA_H;
  delay(5);
  SCL_H;
  delay(5);
  SDA_L;
  delay(5);
} 
/********************************************************/
/************************STOP****************************/
void Stop(void)
{
  SDA_L;
  delay(5);
  SCL_H;
  delay(5);
  SDA_H;
  delay(5);
}
/********************************************************/
/***********向I2C总线发送一个字节+接收一个ACK************/
void SendByte(uchar Dat)
{
  uchar i=0;
  uchar T_Data=0;
  
  DDRD|=(1<<1);//输出
  SCL_L; 
  delay(10);
  T_Data=Dat;
  for(i=0;i<8;i++)
    { 	  
  
	  if(T_Data&0x80)
	    SDA_H;
	  else 
	    SDA_L;
	  delay(5);
      SCL_L;
	  delay(5);
	  SCL_H;
	  delay(5);
	  T_Data=T_Data<<1;
	  SCL_L;
	  delay(5);
   }
  SDA_H;//释放总线 
  delay(5); 
  SCL_L;     /*********************/
  delay(5);//接收一个ACK,不做处理
  SCL_H;     /*********************/
  delay(5);

  SCL_L;
}
/********************************************************/
/**********从I2C总线上读取一个字节+发送一个ACK***********/
uchar ReceiveByte(uchar b)
{
  uchar i;
  uchar temp;
  uchar Dat=0;
/*
  SDA_H;
  delay(5);
  SCL_L;
  delay(5);
*/
  DDRD&=~(1<<1);//输入
  for(i=0;i<8;i++)
    {
	  SCL_H;
      delay(5);
 
	  Dat=Dat<<1;
	  delay(5);
	  temp=PIND;
	  if(temp&0x02)
	    Dat|=0x01;
	  else
	    Dat|=0x00;
	 delay(5);
	 SCL_L; 
	  delay(5); 
    }
  DDRD|=(1<<1);//输出
  
  if(b)//每收一个数后发送ACK或nACK
    SDA_H;
  else
    SDA_L;
	
  delay(5);
  SCL_H;
  delay(5);
  SCL_L;
  delay(5);
  SDA_H;        //释放总线
  delay(100);
  return Dat;
}
/****************************************************/
/***********将一个字节写入DS3231指定的地址***********/
void I2cByteWrite(uchar device,uint addr,uchar bytedata)
{
  Start();
  delay(5);
  SendByte(device);
  delay(5);
  SendByte(addr);
  delay(5);
  SendByte(bytedata);
  delay(5);
  Stop();
}
/****************************************************/
/************从DS3231指定的地址读一个字节************/
uchar I2cByteRead(uchar device,uint addr)
{
  uchar Dat=0;
  
  Start();
  SendByte(device);
  delay(5);
  SendByte(addr);
  delay(5);
  Start();//Restart
  SendByte(0xd1);//读数
  delay(5);
  Dat=ReceiveByte(1);//只接收一个字节,所以发nACK
  Stop();
  return Dat;
}
/***************************************************/
/*********************读取时间**********************/
void Readtime(void)
{
  year=I2cByteRead(0xd0,0x06);  //年
  month=I2cByteRead(0xd0,0x05); //月 
  date=I2cByteRead(0xd0,0x04);  //日
  hour=I2cByteRead(0xd0,0x02);  //时
  minute=I2cByteRead(0xd0,0x01);//分
  second=I2cByteRead(0xd0,0x00);//秒
}
/***************************************************/
/****************修改时间,BCD码输入*****************/
void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec)
{
  uchar temp=0;
  
  temp=B_BCD(yea);
  I2cByteWrite(0xD0,0x06,temp);//修改年
  
  temp=B_BCD(mon);
  I2cByteWrite(0xD0,0x05,temp);//修改月
   
  temp=B_BCD(da);
  I2cByteWrite(0xD0,0x04,temp);//修改日
  
  temp=B_BCD(hou);
  I2cByteWrite(0xD0,0x02,temp);//修改时
  
  temp=B_BCD(min);
  I2cByteWrite(0xD0,0x01,temp);//修改分
  
  temp=B_BCD(sec);
  I2cByteWrite(0xD0,0x00,temp);//修改秒
}
/****************************************************/
/****************读取时间 计算 并显示****************/
void get_show_time(void)
{
 uchar temp1,temp2,a=0,b=0; 
 
 temp1=I2cByteRead(0xd0,0x06);  //年
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x81,tab[a],tab[b]);
 disp_one_word(0x82,"年");
 
 temp1=I2cByteRead(0xd0,0x05);  //月
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x83,tab[a],tab[b]);
 disp_one_word(0x84,"月"); 
 
 temp1=I2cByteRead(0xd0,0x04);  //日
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x85,tab[a],tab[b]);
 disp_one_word(0x86,"日");  
 
 temp1=I2cByteRead(0xd0,0x02);  //时 24小时制
 temp1&=0x3f;                   
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x91,tab[a],tab[b]);
 disp_one_word(0x92,"时"); 
 
 temp1=I2cByteRead(0xd0,0x01);  //分
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x93,tab[a],tab[b]);
 disp_one_word(0x94,"分");  
  
 temp1=I2cByteRead(0xd0,0x00);  //秒
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x95,tab[a],tab[b]);
 disp_one_word(0x96,"秒");  
}
/****************************************************/
/*******************MAIN函数*************************/
void main()
{
  CLI();
  port_init();
  init_lcd ();
  I2cByteWrite(0xD0,0x0e,0);
  I2cByteWrite(0xD0,0x0f,0);
  ModifyTime(7,11,10,18,10,00);//初始化时钟,2007/11/20,12/59/00
                               //小时采用24小时制
  timer1_init();
  SEI();
  lat_disp (0x00,0x00);//显示点阵
  chn_disp (SetTimeTab);
  while(1)
    {

    }  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -