STM32实现万年历

 2 E币 
成为会员,免费下载资料
文件大小:10.87 MB 上传者:495005638 时间:2013-08-26 11:51:16 下载量:8
实现的功能:
1、日历功能。
2、数字和模拟时钟功能。

要点分析:
1、STM32自带了RTC时钟计数器,从0开始计数到232。每一个计数代表秒计数,每六十个计数代表分计数,以此类推。24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。Count%86400得到时分秒。
2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。
3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。指针运动算法和屏幕重绘方法是本程序主要难点所在。(以下参照百度文库之模拟时钟)
不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。计算指针端点(x, y)的公式如下:
x =圆心x坐标 + 指针长度 * cos (指针方向角)
y =圆心y坐标 + 指针长度 * sin (指针方向角)
注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。
由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。
另外,秒表为RTC一秒钟定时计数。
程序分析:
uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。
void  App_UCGUI_TaskCreate (void)
{
    CPU_INT08U  os_err;
        os_err = os_err;
        Clock_SEM=OSSemCreate(1);                         //建立秒更新中断的信号量
         //硬件平台初始化
           BSP_Init();                                             
        //主处理任务---------------------------------------------------------   
        os_err =    OSTaskCreateExt(AppTaskUserIF,
                                                                (void *)0,
                                                                (OS_STK *)&AppTaskUserIFStk[APP_TASK_USER_IF_STK_SIZE-1],
                                                                APP_TASK_USER_IF_PRIO,
                                                                APP_TASK_USER_IF_PRIO,
                                                                (OS_STK *)&AppTaskUserIFStk[0],
                                                                APP_TASK_USER_IF_STK_SIZE,
                                                                (void *)0,
                                                                OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);        

   
     //触摸屏任务---------------------------------------------------------                 
           os_err = OSTaskCreateExt(AppTaskKbd,
                                                         (void *)0,
                                                         (OS_STK *)&AppTaskKbdStk[APP_TASK_KBD_STK_SIZE-1],
                                                         APP_TASK_KBD_PRIO,
                                                         APP_TASK_KBD_PRIO,
                                                         (OS_STK *)&AppTaskKbdStk[0],
                                                         APP_TASK_KBD_STK_SIZE,
                                                         (void *)0,
                                                         OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
        
         //秒更新任务
   os_err = OSTaskCreateExt(Clock_Updata,
                                                        (void *)0,
                                                        (OS_STK *)&Clock_Updata_Stk[Clock_Updata_STK_SIZE-1],
                                                        Clock_Updata_PRIO,
                                                        Clock_Updata_PRIO,
                                                        (OS_STK *)&Clock_Updata_Stk[0],
                                                        Clock_Updata_STK_SIZE,
                                                        (void *)0,
                                                        OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);               
}        
万年历中的时间用的是STM32自带的RTC实时时钟。
1、主处理任务:界面背景初始化,并根据当前时间,画出图1的数据。
static  void  AppTaskUserIF (void *p_arg)
{
        (void)p_arg;
        INT8U err;
        //界面初始化
          GUI_Init();                                                        //ucgui 初始化
        _ExecCalibration();                                  /* 触摸屏校准   */
        GUI_SetBkColor(GUI_WHITE);                //设置背景色
        GUI_SetColor(GUI_GRAY);             //设置前景色
            GUI_Clear();                                                //清屏
           Lcd_show_bmp(0, 0,"/RTC.bmp");                //显示万年历背景
        GUI_SetFont(&GUI_FontHZ_SimSun_16);
        GUI_DispStringAt("一",15,47);       //显示星期一
        GUI_DispStringAt("二",44,47);                //显示星期二
        GUI_DispStringAt("三",73,47);                //显示星期三
        GUI_DispStringAt("四",102,47);                //显示星期四
        GUI_DispStringAt("五",131,47);                //显示星期五
        GUI_SetColor(GUI_RED);                                //用红字显示周末
        GUI_DispStringAt("六",160,47);                //显示星期六
        GUI_DispStringAt("日",189,47);                //显示星期日
        

to_tm(RTC_GetCounter(), &s_time);  //根据RTC时钟得到万年历时间的初值,注意,这个值是根据用户查询万年历变化
        GUI_SetFont(&GUI_Font16_1 );                //设置英文字体
        GUI_DispDecAt(s_time.tm_year,4,13,4);//显示万年历的年份
        GUI_SetFont(&GUI_FontHZ_SimSun_16);  //设置中文字体
        GUI_DispString("年");                                //显示年
        GUI_SetFont(&GUI_Font16_1 );                //设置英文字体
        GUI_DispDec(s_time.tm_mon,2);                //显示万年历的月份
        GUI_SetFont(&GUI_FontHZ_SimSun_16);        //设置中文字体
        GUI_DispString("月");                                //显示月
        GUI_SetFont(&GUI_Font16_1 );                //设置英文字体
        GUI_DispDec(s_time.tm_mday,2);                //显示万年历的日子
        GUI_SetFont(&GUI_FontHZ_SimSun_16);//设置中文字体
        GUI_DispString("日");                                //显示日
        //画模拟时钟界面
        u16 index,x,y;
        GUI_SetPenSize(1);
        GUI_SetColor(GUI_RED);
        GUI_DrawCircle(264,170, 45);                //画时钟最外层的圆,
    for( index = 0; index < 60; index++ )//画时钟的刻度
    {
          x = -(40* cos(( index * 6 ) * DEG2RAD)) + 264;
          y = -(40* sin(( index * 6 ) * DEG2RAD)) + 170;
          if( index % 5 == 0 )
          {                                                                                                                                         
             GUI_SetPenSize(4);                                //指示为小时的刻度用粗点画
          }
          else
          {
             GUI_SetPenSize(2);                                //其它刻度用西点画
          }
          GUI_DrawPoint( x, y );
    }
         while(1)
        {
           RTC_Show(RTC_GetCounter());                //主任务执行程序,接下来分析
           OSTimeDlyHMSM(0,0,0,10);                  
        }                        
}
//主任务执行程序
void RTC_Show(uint32_t TimeVar)
{
           u8 str[15]; // 字符串暂存
           u8 i,k;
           static flag=0;
           
              
  #if (GUI_SUPPORT_CURSOR|GUI_SUPPORT_TOUCH)
    GUI_CURSOR_Show();                                                //鼠标显示
  #endif
           WM_SetCreateFlags(WM_CF_MEMDEV);  /* Automatically use memory devices on all windows */   
  if(flag==0)                //初始化按键,只执行一次。
  {
//建立按键F1-F5   
_ahButton[0] =BUTTON_Create(5, 0, 32,13, GUI_KEY_F1 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
_ahButton[1]=BUTTON_Create(5, 29, 32,13, GUI_KEY_F2 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
_ahButton[2]=BUTTON_Create(53, 0, 16,13, GUI_KEY_F3 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
_ahButton[3]=BUTTON_Create(53,29,16,13, GUI_KEY_F4 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
_ahButton[4]=BUTTON_Create(85, 0, 16,13, GUI_KEY_F5, WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
_ahButton[5]=BUTTON_Create(85,29, 16,13, GUI_KEY_F6, WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV);
   //按键字体设置
   BUTTON_SetFont(_ahButton[0],&GUI_Font6x8);//GUI_Font16_ASCII
   BUTTON_SetFont(_ahButton[1],&GUI_Font6x8);//GUI_Font16_ASCII
   BUTTON_SetFont(_ahButton[2],&GUI_Font6x8);//GUI_Font16_ASCII
   BUTTON_SetFont(_ahButton[3],&GUI_Font6x8);//GUI_Font16_ASCII
   BUTTON_SetFont(_ahButton[4],&GUI_Font6x8);//GUI_Font16_ASCII
BUTTON_SetFont(_ahButton[5],&GUI_Font6x8);//GUI_Font16_ASCII
   //按键背景色设置
        BUTTON_SetBkColor(_ahButton[0],0,GUI_DARKMAGENTA);                                  //按键背景颜色
        BUTTON_SetBkColor(_ahButton[1],0,GUI_DARKMAGENTA);  
        BUTTON_SetBkColor(_ahButton[2],0,GUI_DARKMAGENTA);  
        BUTTON_SetBkColor(_ahButton[3],0,GUI_DARKMAGENTA);  
        BUTTON_SetBkColor(_ahButton[4],0,GUI_DARKMAGENTA);  
        BUTTON_SetBkColor(_ahButton[5],0,GUI_DARKMAGENTA);
   //按键前景色设置
        BUTTON_SetTextColor(_ahButton[0],0,GUI_WHITE);
        BUTTON_SetTextColor(_ahButton[1],0,GUI_WHITE);
        BUTTON_SetTextColor(_ahButton[2],0,GUI_WHITE);
        BUTTON_SetTextColor(_ahButton[3],0,GUI_WHITE);
        BUTTON_SetTextColor(_ahButton[4],0,GUI_WHITE);
        BUTTON_SetTextColor(_ahButton[5],0,GUI_WHITE);
                //按键显示字符
        BUTTON_SetText(_ahButton[0], "+");   
        BUTTON_SetText(_ahButton[1], "-");
        BUTTON_SetText(_ahButton[2], "+");
        BUTTON_SetText(_ahButton[3], "-");
        BUTTON_SetText(_ahButton[4], "+");
        BUTTON_SetText(_ahButton[5], "-");
        flag=1;
  }
                u8 key = GUI_GetKey();                                               //实时获得触摸按键的值
                if(key==40)                                                  //年数增加按钮
                {
                        s_time.tm_year++;                                                                //F1
                        if(s_time.tm_year>2099)                                                        //超过范围处理
                                s_time.tm_year=1970;
                }
                else if(key==41)                                                                        //年数减小按钮
                {
                        s_time.tm_year--;                                                                   //F2
                        if(s_time.tm_year<1900)                                                        //超过范围处理
                                s_time.tm_year=2099;
                }
                else if(key==42)                                                                         //月数增加按钮
                {
                        s_time.tm_mon++;                                                                   //F3
                        if(s_time.tm_mon>12)                                                        //超过范围处理
                        {
                                s_time.tm_mon=1;
                        }
                }
                else if(key==43)                                                                          //月数减小按钮
                {
                        s_time.tm_mon--;                                                                   //F4
                        if(s_time.tm_mon<0)                                                        //超过范围处理
                        {
                                s_time.tm_mon=12;
                                
                        }
                }
                else if(key==44)                                                                         //日数增加按钮
                {
                        s_time.tm_mday++;                                                                   //F5
                        if(s_time.tm_mday>getDays(s_time.tm_year,s_time.tm_mon))                //超过范围处理
                        {
                                s_time.tm_mday=1;
                        }
                }
                else if(key==45)                                                                         //日数减小按钮
                {
                        s_time.tm_mday--;                                                                   //F6
                        if(s_time.tm_mday<0)                                                        //超过范围处理
                        {
                                s_time.tm_mday=getDays(s_time.tm_year,s_time.tm_mon);
                        }
                }
        GUI_SetFont(&GUI_Font16_1 );
        GUI_DispDecAt(s_time.tm_year,4,13,4);                //显示万年历的年数
        GUI_SetFont(&GUI_FontHZ_SimSun_16);
        GUI_DispString("年");                                //显示年        
        GUI_SetFont(&GUI_Font16_1 );
        GUI_DispDec(s_time.tm_mon,2);                        //显示万年历的月数
        GUI_SetFont(&GUI_FontHZ_SimSun_16);
        GUI_DispString("月");                                //显示月
        GUI_SetFont(&GUI_Font16_1 );
        GUI_DispDec(s_time.tm_mday,2);                //显示万年历的日数
        GUI_SetFont(&GUI_FontHZ_SimSun_16);
        GUI_DispString("日");                                //显示日
        GUI_DispString("   ");        
        GetChinaCalendarStr((u16)systmtime.tm_year,(u8)systmtime.tm_mon,(u8)systmtime.tm_mday,str);        //阳历转阴历
//见下面子程序1
        GUI_DispString(str);                                 //显示阴历
        GUI_SetColor(GUI_RED);                                 //字体颜色
        GUI_DispString("竹天笑万年历");
           k=getWeekDay(s_time.tm_year,s_time.tm_mon,1);                //得到某年某月的第一天的星期数        //见下面子程序2
           GUI_GotoXY(18,69);                                .//位置设定
           GUI_SetFont(&GUI_Font6x8);   
  
//万年历日子显示
           for(i=1;i<=40;i++)                        //第一行最少显示一个,第六行最多显示二个,i的上限只需要大于37即可
           {
                   if(igetDays(s_time.tm_year,s_time.tm_mon)+k)                //本月1号前和最后一天后的格子显示清零
                   {                                                                                //见子程序3
                           GUI_DispString("  ");                                                //显示空格,用于清除之前数据
                   }
                   else
                   {
                                   if((i+1)%7==0||i%7==0)                                        //如果为星期六和星期天,字体设置为红色
                                   {
                                           GUI_SetColor(GUI_RED);
                                   }
                                   else                                                                //否则为黑色
                                   {
                                                GUI_SetColor(GUI_BLACK);
                                   }
                                if(i==s_time.tm_mday+k)                                        //如果该天为所选日期,设置背景为黄色
                                {
                                        GUI_SetBkColor(GUI_YELLOW);                 
                                }
                                   GUI_DispDecSpace(i-k,2);                                        //显示日子
                                GUI_SetBkColor(GUI_WHITE);                                //恢复之前背景色
                   }
                   GUI_GotoXY(GUI_GetDispPosX()+17,GUI_GetDispPosY());        //光标移动到下一个格子         
                   if(i%7==0)
                   {
                           GUI_GotoXY(18,GUI_GetDispPosY()+27);                        //7天换行显示
                   }
           }
           GUI_GotoXY(12,79);                                                                 //光标移动到下一行首行        
           GUI_SetFont(&GUI_FontHZ_SimSun_11);
//显示为初几,若为节气则显示节气
           for(i=1;i<=40;i++)
           {
                    if(igetDays(s_time.tm_year,s_time.tm_mon)+k)                //本月1号前和最后一天后的格子显示清零
                   {
                           GUI_DispString("  ");                                        //显示两个中文空格,占两个中文字符
                   }
                   else
                   {
                                   if(GetJieQiDay((u16)s_time.tm_year, (u8)s_time.tm_mon, i-k, str)==1)        //如果为节气
                                {                                                                                        //见子程序4
                                        GUI_SetColor(GUI_MAGENTA);                                                //设置字体为橙色
                                }
                                else
                                {
                                        GUI_SetColor(GUI_BLUE);                                                //正常显示蓝色
                                }
                                if(i==s_time.tm_mday+k)                                        //如果该天为所选日期,设置背景为黄色
                                {
                                        GUI_SetBkColor(GUI_YELLOW);
                                }
                                   GUI_DispString(str);                                        //显示阴历号
                                GUI_SetBkColor(GUI_WHITE);                                //恢复背景色
                   }
                        GUI_GotoXY(GUI_GetDispPosX()+7,GUI_GetDispPosY());                 
                   if(i%7==0)
                   {
                           GUI_GotoXY(12,GUI_GetDispPosY()+27);
                   }
           }
           WM_ExecIdle();                                                                          //刷新屏幕
                                                                                                        #defineDEG2RAD (3.1415926f / 180)
           GUI_POINT m_Hour[2],m_Sec[2],m_Min[2];                                        //时分秒两个端点
        static GUI_POINT m_OldHour[2],m_OldMin[2],m_OldSec[2];                        //时分秒之前的两个端点
         m_Hour[0].x=-20*cos((systmtime.tm_hour*30+90)*DEG2RAD)+264;                //时钟指针端点计算,每一时旋转30
         m_Hour[0].y=-20*sin((systmtime.tm_hour*30+90)*DEG2RAD)+170;                //度,逆时针旋转,当前时钟*30得旋
         m_Hour[1].x=-2*cos((systmtime.tm_hour*30+270)*DEG2RAD)+264;                //转的度数, 时钟另一端加上180度
         m_Hour[1].y=-2*sin((systmtime.tm_hour*30+270)*DEG2RAD)+170;                 //将极坐标形式转换成直角坐标
                GUI_SetColor(GUI_WHITE);                                                        //重绘上一次时钟指针覆盖的背景
                 GUI_DrawLine(m_OldHour[0].x,m_OldHour[0].y, m_OldHour[1].x,m_OldHour[1].y);
                GUI_SetColor(GUI_RED);                                                                //画新的时钟指针
                 GUI_DrawLine(m_Hour[0].x,m_Hour[0].y, m_Hour[1].x,m_Hour[1].y);

         m_Min[0].x=-30*cos((systmtime.tm_min*6+90)*DEG2RAD)+264;                        //分钟指针端点计算,每一分旋转6
         m_Min[0].y=-30*sin((systmtime.tm_min*6+90)*DEG2RAD)+170;                        //度,逆时针旋转,当前分钟*6得旋
         m_Min[1].x=-4*cos((systmtime.tm_min*6+270)*DEG2RAD)+264;                        //转的度数, 时钟另一端加上180度
         m_Min[1].y=-4*sin((systmtime.tm_min*6+270)*DEG2RAD)+170;                         //将极坐标形式转换成直角坐标
                 GUI_SetColor(GUI_WHITE);                                                        //重绘上一次分钟指针覆盖的背景
                  GUI_DrawLine(m_OldMin[0].x,m_OldMin[0].y, m_OldMin[1].x,m_OldMin[1].y);
                 GUI_SetColor(GUI_BLUE);                                                        //画新的分钟指针
                 GUI_DrawLine(m_Min[0].x,m_Min[0].y, m_Min[1].x,m_Min[1].y);

         m_Sec[0].x=-35*cos((systmtime.tm_sec*6+90)*DEG2RAD)+264;                        //分钟指针端点计算,每一秒旋转6
         m_Sec[0].y=-35*sin((systmtime.tm_sec*6+90)*DEG2RAD)+170;                        //度,逆时针旋转,当前秒钟*6得旋
         m_Sec[1].x=-8*cos((systmtime.tm_sec*6+270)*DEG2RAD)+264;                        //转的度数, 时钟另一端加上180度
         m_Sec[1].y=-8*sin((systmtime.tm_sec*6+270)*DEG2RAD)+170;                        //将极坐标形式转换成直角坐标
                 GUI_SetColor(GUI_WHITE);
                 GUI_DrawLine(m_OldSec[0].x,m_OldSec[0].y, m_OldSec[1].x,m_OldSec[1].y);
                 GUI_SetColor(GUI_BLACK);
                 GUI_DrawLine(m_Sec[0].x,m_Sec[0].y, m_Sec[1].x,m_Sec[1].y);
         for(i=0;i<2;i++)
        {           
                   m_OldHour=m_Hour;                                                           //保存当前时分秒指针
                   m_OldMin=m_Min;           
                   m_OldSec=m_Sec;
        }
                  /* 输出公历时间 */
         
                GUI_SetFont(&GUI_Font16_1 );
                GUI_DispDecAt(systmtime.tm_year, 240, 60,4);                                        //显示当前年                  
                GUI_DispString("-");
                GUI_DispDec(systmtime.tm_mon,2);                                                //显示当前月
                GUI_DispString("-");
                GUI_DispDec(systmtime.tm_mday,2);                                                //显示当前日        
                  GUI_DispDecAt(systmtime.tm_hour,240,76,2);                                        //显示当前时        
                GUI_DispString(":");
                GUI_DispDec(systmtime.tm_min,2);                                                //显示当前分        
                GUI_DispString(":");
                GUI_DispDec(systmtime.tm_sec,2);                                                //显示当前秒        
                GUI_SetFont(&GUI_FontHZ_SimSun_16);
                GUI_DispStringAt("星期",240,92);                                                //显示当前星期        
                  GUI_DispString(WEEK_STR[systmtime.tm_wday]);
}
子程序1
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// 函数名称:GetChinaCalendarStr
// 功能描述:输入公历日期得到农历字符串        
//          如:GetChinaCalendarStr(2007,02,06,str) 返回str="丙戌年腊月十九"
// 输 入:  year        公历年
//          month       公历月
//          day         公历日
//          str         储存农历日期字符串地址   15Byte
// 输 出:  无                                                                                                                                 
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void GetChinaCalendarStr(u16 year,u8 month,u8 day,u8 *str)
{
        u8 NLyear[4];
        u8 SEyear;
        StrCopy(&str[0],(u8 *)"甲子年正月初一",15);
        if(GetChinaCalendar(year,month,day,(u8 *)NLyear)==0)        return;        //GetChinaCalendar见子程序5,转化为阴历
        GetSkyEarth(NLyear[0]*100+NLyear[1],&SEyear);
        StrCopy(&str[0],(u8 *)  sky[SEyear%10],2);        //  甲
        StrCopy(&str[2],(u8 *)earth[SEyear%12],2);        //  子        
        if(NLyear[2]==1)        StrCopy(&str[6],(u8 *)"正",2);
        else                                StrCopy(&str[6],(u8 *)monthcode[NLyear[2]-1],2);               
        if(NLyear[3]>10)         StrCopy(&str[10],(u8 *)nongliday[NLyear[3]/10],2);        
        else                                StrCopy(&str[10],(u8 *)"初",2);
        StrCopy(&str[12],(u8 *)monthcode[(NLyear[3]-1)%10],2);
}
子程序2
u8 getWeekDay(u16 y, u8 m, u8 d)                  //得到指定年月日的星期数  
{        
        if (m == 1) m = 13;        
        if (m == 2) m = 14;        
        u8 week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 + 1;        
        return week;   
}
子程序3
/*
*判断是否闰年
*参数:   y 整型, 接收年份值
*返回值: 整型, 只为0或1, 0代表假, 1代表真
*/
u8 isRunNian(u16 y)
{
return (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) ? 1 : 0;
}
/*
*计算某个月的天数
*参数:   y 整型,接收年份值; m 整型,接收月份值;
*返回值: 整型, 是0, 28, 29, 30, 31之间的一个数
*注意:   返回值为0,表示你调用该函数时传递了不正确的年份值或月份值.
*/
u8 getDays(u16 y, u8 m)
{
u8 days = 0;
switch(m)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
  days = 31; break;
case 4:
case 6:
case 9:
case 11:
  days = 30; break;
case 2:
  days = isRunNian(y) ? 29 : 28; break;
default:;
}
return days;
}
子程序4
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// 函数名称:GetJieQiDay
// 功能描述:输入公历日期得到24节气字符串        
//          是否为节气
// 输 入:  year        公历年
//          month       公历月
//          day         公历日
//          str         储存24节气字符串地址   5Byte
// 输 出:  1           成功
//          0           失败                                                                                                                                                         
/////////////////////////////////////////////////////////////////////////////////////////////////////////
u8 GetJieQiDay(u16 year,u8 month,u8 day,u8 *str)
{
        u8 JQdate,JQ;
        u8 NLyear[4];
        StrCopy(&str[0],(u8 *)"初一",5);
        if(GetJieQi(year,month,day,&JQdate)==0)        return 0;
        JQ = (month-1) *2 ;                             //获得节气顺序标号(0~23
        if(day >= 15) JQ++;                             //判断是否是上半月
        if(day==JQdate)                                 //今天正是一个节气日
        {
                StrCopy(str,(u8 *)JieQiStr[JQ],5);
                return 1;
        }                                            //今天不是一个节气日
        else
        {        
                GetChinaCalendar(year,month,day,(u8 *)NLyear);
                if(NLyear[3]>10)         StrCopy(&str[0],(u8 *)nongliday[NLyear[3]/10],2);        
                else                                StrCopy(&str[0],(u8 *)"初",2);
                StrCopy(&str[2],(u8 *)monthcode[(NLyear[3]-1)%10],2);
                return 0;
        }
}
子程序5
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 函数名称:GetChinaCalendar
//功能描述:公农历转换(只允许1901-2099年)
// 输 入:  year        公历年
//          month       公历月
//          day         公历日
//          p           储存农历日期地址
// 输 出:  1           成功
//          0           失败                                                                                                                                                         
/////////////////////////////////////////////////////////////////////////////////////////////////////////
u8 GetChinaCalendar(u16  year,u8 month,u8 day,u8 *p)
{
        u8 temp1,temp2,temp3,month_p,yearH,yearL;        
        u8 flag_y;
        unsigned short temp4,table_addr;

        yearH=year/100;        yearL=year%100;//年份的高低两个字节
        if((yearH!=19)&&(yearH!=20))return(0);//日期不在19xx ~ 20xx 范围内,则退出
        
        // 定位数据表地址  
        if(yearH==20)        table_addr=(yearL+100-1)*3;
        else                          table_addr=(yearL-1)*3;

        // 取当年春节所在的公历月份  
        temp1=year_code[table_addr+2]&0x60;        
        temp1>>=5;

        // 取当年春节所在的公历日  
        temp2=year_code[table_addr+2]&31;

        // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月  
        if(temp1==1)         temp3=temp2-1;
        else                         temp3=temp2+31-1;

        // 计算公历日离当年元旦的天数  
        if (month<10)         temp4=day_code1[month-1]+day-1;
        else                          temp4=day_code2[month-10]+day-1;
        // 如果公历月大于2月并且该年的2月为闰月,天数加1  
        if ((month>2)&&(yearL%4==0))         temp4++;

        // 判断公历日在春节前还是春节后  
        if (temp4>=temp3)
        {                                                
                temp4-=temp3;
                month=1;
                month_p=1;
                                                        
                flag_y=0;
                if(GetMoonDay(month_p,table_addr)==0)        temp1=29; //小月29天
                else                                                                         temp1=30; //大小30天
                // 从数据表中取该年的闰月月份,如为0则该年无闰月  
                temp2=year_code[table_addr]/16;         
                while(temp4>=temp1)
                {
                        temp4-=temp1;
                        month_p++;
                        if(month==temp2)
                        {
                                flag_y=~flag_y;
                                if(flag_y==0)month++;
                        }
                        else month++;
                        if(GetMoonDay(month_p,table_addr)==0)        temp1=29;
                        else                                                                         temp1=30;
                }
                day=temp4+1;
        }
        // 公历日在春节前使用下面代码进行运算  
        else
        {                                                
                temp3-=temp4;
                if (yearL==0)
                {
                        yearL=100-1;
                        yearH=19;
                }
                else yearL--;
                table_addr-=3;
                month=12;
                temp2=year_code[table_addr]/16;         
                if (temp2==0)        month_p=12;
                else                         month_p=13;

                flag_y=0;
                if(GetMoonDay(month_p,table_addr)==0)        temp1=29;
                else                                                                         temp1=30;
                while(temp3>temp1)
                {
                        temp3-=temp1;
                        month_p--;
                        if(flag_y==0)                month--;
                        if(month==temp2)        flag_y=~flag_y;
                        if(GetMoonDay(month_p,table_addr)==0)        temp1=29;
                        else                                                                         temp1=30;
                }
                day=temp1-temp3+1;
        }

        *p++=yearH;
        *p++=yearL;
        *p++=month;
        *p=day;        
        return(1);
}
2、触摸屏任务:处理触摸屏按键任务,更改要查询的年月日。
static  void  AppTaskKbd (void *p_arg)
{  
   (void)p_arg;
   TP_Init();        //触摸初始化
   while(1)
   {
      OSTimeDlyHMSM(0,0,0,10);
          GUI_TOUCH_Exec(); //触摸执行程序,详细请阅读ucgui教程
}
}
3、秒更新任务:秒更新任务中一直等待一个OS_EVENT(信号量),RTC闹钟一秒钟中断一次,闹钟中断程序中发送信号量,秒更新任务接到OS_EVENT(信号量)便执行一次,更新当前的时间。(如果没有不用uCOS中的信号量的话,直接设置一个全局变量也可,在中断函数中将其置1,秒更新任务中判断其为1执行,然后将其置零,等待下一次为1。
void  Clock_Updata(void *p_arg)
{   
        INT8U err;
        (void)p_arg;        
        while(1)
        {
           OSSemPend(Clock_SEM,0,&err);                   //等待 时钟更新信号量
           RTC_Get(RTC_GetCounter());               
        }
}
void RTC_Get(uint32_t TimeVar)
{              
//根据RTC时钟得到时钟的初值,注意,这个值是根据系统自动变化
        to_tm(TimeVar, &systmtime);                          //使用野火RTC例程中的date.c
}
//时间结构体
struct rtc_time {
        int tm_sec;
        int tm_min;
        int tm_hour;
        int tm_mday;
        int tm_mon;
        int tm_year;
        int tm_wday;
};
//RTC计数转化为年月日时分秒,储存在systmtime
void to_tm(u32 tim, struct rtc_time * tm)
{
        register u32    i;
        register long   hms, day;
        day = tim / SECDAY;                        //#define SECDAY                        86400L        得到天数
        hms = tim % SECDAY;                        //余下的为时分秒
        /* Hours, minutes, seconds are easy */
        tm->tm_hour = hms / 3600;           //时
        tm->tm_min = (hms % 3600) / 60;                //分
        tm->tm_sec = (hms % 3600) % 60;        //秒
/* Number of years in days */ /*算出当前年份,起始的计数年份为1970年,总天数减去从1970开始递增的每年天数,当天数小于365/366时,得到当前的年份*/
        for (i = STARTOFTIME; day >= days_in_year(i); i++)                //#define        STARTOFTIME                1970
{                                                               
                day -= days_in_year(i);                                        //#define        days_in_year(a)         (leapyear(a) ? 366 : 365)
        }                                                                     .//#define        leapyear(year)                ((year) % 4 == 0)
        tm->tm_year = i;
        /* Number of months in days left */ /*计算当前的月份*/
        if (leapyear(tm->tm_year))                                                //如果为闰年,二月为29天
{
                days_in_month(FEBRUARY) = 29;                         //#define FEBRUARY                2
        }                                                                        
for (i = 1; day >= days_in_month(i); i++)        //剩下的总天数减去从1月开始递增的每月天数,当天数小于当前月天数时,得到当前的月份。
{                                                //static int month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
                day -= days_in_month(i);                                        //#define        days_in_month(a)         (month_days[(a) - 1])
        }
        days_in_month(FEBRUARY) = 28;                                //还原二月的天数为28天
        tm->tm_mon = i;

        /* Days are what is left over (+1) from all that. *//*计算当前日期*/        
        tm->tm_mday = day + 1;                                                //剩下的天数加一为日。
        /*
         * Determine the day of week
         */
        GregorianDay(tm);
}
/*得到星期几*/
void GregorianDay(struct rtc_time * tm)
{
        int leapsToDate;
        int lastYear;
        int day;
        int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
        lastYear=tm->tm_year-1;
        /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
        leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      
     /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
        if((tm->tm_year%4==0) &&((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && (tm->tm_mon>2)) {
                day=1;
        } else {
                day=0;
        }
        day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从公元元年元旦到计数日期一共有多少天*/
        tm->tm_wday=day%7;                                                //得到今天为星期几
}

附件:[attach]817[/attach]
展开
折叠
1241
评论
共 0 个
内容存在敏感词
    易百纳技术社区暂无数据
相关资料
关于作者
易百纳技术社区
495005638
贡献资料 38
易百纳技术社区 我上传的资料
登录查看
我赚取的积分
登录查看
我赚取的收益
登录查看
上传资料 赚取积分兑换E币
易百纳技术社区
删除原因
广告/SPAM
恶意灌水
违规内容
文不对题
重复发帖
置顶时间设置
结束时间
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-资料模块

审核失败

失败原因
备注
易百纳技术社区