📄 ds3231_yj.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 + -