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

📄 ds3231_yj.c

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

#define twi_stop() TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)   //发送stop
#define twi_start() TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)  //发送start
#define check_TWINT()  while (!(TWCR & (1<<TWINT)))
uchar con[8],con1[8];
uchar err;
uchar TwiStatus;  //TWI阶段指示,全局的  extern
uchar year=0,month=0,date=0,hour=0,minute=0,second=0;
uchar keyin=0;
uchar SetTimeStatu=0;
volatile uchar SetTime_flag=0;

void port_init(void)
{
 PORTA = 0xff;
 DDRA  = 0xff;
 
 PORTB = 0xff;
 DDRB  = 0xff;
 
 PORTC = 0xff; //m103 output only
 DDRC  = 0xff;
 
 PORTD = 0xff;
 DDRD  = 0xff;
 
 PORTE = 0x0f;//键盘口
 DDRE  = 0xf0;
 
 PORTF = 0x0f;
 DDRF  = 0xf0;
 
 PORTG = 0x00;
 DDRG  = 0x00;
}
/***********定时1S**************/
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
}

void Delay(uint t)
{
	uint i; 
	for(;t>0;t--)
		for(i=0;i<1106;i++)
			;						 
}

uchar BCD2HEX(uchar val)   //BCD转换为Byte
{
    uchar 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;
}

uchar bbcd(uchar i)//单字节B码转bcd码子程序
{ uchar a,b;
   a=i/10;
   b=i%10;
   return(a*16+b);
}
	
void ERROR(void)
{
err=1;
twi_stop();
}

//**********************读取指定slave的地址内的数据************
//i2c_address:从机地址。对于x1226,CCR为0xde,,E2为0xae。
uchar I2cByteRead(uchar device,uint addr)//从slave接收1字节数据
{
	uchar temp; //读取数值缓存

	twi_start();  //发开始信号
	check_TWINT();  //等待结束
	con[0]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x08) ERROR();
	
	TWDR=device+0;   //发送SLA+W
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();  //等待结束
	con[1]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x18) ERROR();

	TWDR = addr;   //发送地址
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();
	con[3]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x28) ERROR();
	
	twi_start();  //发开始信号
	check_TWINT();  //等待结束
	con[4]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x10) ERROR();
	
	TWDR =device+1;   //发送SLA+R
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();
	con[5]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x40) ERROR();
	
	TWCR=0x84; //接收8位数据,发送nACK 
	check_TWINT(); 
	con[6]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x58) ERROR();
	temp=TWDR;
	
	twi_stop(); //发送STOP 信号 		
	Delay(5);
return (temp);						
}
//*************将数据写入指定slave的地址内***********************
void I2cByteWrite(uchar device,uint addr,uchar bytedata)
{
	twi_start();  //发开始信号
	check_TWINT();  //等待结束
	con[0]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x08) ERROR();
	
	TWDR=device+0;   //发送SLA+W
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();  //等待结束
	con[1]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x18) ERROR();

	TWDR = addr;
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();
	con[3]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x28) ERROR();
	
	TWDR = bytedata;
	TWCR = (1<<TWINT) |(1<<TWEN);
	check_TWINT();
	con[4]=TWSR & 0xF8;
	if((TWSR & 0xF8) != 0x28) ERROR();
	
	twi_stop(); //发送STOP 信号 			
	Delay(5);		
}
/********************************************/
void ReadRTC(void)                                //读时钟
{
  year = I2cByteRead(0xD0,0x06);
  year =BCD2HEX(year);
  month = I2cByteRead(0xD0,0x05);
  month =BCD2HEX(month);
  date = I2cByteRead(0xD0,0x04);
  date =BCD2HEX(date);
  hour= I2cByteRead(0xD0,0x02); //24小时 
  hour =BCD2HEX(hour);
  minute = I2cByteRead(0xD0,0x01);
  minute =BCD2HEX(minute);
  second = I2cByteRead(0xd0,0x00);
  second =BCD2HEX(second);
}
/****************修改时间,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 (0x91,tab[a],tab[b]);
 disp_one_word(0x92,"年");
 
 temp1=I2cByteRead(0xd0,0x05);  //月
 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,0x04);  //日
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x95,tab[a],tab[b]);
 disp_one_word(0x96,"日");  
 
 temp1=I2cByteRead(0xd0,0x02);  //时 24小时制
 temp1&=0x3f;                   
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x89,tab[a],tab[b]);
 disp_one_word(0x8a,"时"); 
 
 temp1=I2cByteRead(0xd0,0x01);  //分
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x8b,tab[a],tab[b]);
 disp_one_word(0x8c,"分");  
  
 temp1=I2cByteRead(0xd0,0x00);  //秒
 temp2=BCD2HEX(temp1);
 a=temp2/10;
 b=temp2-a*10;
 disp_two_char (0x8d,tab[a],tab[b]);
 disp_one_word(0x8e,"秒");  
}
/****************************************************/

