国庆过的差不多,今天发个基于LOOK的RTC程序,其实也没什么东西,就是写了个RTC类,并能在1602上显示年月日时分秒,能通过串口发送时分秒(每秒发一次),还能通过串口来修改RTC的时间。如果没有1602也能通过串口看到RTC的效果,就是和1602比少显示了年月日。
在写程序的过程中倒也发现了几个问题,并解决了。在调试RTC时发现,如果我使用RTC的节拍中断,当我串口发一串数据的时候,就不能正确处理,RTC设置也就无法使用,还nulink调试就会不怎么好使,不是进不到中断,就是经常进到中断,到后来,我干脆把中断给去掉了,免得搞得烦,可能像RTC的节拍中断时间太短,又频繁,肯定是不怎么好处理的。如果不用串口设置RTC的话,用节拍中断也是可以的,还有闹钟我还没弄,反正寄存器设置都差不多,设置下TAR和CAR,开中断,时间到就产生中断。
现在我就是直接在任务里读取时间值,下面是我更新显示的程序,在RTC类中记录了上次的时间,如果读的时间和上次不同则刷新显示,本来想全部嵌套的,由于嵌套太深就把其分为2部分判断,因为只有秒先变才可能分会变,分变了时才可能变,根据这样嵌套就不用全部刷新了,只要将变的值刷新了就好。
void rtc_c::Dis_Updata() //更新时间
{
uint32_t u32timebuf=0;
char time_array[10]={0};
#ifdef _LCD1602_
int8_t x=10,y=1;
#endif
u32timebuf=RTCs.TLR.Regs;//时分秒
if((u32timebuf&0x0f)!=last_second1) //time updata
{
last_second1=u32timebuf&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_second1+0x30));
#endif
if(((u32timebuf>>4)&0x0f)!=last_second10) //sec
{
last_second10=(u32timebuf>>4)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_second10+0x30));
lcd1.Lcd_WByte(x--,y,':');
#endif
if(((u32timebuf>>8)&0x0f)!=last_mintue1) //mintue
{
last_mintue1=(u32timebuf>>8)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_mintue1+0x30));
#endif
if(((u32timebuf>>12)&0x0f)!=last_mintue10)
{
last_mintue10=(u32timebuf>>12)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_mintue10+0x30));
lcd1.Lcd_WByte(x--,y,':');
#endif
if(((u32timebuf>>16)&0x0f)!=last_hour1) //hour
{
last_hour1=(u32timebuf>>16)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_hour1+0x30));
#endif
if((u32timebuf>>20)!=last_hour10)
{
last_hour10=u32timebuf>>20;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_hour10+0x30));
#endif
}
}
}
}
}
//当时间改变时通过串口查看
time_array[0]=last_hour10+0x30;
time_array[1]=last_hour1+0x30;
time_array[2]=':';
time_array[3]=last_mintue10+0x30;
time_array[4]=last_mintue1+0x30;
time_array[5]=':';
time_array[6]=last_second10+0x30;
time_array[7]=last_second1+0x30;
time_array[8]='\0';
uart0.Wstr(time_array);
uart0.Wstr(" ");
}
u32timebuf=RTCs.CLR.Regs;//年月日
x=12;y=0;
if((u32timebuf&0x0f)!=last_day1) //time updata
{
last_day1=u32timebuf&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_day1+0x30));
#endif
if(((u32timebuf>>4)&0x0f)!=last_day10) //day
{
last_day10=(u32timebuf>>4)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_day10+0x30));
lcd1.Lcd_WByte(x--,y,' ');
#endif
if(((u32timebuf>>8)&0x0f)!=last_month1) //month
{
last_month1=(u32timebuf>>8)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_month1+0x30));
#endif
if(((u32timebuf>>12)&0x0f)!=last_month10)
{
last_month10=(u32timebuf>>12)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_month10+0x30));
lcd1.Lcd_WByte(x--,y,':');
#endif
if(((u32timebuf>>16)&0x0f)!=last_year1) //year
{
last_year1=(u32timebuf>>16)&0x0f;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_year1+0x30));
#endif
if((u32timebuf>>20)!=last_year10)
{
last_year10=u32timebuf>>20;
#ifdef _LCD1602_
lcd1.Lcd_WByte(x--,y,(last_year10+0x30));
lcd1.Lcd_WByte(x--,y,'0');
lcd1.Lcd_WByte(x--,y,'2');
#endif
}
}
}
}
}
}
}
下面把主要的任务函数和RTC类发上来
/******************************************/
//声明对象
///////////////////////////////////////////
#ifdef _LCD1602_
lcd1602_c lcd1;
#endif
rtc_c rtc1(0x11,0x10,0x05,0x03,0x12,0x51,0x00);//RTC初始化时间
uint8_t cnt=0;
uart0_int_c uart0; //串口
#ifdef LOOK_SCHEDULING_PRIORITY
instantiate::task<task1_main_t, LOOK_STACK_SIZE> task1_main(0);
instantiate::task<task2_uart0_c,LOOK_STACK_SIZE> task2_uart0(1);
#else
instantiate::task<task1_main_t, LOOK_STACK_SIZE> task1_main;
instantiate::task<task2_uart0_c,LOOK_STACK_SIZE> task2_uart0;
#endif
/*************************************
//task1任务类的任务函数
**************************************/
void task1_main_t::routine()
{
#ifdef _LCD1602_ //初始化1602显示
rtc1.Dis_Time();
#endif
// TODO: 在此编写 task1_main_t 例程的内容
while (true) {
rtc1.Dis_Updata(); //更新RTC时间
cnt=0;
scheduler.yield();
// TODO: 在此编写 task1_main_t 例程的内容
}
}
/***************************************
//
***************************************/
void task2_uart0_c::routine()
{
uint32_t rev_timebuf[7]={0};
uart0.Uart0RxEnableInt();//接收中断使能
while(true){
rev_timebuf[cnt++]=task2_megs.get();
if(cnt==7)
{
rtc1.Rtc_Updata(rev_timebuf[0],rev_timebuf[1],rev_timebuf[2],rev_timebuf[3],\
rev_timebuf[4],rev_timebuf[5],rev_timebuf[6]); //更新寄存器时间
rtc1.Dis_Time();
cnt=0;
}
}
}
RTC.H
/*****************************************
//
//
******************************************/
#ifndef _rtc_h_
#define _rtc_h_
/*---------------------------------------------------------------------------------------------------------*/
/* 12-Hour / 24-Hour */
/*---------------------------------------------------------------------------------------------------------*/
#define DRVRTC_CLOCK_12 0
#define DRVRTC_CLOCK_24 1
class rtc_c: public interrupt_t {
public:
rtc_c(uint32_t year =1,uint32_t month =1,uint32_t day =1,uint32_t week =0,\
uint32_t hour=0,uint32_t mintue =0,uint32_t second =0,uint8_t ClockDisplay =1);
void Rtc_Updata(uint32_t year,uint32_t month,uint32_t day,uint32_t week,\
uint32_t hour,uint32_t mintue ,uint32_t second );//更新寄存器时间
#ifdef _LCD1602_
void Dis_Time(void);
void Dis_Updata();
#endif
protected:
bool isr(int vector);
void dsr(int vector,uintptr_t count);
private:
uint32_t Rtc_Write_Enable();
int8_t last_year10,last_year1;
int8_t last_month10,last_month1;
int8_t last_day10,last_day1;
int8_t last_hour10,last_hour1;
int8_t last_mintue10,last_mintue1;
int8_t last_second10,last_second1;
int8_t last_week;
};
#endif
RTC.CPP
/*****************************************
//
//
******************************************/
#include <NUC1xx.h>
#include"NUC1xxM051Seriescfg.h"
#include"main.h"
#include"rtc.h"
/********************************************************************************
//RTC的构造函数
//参数:年、月、日、星期、时、分、秒、12或24显示
// 要确保年月日时分秒为BCD码
********************************************************************************/
rtc_c::rtc_c(uint32_t year,uint32_t month,uint32_t day,uint32_t week,\
uint32_t hour,uint32_t mintue,uint32_t second,uint8_t ClockDisplay)
{
uint32_t write_enable=0,timer_buf=0;;
RTCs.INIR.Regs=0xa5eb1357; //唤醒RTC
for(uint8_t i=0;i<200;i++)
{
if(RTCs.INIR.Bits.Bit0==1) //判断是否正常运行
{
break;
}
}
write_enable=Rtc_Write_Enable();//15MS之后自动关闭
if(write_enable)//判断是否写打开
{
RTCs.TSSR.Bits.HR24= ClockDisplay;//
//写时分秒
Rtc_Write_Enable();
timer_buf=(hour<<16)|(mintue<<8)|(second);
RTCs.TLR.Regs=timer_buf;
//写年月日
Rtc_Write_Enable();
timer_buf=(year<<16)|(month<<8)|(day);
RTCs.CLR.Regs=timer_buf;
//写星期
Rtc_Write_Enable();
RTCs.DWR.Bits.DWR=week;
// RTCs.TTR.Bits.TTR=0;//1s产生中断
// RTCs.RIER.Bits.TIER=1;//使能节拍中断
attach(RTC_IRQn);
vector_t::enable(RTC_IRQn);
}
//将时间更新后,存起来,用来刷新判断用
last_year10=year>>4;
last_year1=year&0x0f;
last_month10=month>>4;
last_month1=month&0x0f;
last_day10=day>>4;
last_day1=day&0x0f;
last_hour10=hour>>4;
last_hour1=hour&0x0f;
last_mintue10=mintue>>4;
last_mintue1=mintue&0x0f;
last_second10=second>>4;
last_second1=second&0x0f;
last_week=week;
}
void rtc_c::Rtc_Updata(uint32_t year,uint32_t month,uint32_t day,uint32_t week,\
uint32_t hour,uint32_t mintue ,uint32_t second )
{
uint32_t timer_buf=0;
//写时分秒
Rtc_Write_Enable();
timer_buf=(hour<<16)|(mintue<<8)|(second);
RTCs.TLR.Regs=timer_buf;
//写年月日
Rtc_Write_Enable();
timer_buf=(year<<16)|(month<<8)|(day);
RTCs.CLR.Regs=timer_buf;
//写星期
Rtc_Write_Enable();
RTCs.DWR.Bits.DWR=week;
//将时间更新后,存起来,用来刷新判断用
last_year10=year>>4;
last_year1=year&0x0f;
last_month10=month>>4;
last_month1=month&0x0f;
last_day10=day>>4;
last_day1=day&0x0f;
last_hour10=hour>>4;
last_hour1=hour&0x0f;
last_mintue10=mintue>>4;
last_mintue1=mintue&0x0f;
last_second10=second>>4;
last_second1=second&0x0f;
last_week=week;
}
//使能RTC写寄存器
uint32_t rtc_c::Rtc_Write_Enable()
{
uint8_t i=0;
RTCs.AER.Bits.AER=0xA965;
for(i=0;i<100;i++)
{
if(RTCs.AER.Bits.ENF==1)
{
break;
}
RTCs.AER.Bits.AER=0xA965;
}
if(i==100)
{
return 0;
}
return 1;
}#ifdef _LCD1602_void rtc_c::Dis_Time(void){ int8_t x=10,y=1; lcd1.Lcd_WByte(x--,y,(last_second1+0x30)); lcd1.Lcd_WByte(x--,y,(last_second10+0x30)); lcd1.Lcd_WByte(x--,y,':'); lcd1.Lcd_WByte(x--,y,(last_mintue1+0x30)); lcd1.Lcd_WByte(x--,y,(last_mintue10+0x30)); lcd1.Lcd_WByte(x--,y,':'); lcd1.Lcd_WByte(x--,y,(last_hour1+0x30)); lcd1.Lcd_WByte(x--,y,(last_hour10+0x30));
x=12;y=0; lcd1.Lcd_WByte(x--,y,(last_day1+0x30)); lcd1.Lcd_WByte(x--,y,(last_day10+0x30)); lcd1.Lcd_WByte(x--,y,' '); lcd1.Lcd_WByte(x--,y,(last_month1+0x30)); lcd1.Lcd_WByte(x--,y,(last_month10+0x30)); lcd1.Lcd_WByte(x--,y,' '); lcd1.Lcd_WByte(x--,y,(last_year1+0x30)); lcd1.Lcd_WByte(x--,y,(last_year10+0x30)); lcd1.Lcd_WByte(x--,y,'0'); lcd1.Lcd_WByte(x--,y,'2');
}
void rtc_c::Dis_Updata() //更新时间{ uint32_t u32timebuf=0; char time_array[10]={0};
#ifdef _LCD1602_ int8_t x=10,y=1; #endif
u32timebuf=RTCs.TLR.Regs;//时分秒 if((u32timebuf&0x0f)!=last_second1) //time updata { last_second1=u32timebuf&0x0f; #ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_second1+0x30)); #endif if(((u32timebuf>>4)&0x0f)!=last_second10) //sec { last_second10=(u32timebuf>>4)&0x0f; #ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_second10+0x30)); lcd1.Lcd_WByte(x--,y,':'); #endif if(((u32timebuf>>8)&0x0f)!=last_mintue1) //mintue { last_mintue1=(u32timebuf>>8)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_mintue1+0x30)); #endif
if(((u32timebuf>>12)&0x0f)!=last_mintue10) { last_mintue10=(u32timebuf>>12)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_mintue10+0x30)); lcd1.Lcd_WByte(x--,y,':'); #endif
if(((u32timebuf>>16)&0x0f)!=last_hour1) //hour { last_hour1=(u32timebuf>>16)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_hour1+0x30)); #endif
if((u32timebuf>>20)!=last_hour10) { last_hour10=u32timebuf>>20;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_hour10+0x30)); #endif } } } } } //当时间改变时通过串口查看 time_array[0]=last_hour10+0x30; time_array[1]=last_hour1+0x30; time_array[2]=':'; time_array[3]=last_mintue10+0x30; time_array[4]=last_mintue1+0x30; time_array[5]=':'; time_array[6]=last_second10+0x30; time_array[7]=last_second1+0x30; time_array[8]='\0'; uart0.Wstr(time_array); uart0.Wstr(" "); } u32timebuf=RTCs.CLR.Regs;//年月日 x=12;y=0; if((u32timebuf&0x0f)!=last_day1) //time updata { last_day1=u32timebuf&0x0f; #ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_day1+0x30)); #endif if(((u32timebuf>>4)&0x0f)!=last_day10) //day { last_day10=(u32timebuf>>4)&0x0f; #ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_day10+0x30)); lcd1.Lcd_WByte(x--,y,' '); #endif if(((u32timebuf>>8)&0x0f)!=last_month1) //month { last_month1=(u32timebuf>>8)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_month1+0x30)); #endif
if(((u32timebuf>>12)&0x0f)!=last_month10) { last_month10=(u32timebuf>>12)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_month10+0x30)); lcd1.Lcd_WByte(x--,y,':'); #endif
if(((u32timebuf>>16)&0x0f)!=last_year1) //year { last_year1=(u32timebuf>>16)&0x0f;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_year1+0x30)); #endif
if((u32timebuf>>20)!=last_year10) { last_year10=u32timebuf>>20;
#ifdef _LCD1602_ lcd1.Lcd_WByte(x--,y,(last_year10+0x30)); lcd1.Lcd_WByte(x--,y,'0'); lcd1.Lcd_WByte(x--,y,'2'); #endif } } } } } }}#endif
好了,串口发送命令没什么格式只要按照BCD码并根据【年/月/日/星期/时/分/秒】的顺序发送7个字节数据,中间不能有0,要想有零只能用偏移方式,像我这串:11 10 05 03 17 20 12(HEX格式)代表2011年10月05号 星期三 17点20分12秒
希望大家一起交流,还有点问题想问老师,mmbox邮箱是不是只能通过get来一条条读消息,能不能实现清空邮箱,不然数据格式出现错误那么以后发的也就会出现错误,只能复位,本来任务中想连续读取消息的,不过感觉用for怪怪的就用来现在这个,用一个计数变量来计数,反正这次程序写的有点怪:dizzy:,不过功能倒是能瞎玩玩了 |