TA的每日心情 | 奋斗 2012-10-15 15:19 |
|---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
童生
- 积分
- 80
|
//--------------------------------------------
//功能描述:通过IIC总线测试PCF8563芯片设定时间、读取时间
//作者:SLJ
//--------------------------------------------
//头函数
#include <avr/io.h>
#define sbi(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit))
#define cbi(sfr,bit) (_SFR_BYTE(sfr)&=~_BV(bit))
//--------------------------------------------
#define DATA_OFF PORTB&=~(1<<2)
#define DATA_ON PORTB|=(1<<2)
#define LCK_OFF PORTB&=~(1<<1)
#define LCK_ON PORTB|=(1<<1)
//全局变量声明
uint8_t date_time[20];//---存放当前时间
//0 年 //1 月 //2 日
//3 时 //4 分 //5 秒
uint8_t temp_data[8];//存放中间变量
uint8_t dat[8];
uint8_t num;
//--------------------------------------------
uint8_t DSY_d[]={ //字型码(段选码)0-9,低电平有效
0xC0,0xF9,0xA4,0xB0,
0x99,0x92,0x82,0xF8,
0x80,0x90};
//uint8_t DSY_w[]={ //低电平有效
//0xfe,0xfd,0xfb,0xf7,
//0xef,0xdf,0xbf,0x7f}; //位选信号
//#define PORT_Duan PORTB //数码管段显
//#define PORT_Wei PORTA //数码管位显
void delay(int z)
{
while(z--)
{
uint8_t a;
for(a=0;a<150;a++);
}
}
/*void SEG_DSY( void )
{
// PORT_Wei = PORT_Wei ;
// PORT_Duan= 0Xff;
PORT_Duan = DSY_d[ dat[0]];
PORT_Wei=0XFE;
delay(60000);
PORT_Duan = DSY_d[ dat[1]];
PORT_Wei=0XFE;
delay(60000);
// PORT_Wei = 0Xff;
// PORT_Wei=~DSY_w[ num ] ;
// if(++num==6) num = 0 ;
}*/
//延时子程序
void delay_ms1(void)
{
uint8_t i,j,m;
for(i=1;i<2;i++)
{ for(j=1;j<2;j++)
{ for(m=1;m<2;m++)
{;}
}
}
}
void delay_1ms(uint8_t xtal)
{
uint8_t i;
for(i=1;i<(uint8_t)(xtal*143-2);i++)
{;}
}
//2 延时nms
void delay_ms(uint8_t m, uint8_t fosc)
{
uint8_t i;
i=0;
while(i<m)
{
delay_1ms(fosc);
i++;
}
}
//--------------------------------------------
//转BCD码子程序
int8_t _BCD(int8_t input)
{
uint8_t temp,result1=0;
temp=input/10;
result1|=(temp<<4);
temp=input%10;
temp&=(0x0f);
result1|=temp;
return result1;
}
//--------------------------------------------
//BCD码转
int8_t BCD_(int8_t input)
{
uint8_t temp,result1;
result1=0;
temp=(input>>4)*10;
result1=temp+(input&0x0f);
return result1;
}
//--------------------------------------------
//IIC写操作子程序;address_device为器件地址:0xa2,address_reg,data_package为写的数据
void TWI_WRITE(uint8_t address_device,uint8_t address_reg1, uint8_t data_package)
{
//TWI预分频为4分频
sbi(TWSR,TWPS0);
cbi(TWSR,TWPS1);
TWBR=0x40;//SCL频率92160HZ
begin:
TWCR=_BV(TWEN)|_BV(TWSTA)|_BV(TWINT);
while(!(TWCR&_BV(TWINT)))//等待TWINT置位,TWINT置位表示开始信号发送完毕
;
if(((TWSR&0xF8)!=0x08)&((TWSR&0xF8)!=0x10))//检查状态寄存器,如果状态字不是START或RESTART,重新发送开始信号
goto begin;
TWDR=address_device;//将器件地址写入到TWDR寄存器,TWINT位清零,启动发送地址
TWDR=address_device;
TWCR=_BV(TWEN)|_BV(TWINT);
while(!(TWCR&_BV(TWINT)))//等待TWINT置位,TWINT置位表示总线命令SLA+W已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x18)//检查TWI状态寄存器,如果状态字不是地址ACK,重新发送开始信号
goto begin;
TWDR=address_reg1;//写寄存器地址
TWDR=address_reg1;
TWCR=_BV(TWEN)|_BV(TWINT);
while(!(TWCR&_BV(TWINT)))//等待TWINT置位,TWINT置位表示总线命令SLA+W已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x28)//检查TWI状态寄存器,如果状态字不是地址ACK,重新发送开始信号
goto begin;
TWDR=data_package;//将数据载入到TWDR寄存器,TWINT位清零,启动发送地址
TWDR=data_package;
TWCR=_BV(TWINT)|_BV(TWEN);
while(!(TWCR&_BV(TWINT)))//等待TWINT置位,TWINT置位表示总线数据已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x28)//检查TWI状态寄存器,如果状态字不是数据ACK,重新发送开始信号
goto begin;
TWCR=_BV(TWINT)|_BV(TWSTO)|_BV(TWEN);//发送STOP信号
delay_ms(2,8);
delay_ms(2,8);
delay_ms(2,8);
}
//-------------------------------------------
//IIC读操作,address_device为器件地址:0xa2+1,address_reg1为寄存器地址,
uint8_t TWI_READ(uint8_t address_device,uint8_t address_reg1)
{
uint8_t result1=0;
sbi(TWSR,TWPS0);//TWI预分频为4分频
cbi(TWSR,TWPS1);
TWBR=0x02;//SCL频率92160HZ
begin:
//delay_ms(2,8);
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//发送开始信号
while(!(TWCR&(1<<TWINT)))//等待开始信号发送完毕
;
if(((TWSR&0xF8)!=0x08)&((TWSR&0xF8)!=0x10))//检查TWI状态寄存器,如果状态字不是START或RESTART,重新发送开始信号
goto begin;
TWDR=address_device;//发器件写地址,TWINT位清零,启动发送
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)))//等待TWINT置位,TWINT置位表示总线命令SLA+W已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x18)//检查TWI状态寄存器,如果状态字不是地址ACK,重新发送开始信号
goto begin;
TWDR=address_reg1;//写寄存器地址,TWINT位清零,启动发送
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)))//等待TWINT置位,TWINT置位表示总线数据已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x28)//检查TWI状态寄存器,如果状态字不是数据ACK,重新发送开始信号
goto begin;
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//发送开始信号
while(!(TWCR&(1<<TWINT)))//等待TWINT置位,TWINT置位表示开始信号发送完毕
;
if(((TWSR&0xF8)!=0x08)&((TWSR&0xF8)!=0x10))//检查TWI状态寄存器,如果状态字不是START或RESTART,重新发送开始信号
goto begin;
TWDR=address_device+1;//读器件地址写入到TWDR寄存器,TWINT位清零,启动发送
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)))//等待TWINT置位,TWINT置位表示总线命令SLA+W已发出,及收到应答信号ACK/NACK
;
if((TWSR&0xF8)!=0x40)//检查TWI状态寄存器,如果状态字不是地址ACK,重新发送开始信号
goto begin;
TWCR=(1<<TWINT)|(1<<TWEN);//发送NACK信号
while(!(TWCR&(1<<TWINT)))
;
if((TWSR&0xF8)!=0x58)
goto begin;
TWCR=(1<<TWSTO)|(1<<TWEN);//发送STOP信号
result1=TWDR;//将TWDR寄存器的数据读入
//delay_ms(2,8);
//delay_ms(2,8);
delay_ms(2,8);
return result1;
}
//--------------------------------------------
//8563操作子程序,包括写控制字和时间校准,转换成BCD码在程序中完成
void CALENDAR_WRITE(uint8_t year,uint8_t month,uint8_t date,uint8_t hour,uint8_t minute,uint8_t second)
{
uint8_t temp=0;
TWI_WRITE(0xa2,0x00,0x20);//写控制字,寄存器锁定
temp=_BCD(second)&0x7f;//写秒
TWI_WRITE(0xa2,0x02,temp);
TWI_WRITE(0xa2,0x03,_BCD(minute));//写分钟
TWI_WRITE(0xa2,0x04,_BCD(hour));//写小时
TWI_WRITE(0xa2,0x05,_BCD(date));//写日期
temp=_BCD(month)&0x7f;//写月
TWI_WRITE(0xa2,0x07,temp);
TWI_WRITE(0xa2,0x08,_BCD(year));//写年
TWI_WRITE(0xa2,0x00,0x00);//写控制字,重新启动时钟
}
//--------------------------------------------
//读8563,返回BCD码数组
void CALENDAR_READ(void)
{ uint8_t temp;
TWI_WRITE(0xa2,0x00,0x20);//写控制字,时钟停止运行
//----------
temp=TWI_READ(0xa2,0x08);//读年
temp=BCD_(temp);
date_time[0]=temp;
//----------
temp=TWI_READ(0xa2,0x07);//读月
temp&=0x1F;//将5、6、7屏蔽
temp=BCD_(temp);
date_time[1]=temp;
//----------
temp=TWI_READ(0xa2,0x05);//读日
temp&=0x3F;//将6、7屏蔽
temp=BCD_(temp);
date_time[2]=temp;
//----------
temp=TWI_READ(0xa2,0x04);//读时
temp&=0x3F;//将6、7屏蔽
temp=BCD_(temp);
date_time[3]=temp;
//----------
temp=TWI_READ(0xa2,0x03);//读分
temp&=0x7F;//将7屏蔽
temp=BCD_(temp);
date_time[4]=temp;
//----------
temp=TWI_READ(0xa2,0x02);//读秒
temp&=0x7F;//将7屏蔽
temp=BCD_(temp);
date_time[5]=temp;
//----------
TWI_WRITE(0xa2,0x00,0x00);//写控制字,重新启动时钟
}
//--------------------------------------------
void segvalue(void)
{
dat[0]=date_time[5]%10 ;//秒
dat[1]=date_time[5]/10 ; //十秒
dat[2]=date_time[4]%10; //分
dat[3]=date_time[4]/10 ; //十分
dat[4]=date_time[3]%10; //时
dat[5]=date_time[3]/10 ; //十时
dat[6]=date_time[0]%10; //时
dat[7]=date_time[0]/10 ; //十时
}
void write_164(uint8_t data_164)//写一位数据164
{
uint8_t i;
for(i=0;i<8;i++)
{
LCK_OFF;
LCK_ON;
if(data_164&0x01)
{
DATA_ON;
}
else DATA_OFF;
data_164=data_164>>1;
LCK_ON;
}
}
//主程序
int main(void)
{
DDRA=0XFF;
DDRB=0XFF;
DDRC=0XFF;
//CALENDAR_WRITE(12,9,13,10,34,0); //时间初始化2009年8月6日14时36分
while(1)
{
CALENDAR_READ();
segvalue();
// SEG_DSY();
/*LCK_OFF;
LCK_ON;
DATA_ON;
LCK_OFF;
LCK_ON;
DATA_OFF;
LCK_OFF;
LCK_ON;
DATA_OFF;
LCK_OFF;
LCK_ON;
DATA_ON;
LCK_OFF;
LCK_ON;
DATA_ON;
LCK_OFF;
LCK_ON;
DATA_ON;
LCK_OFF;
LCK_ON;
DATA_ON;
LCK_OFF;
LCK_ON;
DATA_ON;*/
write_164(DSY_d[ dat[7]]);
write_164(DSY_d[ dat[6]]);
write_164(DSY_d[ dat[5]]);
write_164(DSY_d[ dat[4]]);
write_164(DSY_d[ dat[3]]);
write_164(DSY_d[ dat[2]]);
write_164(DSY_d[ dat[1]]);
write_164(DSY_d[ dat[0]]);
delay(6000);
}
}
|
|