void SetTimeShow()
{
  chn_disp (SetTimeTab);
  disp_two_char (0x91,tab[year/10],tab[year%10]);
  disp_one_word(0x92,"年");
  
  disp_two_char (0x93,tab[month/10],tab[month%10]);
  disp_one_word(0x94,"月");
  
  disp_two_char (0x95,tab[date/10],tab[date%10]);
  disp_one_word(0x96,"日");
  
  disp_two_char (0x89,tab[hour/10],tab[hour%10]);
  disp_one_word(0x8a,"时");
  
  disp_two_char (0x8b,tab[minute/10],tab[minute%10]);
  disp_one_word(0x8c,"分");
  
  disp_two_char (0x8d,tab[second/10],tab[second%10]);
  disp_one_word(0x8e,"秒");
}

void SetTime()
{
  uchar key=0;
  
  SetTime_flag=0;
  CLI();//关中断
  ReadRTC();
  SetTimeShow();
  con_disp (0xff,0xff,0x91,0x90,1,16);//反白显示
  Delay(1000);
  do
    {
	  keyin=getkey();

      if(keyin==13)//假如是确认键按下,切换设置值
		{
		  Delay(270);
		  if(keyin==13)
		  {
		    SetTimeStatu++;
		    if(SetTimeStatu>4)
		    SetTimeStatu=0;
			
			switch(SetTimeStatu)
			  {
			    case 0:con_disp (0xff,0xff,0x91,0x90,1,16);
				       con_disp (0x00,0x00,0x93,0x90,1,16);
					   con_disp (0x00,0x00,0x95,0x90,1,16);
					   con_disp (0x00,0x00,0x89,0x80,1,16);
					   con_disp (0x00,0x00,0x8b,0x80,1,16);break;
					   
				case 1:con_disp (0x00,0x00,0x91,0x90,1,16);
				       con_disp (0xff,0xff,0x93,0x90,1,16);
					   con_disp (0x00,0x00,0x95,0x90,1,16);
					   con_disp (0x00,0x00,0x89,0x80,1,16);
					   con_disp (0x00,0x00,0x8b,0x80,1,16);break;
					   
				case 2:con_disp (0x00,0x00,0x91,0x90,1,16);
				       con_disp (0x00,0x00,0x93,0x90,1,16);
					   con_disp (0xff,0xff,0x95,0x90,1,16);
					   con_disp (0x00,0x00,0x89,0x80,1,16);
					   con_disp (0x00,0x00,0x8b,0x80,1,16);break;
					   
				case 3:con_disp (0x00,0x00,0x91,0x90,1,16);
				       con_disp (0x00,0x00,0x93,0x90,1,16);
					   con_disp (0x00,0x00,0x95,0x90,1,16);
					   con_disp (0xff,0xff,0x89,0x80,1,16);
					   con_disp (0x00,0x00,0x8b,0x80,1,16);break;
					   
				case 4:con_disp (0x00,0x00,0x91,0x90,1,16);
				       con_disp (0x00,0x00,0x93,0x90,1,16);
					   con_disp (0x00,0x00,0x95,0x90,1,16);
					   con_disp (0x00,0x00,0x89,0x80,1,16);
					   con_disp (0xff,0xff,0x8b,0x80,1,16);break;
				default:break;
			  }
		  }
        } 
	  else if(keyin==15)
	    {  
		 Delay(270);
		 if(keyin==15)
		  {
		   switch(SetTimeStatu)
		    {
			  case 0:year++;  if(year>99)   year=0;break;
			  case 1:month++; if(month>12)  month=1;break;
			  case 2:date++;   if(date>31)    date=1;break;
			  case 3:hour++;  if(hour>23)   hour=0;break;
			  case 4:minute++;if(minute>59) minute=0;break;
			  default:break; 
			}
		   SetTimeShow();
		  }
		}
	  else if(keyin==11)
	    {
		 Delay(270);
		 if(keyin==11)
		  {
	       switch(SetTimeStatu)
	        {
			  case 0:year--;  if(year<1) year=99;break;
			  case 1:month--; if(month<1) month=12;break;
			  case 2:date--;   if(date<1) date=31;break;
			  case 3:hour--;  if(hour<1) hour=23;break;
			  case 4:minute--;if(minute<1) minute=59;break;
			  default:break;
		 	} 
		   SetTimeShow();
		  }
		}
	  else
	    ;
		
	} while(keyin!=9);//判断返回键是否按下
	
	ModifyTime(year,month,date,hour,minute,second);
	SEI();
	clrram ();
	get_show_time();
	//chn_disp (tab2);
}

void main()
{ 
  uchar a=0,b=0;
  CLI();
  port_init();
  init_lcd ();
  timer1_init();
  I2cByteWrite(0xD0,0x0e,0x00);
  I2cByteWrite(0xD0,0x0f,0x00);
  ModifyTime(07,11,10,18,11,00);
  lat_disp (0x00,0x00);
  chn_disp (tab2);
  SEI();
  while(1)
  {
	if (SetTime_flag>=3)
	  SetTime();
  }
}

#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
  get_show_time();
  
  keyin=getkey();
  if((keyin!=13)&&(SetTime_flag>0))
    SetTime_flag=0;//备注:假如SetTime_flag<3就松开则应将SetTime_flag清零
  if(keyin==13)//确认键
    {  
	  SetTime_flag++;
	}
}

⌨️ 快捷键说明

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