新手,现在在学PCF8563,现在时间已经读出来了,但是现在想用串口发数中断的方式来调整时间。发现如下问题,分钟尾数为0到8时,可以加1。但是,分钟尾数为9时,再加1变成了A,然后再加变为B。怎么让分钟数正常加减?求解。
我移植别人的程序,也是理解不透彻。8563程序和串口中断程序如下:
u8 Display_Time[9] = {0x30,0x30,0x3a,0x30,0x30,0x3a,0x30,0x30,0x00};
// 【2】和【5】为“:”
//时间显示缓存 格式 00:00:00
u8 Display_Date[14] = {0x32,0x30,0x31,0x33,0x2f,0x31,0x30,0x2f,0x32,0x30,0x20,0x37,0x57,0x00};
//日期显示缓存 格式 2013/10/20 7W
u8 Time_Register[16];
/******************************************************************************
定义相关的变量函数
******************************************************************************/
//Time_Typedef TimeValue={0x2018,0x10,0x03,0x17,0x13,0x58,0x11}; //定义时间数据指针
Time_Typedef TimeValue={0x7e2,0x0a,0x03,0x11,0x0c,0x35,0x11}; //定义时间数据指针
u8 Time_Buffer[16]; //时间日历数据缓存
/******************************************************************************
* Function --> PCF8563某寄存器写入一个字节数据
* Param --> REG_ADD:要操作寄存器地址
* dat: 要写入的数据
* Reaturn --> none
* Brief --> none
******************************************************************************/
void PCF8563_Write_Byte(u8 REG_ADD,u8 dat)
{
IIC_Start();
if(!(IIC_Write_Byte(PCF8563_Write))) //发送写命令并检查应答位
{
IIC_Write_Byte(REG_ADD);
IIC_Write_Byte(dat); //发送数据
}
IIC_Stop();
}
/******************************************************************************
* Function --> PCF8563某寄存器读取一个字节数据
* Param --> REG_ADD:要操作寄存器地址
* Reaturn --> 读取得到的寄存器的值
* Brief --> none
******************************************************************************/
u8 PCF8563_Read_Byte(u8 REG_ADD)
{
u8 ReData;
IIC_Start();
if(!(IIC_Write_Byte(PCF8563_Write))) //发送写命令并检查应答位
{
IIC_Write_Byte(REG_ADD); //确定要操作的寄存器
IIC_Start(); //重启总线
IIC_Write_Byte(PCF8563_Read); //发送读取命令
ReData = IIC_Read_Byte(); //读取数据
IIC_Ack(1); //发送非应答信号结束数据传送
}
IIC_Stop();
return ReData;
}
/******************************************************************************
* Function --> PCF8563检测是否存在
* Param --> none
* Reaturn --> 0:正常
* 1:PCF8563错误或者损坏
* Brief --> 向定时器倒计时寄存器写入一个数值再读取出来做对比,相同正确,不同则错误
******************************************************************************/
u8 PCF8563_Check(void)
{
u8 test_value=0;
u8 Time_Count=0; //定时器倒计时数据缓存
if(PCF8563_Read_Byte(Address_Time) & 0x80) //如果打开了定时器,则先关闭
{
PCF8563_Write_Byte(Address_Time, Time_Close); //先关闭定时器
Time_Count = PCF8563_Read_Byte(Address_Time_VAL); //先保存计数值
}
PCF8563_Write_Byte(Address_Time_VAL, PCF8563_Check_Data); //写入检测值
for(test_value = 0;test_value < 250;test_value++) {} //延时一定时间再读取
test_value = PCF8563_Read_Byte(Address_Time_VAL); //再读取回来
if(Time_Count != 0) //启动了定时器功能,则恢复
{
PCF8563_Write_Byte(Address_Time_VAL, Time_Count); //恢复现场
PCF8563_Write_Byte(Address_Time, Time_Open); //启动定时器
}
if(test_value != PCF8563_Check_Data) return 1; //器件错误或者损坏
return 0; //正常
}
/******************************************************************************
* Function --> PCF8563对时间日历寄存器操作,写入数据或者读取数据
* Param --> REG_ADD:要操作寄存器起始地址
* *WBuff: 写入数据缓存
* num: 写入数据数量
* mode: 操作模式。0:写入数据操作。1:读取数据操作
* Reaturn --> none
* Brief --> 连续写入n字节或者连续读取n字节数据
******************************************************************************/
void PCF8563_Operate_Register(u8 REG_ADD,u8 *pBuff,u8 num,u8 mode)
{
u8 i;
if(mode) //读取数据
{
IIC_Start();
if(!(IIC_Write_Byte(PCF8563_Write))) //发送写命令并检查应答位
{
IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
IIC_Start(); //重启总线
IIC_Write_Byte(PCF8563_Read); //发送读取命令
for(i = 0;i < num;i++)
{
*pBuff = IIC_Read_Byte(); //读取数据
if(i == (num - 1)) IIC_Ack(1); //发送非应答信号
else IIC_Ack(0); //发送应答信号
pBuff++;
}
}
IIC_Stop();
}
else //写入数据
{
IIC_Start();
if(!(IIC_Write_Byte(PCF8563_Write))) //发送写命令并检查应答位
{
IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
for(i = 0;i < num;i++)
{
IIC_Write_Byte(*pBuff); //写入数据
pBuff++;
}
}
IIC_Stop();
}
}
/******************************************************************************
* Function --> PCF8563读取或者写入时间信息
* Param --> *pBuff:写入数据缓存
* mode:操作模式。0:写入数据操作。1:读取数据操作
* Reaturn --> none
* Brief --> 连续写入n字节或者连续读取n字节数据
******************************************************************************/
void PCF8563_ReadWrite_Time(u8 mode)
{
//定义时间缓存
if(mode) //读取时间信息
{
PCF8563_Operate_Register(Address_second,Time_Register,7,1); //从秒地址(0x02)开始读取时间日历数据
/******将数据复制到时间结构体中,方便后面程序调用******/
TimeValue.second = Time_Register[0] & Shield_secondBit; //秒数据
TimeValue.minute = Time_Register[1] & Shield_minuteBit; //分钟数据
TimeValue.hour = Time_Register[2] & Shield_hourBit; //小时数据
TimeValue.date = Time_Register[3] & Shield_dateBit; //日数据
TimeValue.week = Time_Register[4] & Shield_weekBit; //星期数据
TimeValue.month = Time_Register[5] & Shield_monthBit; //月数据
TimeValue.year = Time_Register[6] | PCF8563_YEARDATA; //年数据
}
else
{
if(TimeValue.week == 0x07) TimeValue.week = 0x00; //寄存器数值为0 ~ 6
/******从时间结构体中复制数据进来******/
Time_Register[0] = TimeValue.second | Accuracy_Clock_Yes; //秒,保证准确时间
Time_Register[1] = TimeValue.minute; //分钟
Time_Register[2] = TimeValue.hour; //小时
Time_Register[3] = TimeValue.date; //日
Time_Register[4] = TimeValue.week; //星期
Time_Register[5] = TimeValue.month | (0<<7); //月,设置年数据位20xx年
Time_Register[6] = (u8)TimeValue.year; //年
PCF8563_Operate_Register(Address_second,Time_Register,7,0); //从秒地址(0x00)开始写入时间日历数据
}
}
/******************************************************************************
* Function --> 时间日历初始化
* Param --> *TimeVAL:RTC芯片寄存器值指针
* Reaturn --> none
* Brief --> none
******************************************************************************/
void PCF8563_Time_Init(Time_Typedef *TimeVAL)
{
if(TimeVAL->week == 0x07) TimeVAL->week = 0x00; //寄存器数值为0 ~ 6
//控制/状态寄存器
Time_Buffer[0] = TimeVAL->cont1; //控制/状态寄存器1
Time_Buffer[1] = TimeVAL->cont2; //控制/状态寄存器2
//时间日历数据
Time_Buffer[2] = TimeVAL->second | Accuracy_Clock_Yes; //保证准确时间
Time_Buffer[3] = TimeVAL->minute;
Time_Buffer[4] = TimeVAL->hour;
Time_Buffer[5] = TimeVAL->date;
Time_Buffer[6] = TimeVAL->week;
Time_Buffer[7] = TimeVAL->month | Set_Year20xx; //设置为20xx年
Time_Buffer[8] = (u8)TimeVAL->year;
//闹铃报警
Time_Buffer[9] = TimeVAL->alarmmin | Alarm_minute_Close; //分钟报警
Time_Buffer[10] = TimeVAL->alarmhour | Alarm_hour_Close; //小时报警
Time_Buffer[11] = TimeVAL->alarmdate | Alarm_date_Close; //日报警
Time_Buffer[12] = TimeVAL->alarmweek | Alarm_week_Close; //星期报警
//频率输出设置;定时器设置
Time_Buffer[13] = TimeVAL->CLKcont; //频率输出控制
Time_Buffer[14] = TimeVAL->timecont; //定时器控制
Time_Buffer[15] = TimeVAL->timeconut; //定时器倒计时
PCF8563_Operate_Register(Address_control1,Time_Buffer,16,0); //从控制/状态寄存器1(0x00)开始写入16组数据
}
/******************************************************************************
* Function --> 时间日历数据处理函数
* Param --> none
* Reaturn --> none
* Brief --> 将读取到的时间日期信息转换成ASCII后保存到时间格式数组中
******************************************************************************/
void Time_Handle(void)
{
/******************************************************
读取时间日期信息
******************************************************/
PCF8563_ReadWrite_Time(1); //获取时间日历数据
/******************************************************
时间信息转换为ASCII码可视字符
******************************************************/
Display_Time[6] = (TimeValue.second >> 4) + 0x30;
Display_Time[7] = (TimeValue.second & 0x0f) + 0x30; //Second
Display_Time[3] = (TimeValue.minute >> 4) + 0x30;
Display_Time[4] = (TimeValue.minute & 0x0f) + 0x30; //Minute
Display_Time[0] = (TimeValue.hour >> 4) + 0x30;
Display_Time[1] = (TimeValue.hour & 0x0f) + 0x30; //Hour
Display_Date[8] = (TimeValue.date >> 4) + 0x30;
Display_Date[9] = (TimeValue.date & 0x0f) + 0x30; //Date
Display_Date[5] = (TimeValue.month >> 4) + 0x30;
Display_Date[6] = (TimeValue.month & 0x0f) + 0x30; //Month
Display_Date[0] = (u8)(TimeValue.year >> 12) + 0x30; //2
Display_Date[1] = (u8)((TimeValue.year & 0x0f00) >> 8) + 0x30; //0
Display_Date[2] = (TimeValue.year >> 4) + 0x30;
Display_Date[3] = (TimeValue.year & 0x0f) + 0x30; //Year
/******************************************************
星期日显示的是7,其他的就是对应的数字显示,将0转换为7
******************************************************/
if(TimeValue.week == 0x00)
{ Display_Date[11] = 0x37; } //week
else
{ Display_Date[11] = (TimeValue.week & 0x0f) + 0x30; }
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 r;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
switch(r)
{
case 1:
TimeValue.minute++;
break;
case 2:
TimeValue.minute--;
}
PCF8563_ReadWrite_Time(0);
//PCF8563_Time_Init(&TimeValue);
USART_SendData(USART1,r);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
}
USART_ClearFlag(USART1,USART_FLAG_TC);
}
主程序中的显示程序:
printf("%x年,%x月,%x日,星期%x,%x点,%x分,%x秒
",TimeValue.year,TimeValue.month,TimeValue.date,TimeValue.week,TimeValue.hour,TimeValue.minute,TimeValue.second);
写入时
second = (second/10 <<4) + second %10;
读取得数据处理
second = (second&0x0f)+(second>>4)*10;
谢谢,转换后已经可以修改了。但是为什么分钟可以加减,而时、星期、日、月、年只能减不能加?有什么地方限制住了吗?
一周热门 更多>