找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2750|回复: 0
打印 上一主题 下一主题
收起左侧

STM32红外遥控RTC时钟温度采集报警仪程序源码

[复制链接]
跳转到指定楼层
楼主
ID:427027 发表于 2018-11-20 10:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
采用学过的STM32微控制器芯片设计一个温度采集报警仪。该温度采集报警仪可以通过数...

1、温度采集和显示功能:通过电位器模拟温度传感器,量程范围0~3.3V对应-10~+200度,在LCD上显示电位器所模拟的温度值。或者通过DS18B20数字温度传感器采集环境温度,并通过LCD进行显示。
2、温度报警功能:环境温度如果超过设定的温度高报警值,报警指示灯LED1开始闪烁,温度越高闪烁的频率越快;如果低于温度高报警值,LED1熄灭,在LCD上显示温度报警值。
3、温度高报警值修改功能:可以通过红外遥控器或按键调整温度高报警值。
4、在LCD上显示自己的中文名字。
5、时钟功能:在LCD上显示当前的时间。
6、定时控制功能:根据设定的动作时间控制LED2开始闪烁或停止闪烁(熄灭);也可在定时控制动作后延迟一段时间熄灭LED2灯,或者通过红外遥控器及按键直接消除LED2的闪烁(类似闹钟功能)。
7、时间修改功能:可以通过红外遥控器或按键调整当前时间和定时时间。

单片机源程序如下:
  1. /******************** 尚学科技 **************************
  2. * 实验平台:开拓者STM32开发板
  3. * 库版本  :ST3.5.0
  4. * 本程序只供学习使用,未经作者许可,不得用于其它任何用途
  5. *版权所有,盗版必究。
  6. **********************************************************************************/
  7. #include "usart1.h"
  8. #include "lcd.h"
  9. #include "text.h"
  10. #include "temperature.h"
  11. #include "delay.h"
  12. #include "text.h"
  13. #include "LED.h"
  14. #include "Key.h"
  15. #include "rtc.h"
  16. #include "remote.h"


  17. const unsigned char HZ_1616[][32]={
  18. {0x00, 0x10, 0x1F, 0xF8, 0x10, 0x10, 0x10, 0x10, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x10, 0x3F, 0xF8,
  19. 0x01, 0x00, 0x01, 0x04, 0xFF, 0xFE, 0x02, 0x80, 0x02, 0x40, 0x04, 0x20, 0x18, 0x1C, 0x60, 0x08,},
  20. {0x00, 0x08, 0x7F, 0xFC, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x10, 0x3F, 0xF8,
  21. 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 0x01, 0x30, 0x01, 0x10, 0x01, 0x04, 0xFF, 0xFE, 0x00, 0x00,},
  22. {0x10, 0x40, 0x10, 0x24, 0x13, 0xFE, 0x10, 0x00, 0xFC, 0xF8, 0x24, 0x88, 0x24, 0xF8, 0x24, 0x00,
  23. 0x27, 0xFE, 0x4A, 0x02, 0x29, 0xFC, 0x10, 0x20, 0x28, 0x20, 0x44, 0x20, 0x84, 0xA0, 0x00, 0x40}
  24. };
  25. void LCD_DrawPoint1(u16 x,u16 y,u16 Color)
  26. {
  27.         LCD_SetCursor(x,y);//设置光标位置
  28.         LCD_WriteRAM_Prepare();        //开始写入GRAM
  29.         LCD_WR_DATA(Color);
  30. }
  31. void LCD_ShowHZ(u16 x,u16 y,u8 num,u8 size,u8 mode,u16 Color)
  32. {  

  33.     u8 temp;
  34.     u8 j,k;
  35.           u8 count;
  36.         u16 x0=x;   
  37. //   Char_Horizontal_or_Vertical_Set();
  38.     if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return;            
  39.         //设置窗口                  
  40.           ;//得到偏移后的值
  41.         if(mode==0) //正常显示
  42.         {
  43.                 for(j=0;j<size;j++)
  44.                 {
  45.                         //字体大小选择
  46.                                 temp=HZ_1616[num][2*j];        
  47.                                 count=8;
  48.                         for(k=0;k<count;k++)
  49.                     {                 
  50.                     if(temp&0x80)
  51.                                 {
  52.                                 LCD_DrawPoint1(x,y,BLACK);        
  53.                                 }
  54.                                 else
  55.                                 {
  56.                                 LCD_DrawPoint1(x,y,WHITE);        
  57.                                 }
  58.                                 temp<<=1;
  59.                                 x++;
  60.                     }
  61.                                 
  62.                                 temp=HZ_1616[num][2*j+1];        
  63.                                 count=8;
  64.                         for(k=0;k<count;k++)
  65.                     {                 
  66.                     if(temp&0x80)
  67.                                 {
  68.                                 LCD_DrawPoint1(x,y,BLACK);        
  69.                                 }
  70.                                 else
  71.                                 {
  72.                                 LCD_DrawPoint1(x,y,WHITE);        
  73.                                 }
  74.                                 temp<<=1;
  75.                                 x++;
  76.                     }
  77.                         x=x0;
  78.                         y++;
  79.                 }        
  80.         }
  81. }
  82. void LED2_GPIO_Config(void)
  83. {
  84.          GPIO_InitTypeDef GPIO_InitStructure;

  85.         /*开启GPIOC的外设时钟*/
  86.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

  87.         /*选择要控制的GPIOC引脚*/                                                                                                                           
  88.      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        

  89.         /*设置引脚模式为通用推挽输出*/
  90.            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  91.         /*设置引脚速率为50MHz */   
  92.            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  93.         /*调用库函数,初始化GPIOC*/
  94.      GPIO_Init(GPIOD, &GPIO_InitStructure);
  95.          
  96. }
  97. void TIME_NVIC_Configuration(void)
  98. {
  99.         NVIC_InitTypeDef NVIC_InitStructure;
  100.         /*设置NVIC中断分组2:2位抢占优先级,2位响应优先级*/
  101.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        
  102.         /*TIM3中断*/
  103.   NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  104.   /*先占优先级0级*/        
  105.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  106.   /*从优先级3级*/        
  107.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  108.   /*IRQ通道被使能*/        
  109.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  110.         /*根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器*/
  111.         NVIC_Init(&NVIC_InitStructure);  
  112. }
  113. void TIME_Configuration(void)
  114. {
  115.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  116.         /*定时器TIM3时钟使能*/
  117.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  118.   /*设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到5000为500ms*/
  119.         TIM_TimeBaseStructure.TIM_Period = 36000-1;
  120.         /*设置用来作为TIMx时钟频率除数的预分频值*/
  121.         TIM_TimeBaseStructure.TIM_Prescaler =(2000-1);
  122.   /*设置时钟分割:TDTS = Tck_tim*/  
  123.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  124.         /*TIM向上计数模式*/
  125.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  126.   /*根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位*/
  127.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  128.   /*使能或者失能指定的TIM中断*/
  129.         TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_Trigger,ENABLE);
  130.         /*使能TIMx外设*/
  131. //        TIM_Cmd(TIM3, ENABLE);  
  132. }
  133. void TIM3_IRQHandler(void)   
  134. {if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
  135.                 {
  136.                         GPIOD->ODR^=1<<2;
  137.                         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除标志位
  138.                 }
  139. }


  140. int main(void)
  141. {
  142.          u8 acer;
  143.          u8 ACER;
  144.          u8 H=18;
  145.          u8 M=1;
  146.          u8 S;
  147.          u8 flag;
  148.          u8 FLAG;
  149.         u16 temp;
  150.          u8 key;
  151.         float t,A=0;
  152.   float temp_value;
  153.         float temperate;
  154.         float temp_set=40;
  155.         char str[5];
  156.         unsigned char value=0;
  157.         USART1_Config();                        //串口初始化
  158.         
  159.         Stm32_Clock_Init(9);        //系统时钟设置        
  160.         uart_init(72,9600);                 //串口初始化为9600
  161.          delay_init(72);                            //延时初始化
  162.          LED_GPIO_Config();                //LED 端口初始化
  163.         Key_GPIO_Config();                // 按键端口初始化
  164.   Temperature_Adc_Init();//温度转换器初始化
  165. Remote_Init();                        //红外接收初始化
  166.           LED2_GPIO_Config();               
  167.                  TIME_NVIC_Configuration();
  168.   TIME_Configuration();
  169.         GPIO_WriteBit(GPIOD,GPIO_Pin_2,(BitAction)1);

  170.         RTC_Init();
  171.         POINT_COLOR=RED;
  172.         LCD_Init();                                                //屏幕初始化
  173.         LCD_Clear(WHITE);
  174.         LCD_ShowString(30,30,"wu yu ting",POINT_COLOR);        
  175.         LCD_ShowString(30,70,"1503150108",POINT_COLOR);        
  176.         LCD_ShowString(30,90,"warninig:",POINT_COLOR);
  177.         LCD_ShowString(90,110,"C:",POINT_COLOR);
  178.         LCD_ShowString(30,130,"temp:",POINT_COLOR);
  179.         LCD_ShowString(90,150,"C",POINT_COLOR);


  180.          LCD_ShowString(30,170,"RTC IS READY!   ",POINT_COLOR);
  181.          LCD_ShowString(30,190,"    -  -     ",POINT_COLOR);           
  182.          LCD_ShowString(30,210,"  :  :  ",POINT_COLOR);
  183.          LCD_ShowString(30,250,"  :  :  ",POINT_COLOR);        
  184.          LCD_ShowHZ(30,50,0,16,0,BLACK);
  185.           LCD_ShowHZ(55,50,1,16,0,BLACK);
  186.                   LCD_ShowHZ(80,50,2,16,0,BLACK);


  187.   while(1)
  188.         {                 temp=Get_Temperature_value();//得到内部温度的数字量的值
  189.                         temperate=temp*(3.3/4095);//保存温度传感器的电压值
  190.                         temp_value=(1.43-temperate)/0.0043+25;        //得到芯片内部的温度
  191.         key=Remote_Scan();        
  192.                         if(key)
  193.                 {        
  194.                   switch(key)
  195.                         {   
  196.                                    case 56://按键5
  197.                                         FLAG=0;
  198.                                               ACER=0;
  199.                                   LCD_ShowString(30,10,"                ",POINT_COLOR);break;
  200.                                              
  201.                                          case 226: //按键MENU
  202.                                                  {        FLAG++;
  203.                                                                                         if(FLAG==1){LCD_ShowString(30,10,"Set year",POINT_COLOR);flag=1;break;}
  204.                                                                                         else if(FLAG==2){LCD_ShowString(30,10,"Set month",POINT_COLOR);flag=2;break;}
  205.                                                                                         else if(FLAG==3){LCD_ShowString(30,10,"Set date     ",POINT_COLOR);flag=3;break;}
  206.                                                                                         else if(FLAG==4){LCD_ShowString(30,10,"Set hour     ",POINT_COLOR);flag=4;break;}
  207.                                                                                         else if(FLAG==5){LCD_ShowString(30,10,"Set min      ",POINT_COLOR);flag=5;break;}
  208.                                                                                         else if(FLAG==6){LCD_ShowString(30,10,"Set sec      ",POINT_COLOR);flag=6;break;}
  209.                                                                                         else if(FLAG>6&&FLAG%6==1){FLAG==1;LCD_ShowString(30,10,"Set year",POINT_COLOR);flag=1;break;}
  210.                                                                                         break;
  211.                                                                                 }
  212.                                                 case 144://按键right
  213.                                                                                 {
  214.                                                                                         if(flag==1){calendar.w_year++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  215.                                                                                         else if(flag==2){calendar.w_month++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  216.                                                                                         else if(flag==3){calendar.w_date++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  217.                                                                                         else if(flag==4){calendar.hour++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  218.                                                                                         else if(flag==5){calendar.min++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  219.                                                                                         else if(flag==6){calendar.sec++;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  220.                                                                                         break;
  221.                                                                                 }
  222.                                                 case 224: //按键left
  223.                                                                                 {
  224.                       if(flag==1){calendar.w_year--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  225.                                                                                         else if(flag==2){calendar.w_month--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  226.                                                                                         else if(flag==3){calendar.w_date--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  227.                                                                                         else if(flag==4){calendar.hour--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  228.                                                                                         else if(flag==5){calendar.min--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}
  229.                                                                                         else if(flag==6){calendar.sec--;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);break;}        
  230.                                                                                         break;
  231.                                                                                 }
  232.                                                                                                 
  233.                           case 152:
  234.                                          temp_set =temp_set -1;                                //("按键:VOL- \r\n");
  235.                                         break;
  236.                                 case 2:
  237.                                           temp_set=temp_set +1;                                //("按键:VOL+\r\n");
  238.                                                                
  239.                                              case 162://按键power
  240.                                                        {  ACER++;
  241.                                                                                         if(ACER==1){LCD_ShowString(30,10,"Set clock hour",POINT_COLOR);acer=1;break;}
  242.                                                                                         else if(ACER==2){LCD_ShowString(30,10,"Set clock min",POINT_COLOR);acer=2;break;}
  243.                                                                                         else if(ACER==3){LCD_ShowString(30,10,"Set clock sec ",POINT_COLOR);acer=3;break;}
  244.                                                                       else if(ACER>3&&ACER%3==1){ACER==1;LCD_ShowString(30,10,"Set clock hour",POINT_COLOR);acer=1;break;}
  245.                                                                                         break;
  246.                                                                                 }
  247.                                                 case 90://按键6
  248.                                                                                 {
  249.                                                                                         if(acer==1){H++;break;}
  250.                                                                                         else if(acer==2){M++;break;}
  251.                                                                                         else if(acer==3){S++;break;}
  252.                                                                                   break;
  253.                                                                                 }
  254.                                                 case 16://按键4
  255.                                                                                 {
  256.                       if(acer==1){H--;break;}
  257.                                                                                         else if(acer==2){M--;break;}
  258.                                                                                         else if(acer==3){S--;break;}
  259.                       break;
  260.                                                                                 }
  261.                                                                                           case 34: //按键:text
  262.                                     A=1;
  263.                                         break;                        
  264.                                            }
  265.                                          }
  266.                         if((calendar.hour==H)&&(calendar.min==M)&&(calendar.sec==S))
  267.                         {TIM_Cmd(TIM3, ENABLE);}
  268.                         if(A)                                
  269.      {
  270.              {
  271.                                  TIM_Cmd(TIM3,DISABLE );
  272.          LED2_OFF;
  273.                                  A=0;
  274.                          }
  275. }
  276.                 //时间显示
  277.    POINT_COLOR=RED;
  278.                 if(t!=calendar.sec)
  279.                 {
  280.                         t=calendar.sec;
  281.       LCD_ShowNum(30,190,calendar.w_year,4,16);                                                                          
  282.                         LCD_ShowNum(70,190,calendar.w_month,2,16);                                                                          
  283.                         LCD_ShowNum(94,190,calendar.w_date,2,16);
  284.       LCD_ShowNum(30,210,calendar.hour,2,16);                                                                          
  285.                         LCD_ShowNum(54,210,calendar.min,2,16);                                                                          
  286.                         LCD_ShowNum(78,210,calendar.sec,2,16);
  287.       LCD_ShowNum(30,250,H,2,16);                                                                          
  288.                         LCD_ShowNum(54,250,M,2,16);                                                                          
  289.                         LCD_ShowNum(78,250,S,2,16);               
  290.                         switch(calendar.week)
  291.                                                 {
  292.                                                         case 0:
  293.                                                                 LCD_ShowString(30,230,"Sunday   ",POINT_COLOR);
  294.                                                                 break;
  295.                                                         case 1:
  296.                                                                 LCD_ShowString(30,230,"Monday   ",POINT_COLOR);
  297.                                                                 break;
  298.                                                         case 2:
  299.                                                                 LCD_ShowString(30,230,"Tuesday  ",POINT_COLOR);
  300.                                                                 break;
  301.                                                         case 3:
  302.                                                                 LCD_ShowString(30,230,"Wednesday",POINT_COLOR);
  303.                                                                 break;
  304.                                                         case 4:
  305.                                                                 LCD_ShowString(30,230,"Thursday ",POINT_COLOR);
  306.                                                                 break;
  307.                                                         case 5:
  308.                                                                 LCD_ShowString(30,230,"Friday   ",POINT_COLOR);
  309.                                                                 break;
  310.                                                         case 6:
  311.                                                                 LCD_ShowString(30,230,"Saturday ",POINT_COLOR);
  312.                                                                 break;  
  313.                                                  }        
  314.                  
  315.             }         
  316.                
  317.                 /*按键控制报警上限*/
  318.                 {        
  319.                         value=KEY_Scan(); //获取按键值
  320.                    if(value==2)
  321.                                  temp_set+=1;
  322.                    else if(value==1)
  323.                                  temp_set-=1;

  324.                 }
  325.                
  326.                 /*报警闪烁*/
  327.                 {        if(temp_value>temp_set)
  328.                                 {          LED1_ON;
  329.                                                 Delay(100000/(temp_value-temp_set));
  330.                                                 LED1_OFF;
  331.                                                 Delay(100000/(temp_value-temp_set));
  332.                                 }
  333.                         else
  334.                                 {                LED1_OFF;
  335.                                 }
  336.                 }
  337.                
  338.                 /*温度显示*/
  339.                 {        
  340.                         fun(temp_set,str);
  341.                         LCD_ShowString(50,110,str,POINT_COLOR);
  342.                         fun(temp_value,str);
  343.                         LCD_ShowString(50,150,str,POINT_COLOR);
  344.                         Delay(500000);
  345.                 }
  346.   }        
  347. }
复制代码

rtc程序:
  1. #include "delay.h"
  2. #include "usart.h"
  3. #include "rtc.h"                     

  4.           
  5. _calendar_obj calendar;//时钟结构体        
  6.    
  7. //实时时钟配置
  8. //初始化RTC时钟,同时检测时钟是否工作正常
  9. //BKP->DR1用于保存是否第一次配置的设置
  10. //返回0:正常
  11. //其他:错误代码
  12. u8 RTC_Init(void)
  13. {
  14.         //检查是不是第一次配置时钟
  15.         u8 temp=0;
  16.         if(BKP->DR1!=0X5050)//第一次配置
  17.         {         
  18.                   RCC->APB1ENR|=1<<28;     //使能电源时钟            
  19.                 RCC->APB1ENR|=1<<27;     //使能备份时钟            
  20.                 PWR->CR|=1<<8;           //取消备份区写保护
  21.                 RCC->BDCR|=1<<16;        //备份区域软复位          
  22.                 RCC->BDCR&=~(1<<16);     //备份区域软复位结束                   
  23.             RCC->BDCR|=1<<0;         //开启外部低速振荡器
  24.             while((!(RCC->BDCR&0X02))&&temp<250)//等待外部时钟就绪         
  25.                 {
  26.                         temp++;
  27.                         delay_ms(10);
  28.                 };
  29.                 if(temp>=250)return 1;//初始化时钟失败,晶振有问题          
  30.                 RCC->BDCR|=1<<8; //LSI作为RTC时钟             
  31.                 RCC->BDCR|=1<<15;//RTC时钟使能          
  32.                   while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成         
  33.             while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步  
  34.             RTC->CRH|=0X01;                    //允许秒中断
  35.             while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成         
  36.                 RTC->CRL|=1<<4;           //允许配置         
  37.                 RTC->PRLH=0X0000;
  38.                 RTC->PRLL=32767;          //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767       
  39.                 RTC_Set(2017,6,22,18,00,00);  //设置时间          
  40.                 RTC->CRL&=~(1<<4);           //配置更新
  41.                 while(!(RTC->CRL&(1<<5)));   //等待RTC寄存器操作完成                                                                                           
  42.                 BKP->DR1=0X5050;  
  43.                  printf("FIRST TIME\n");
  44.         }else//系统继续计时
  45.         {
  46.             while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步  
  47.             RTC->CRH|=0X01;                    //允许秒中断
  48.             while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
  49.                 printf("OK\n");
  50.         }                                                      
  51.         MY_NVIC_Init(0,0,RTC_IRQn,2);//优先级设置   
  52.         RTC_Get();//更新时间
  53.         return 0; //ok
  54. }                                                     
  55. //RTC时钟中断
  56. //每秒触发一次           
  57. void RTC_IRQHandler(void)
  58. {                 
  59.         if(RTC->CRL&0x0001)//秒钟中断
  60.         {                                                       
  61.                 RTC_Get();//更新时间   
  62.                 //printf("sec:%d\r\n",calendar.sec);
  63.         }
  64.         if(RTC->CRL&0x0002)//闹钟中断
  65.         {
  66.                 RTC->CRL&=~(0x0002);                //清闹钟中断          
  67.                   //printf("Alarm!\n");                  
  68.           }                                                                                                    
  69.     RTC->CRL&=0X0FFA;         //清除溢出,秒钟中断标志
  70.         while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成                                                                                           
  71. }
  72. //判断是否是闰年函数
  73. //月份   1  2  3  4  5  6  7  8  9  10 11 12
  74. //闰年   31 29 31 30 31 30 31 31 30 31 30 31
  75. //非闰年 31 28 31 30 31 30 31 31 30 31 30 31
  76. //year:年份
  77. //返回值:该年份是不是闰年.1,是.0,不是
  78. u8 Is_Leap_Year(u16 year)
  79. {                          
  80.         if(year%4==0) //必须能被4整除
  81.         {
  82.                 if(year%100==0)
  83.                 {
  84.                         if(year%400==0)return 1;//如果以00结尾,还要能被400整除           
  85.                         else return 0;   
  86.                 }else return 1;   
  87.         }else return 0;       
  88. }                                   
  89. //设置时钟
  90. //把输入的时钟转换为秒钟
  91. //以1970年1月1日为基准
  92. //1970~2099年为合法年份
  93. //返回值:0,成功;其他:错误代码.
  94. //月份数据表                                                                                         
  95. u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表          
  96. //平年的月份日期表
  97. const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  98. //syear,smon,sday,hour,min,sec:年月日时分秒
  99. //返回值:设置结果。0,成功;1,失败。
  100. u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  101. {
  102.         u16 t;
  103.         u32 seccount=0;
  104.         if(syear<1970||syear>2099)return 1;          
  105.         for(t=1970;t<syear;t++)        //把所有年份的秒钟相加
  106.         {
  107.                 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
  108.                 else seccount+=31536000;                          //平年的秒钟数
  109.         }
  110.         smon-=1;
  111.         for(t=0;t<smon;t++)           //把前面月份的秒钟数相加
  112.         {
  113.                 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
  114.                 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数          
  115.         }
  116.         seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
  117.         seccount+=(u32)hour*3600;//小时秒钟数
  118.     seccount+=(u32)min*60;         //分钟秒钟数
  119.         seccount+=sec;//最后的秒钟加上去
  120.                                                                                                             
  121.         //设置时钟
  122.     RCC->APB1ENR|=1<<28;//使能电源时钟
  123.     RCC->APB1ENR|=1<<27;//使能备份时钟
  124.         PWR->CR|=1<<8;    //取消备份区写保护
  125.         //上面三步是必须的!
  126.         RTC->CRL|=1<<4;   //允许配置
  127.         RTC->CNTL=seccount&0xffff;
  128.         RTC->CNTH=seccount>>16;
  129.         RTC->CRL&=~(1<<4);//配置更新
  130.         while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
  131.         RTC_Get();//设置完之后更新一下数据        
  132.         return 0;            
  133. }
  134. //得到当前的时间,结果保存在calendar结构体里面
  135. //返回值:0,成功;其他:错误代码.
  136. u8 RTC_Get(void)
  137. {
  138.         static u16 daycnt=0;
  139.         u32 timecount=0;
  140.         u32 temp=0;
  141.         u16 temp1=0;          
  142.         timecount=RTC->CNTH;//得到计数器中的值(秒钟数)
  143.         timecount<<=16;
  144.         timecount+=RTC->CNTL;                         

  145.         temp=timecount/86400;   //得到天数(秒钟数对应的)
  146.         if(daycnt!=temp)//超过一天了
  147.         {          
  148.                 daycnt=temp;
  149.                 temp1=1970;        //从1970年开始
  150.                 while(temp>=365)
  151.                 {                                 
  152.                         if(Is_Leap_Year(temp1))//是闰年
  153.                         {
  154.                                 if(temp>=366)temp-=366;//闰年的秒钟数
  155.                                 else break;  
  156.                         }
  157.                         else temp-=365;          //平年
  158.                         temp1++;  
  159.                 }   
  160.                 calendar.w_year=temp1;//得到年份
  161.                 temp1=0;
  162.                 while(temp>=28)//超过了一个月
  163.                 {
  164.                         if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
  165.                         {
  166.                                 if(temp>=29)temp-=29;//闰年的秒钟数
  167.                                 else break;
  168.                         }
  169.                         else
  170.                         {
  171.                                 if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
  172.                                 else break;
  173.                         }
  174.                         temp1++;  
  175.                 }
  176.                 calendar.w_month=temp1+1;        //得到月份
  177.                 calendar.w_date=temp+1;          //得到日期
  178.         }
  179.         temp=timecount%86400;                     //得到秒钟数             
  180.         calendar.hour=temp/3600;             //小时
  181.         calendar.min=(temp%3600)/60;         //分钟       
  182.         calendar.sec=(temp%3600)%60;         //秒钟
  183.         calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期   
  184.         return 0;
  185. }         
  186. //获得现在是星期几
  187. //功能描述:输入公历日期得到星期(只允许1901-2099年)
  188. //year,month,day:公历年月日
  189. //返回值:星期号                                                                                                                                                                                 
  190. u8 RTC_Get_Week(u16 year,u8 month,u8 day)
  191. {       
  192.         u16 temp2;
  193.         u8 yearH,yearL;
  194.        
  195.         yearH=year/100;        yearL=year%100;
  196.         // 如果为21世纪,年份数加100  
  197.         if (yearH>19)yearL+=100;
  198.         // 所过闰年数只算1900年之后的  
  199.         temp2=yearL+yearL/4;
  200.         temp2=temp2%7;
  201.         temp2=temp2+day+table_week[month-1];
  202.         if (yearL%4==0&&month<3)temp2--;
  203.         return(temp2%7);
  204. }
复制代码

红外遥控程序:
  1. #include "remote.h"
  2. #include "delay.h"


  3. void Remote_Init(void)                              
  4. {  

  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         NVIC_InitTypeDef NVIC_InitStructure;
  7.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  8.         TIM_ICInitTypeDef  TIM_ICInitStructure;  

  9.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  10.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);       

  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                                 //PA1 输入
  12.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;                 //上拉输入
  13.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.         GPIO_SetBits(GPIOA,GPIO_Pin_1);        //初始化GPIOA1
  15.        
  16.                                                   
  17.         TIM_TimeBaseStructure.TIM_Period = 10000; //设定计数器自动重装值 最大10ms溢出  
  18.         TIM_TimeBaseStructure.TIM_Prescaler =(72-1);         //预分频器,1M的计数频率,1us加1.          
  19.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  20.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

  21.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx

  22.   TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;  // 选择输入端 IC2映射到TI2上
  23.   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;        //上升沿捕获
  24.   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  25.   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;         //配置输入分频,不分频
  26.   TIM_ICInitStructure.TIM_ICFilter = 0x03;//IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波
  27.   TIM_ICInit(TIM2, &TIM_ICInitStructure);//初始化定时器输入捕获通道

  28.   TIM_Cmd(TIM2,ENABLE );         //使能定时器2

  29.                                                
  30.         NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
  31.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级
  32.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  33.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  34.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器       

  35.         TIM_ITConfig( TIM2,TIM_IT_Update|TIM_IT_CC2,ENABLE);//允许更新中断 ,允许CC2IE捕获中断       
  36. }


  37. //遥控器接收状态
  38. //[7]:收到了引导码标志
  39. //[6]:得到了一个按键的所有信息
  40. //[5]:保留       
  41. //[4]:标记上升沿是否已经被捕获                                                                  
  42. //[3:0]:溢出计时器
  43. u8         RmtSta=0;                    
  44. u16 Dval;                //下降沿时计数器的值
  45. u32 RmtRec=0;        //红外接收到的数据                               
  46. u8  RmtCnt=0;        //按键按下的次数          
  47. //定时器5中断服务程序         
  48. void TIM2_IRQHandler(void)
  49. {                              
  50.   if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  51.         {
  52.                 if(RmtSta&0x80)//上次有数据被接收到了
  53.                 {       
  54.                         RmtSta&=~0X10;                                                //取消上升沿已经被捕获标记
  55.                         if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
  56.                         if((RmtSta&0X0F)<14)RmtSta++;
  57.                         else
  58.                         {
  59.                                 RmtSta&=~(1<<7);//清空引导标识
  60.                                 RmtSta&=0XF0;        //清空计数器       
  61.                         }                                                                   
  62.                 }                                                            
  63.         }
  64.         if(TIM_GetITStatus(TIM2,TIM_IT_CC2)!=RESET)
  65.         {          
  66.                 if(RDATA)//上升沿捕获
  67.                 {

  68.                         TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Falling);                //CC2P=1 设置为下降沿捕获                               
  69.             TIM_SetCounter(TIM2,0);                   //清空定时器值
  70.                         RmtSta|=0X10;                                        //标记上升沿已经被捕获
  71.                 }else //下降沿捕获
  72.                 {                       
  73.                         Dval=TIM_GetCapture2(TIM2);//读取CCR2也可以清CC2IF标志位
  74.                         TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC2P=0        设置为上升沿捕获
  75.                        
  76.                         if(RmtSta&0X10)                                        //完成一次高电平捕获
  77.                         {
  78.                                 if(RmtSta&0X80)//接收到了引导码
  79.                                 {
  80.                                        
  81.                                         if(Dval>300&&Dval<800)                        //560为标准值,560us
  82.                                         {
  83.                                                 RmtRec<<=1;        //左移一位.
  84.                                                 RmtRec|=0;        //接收到0          
  85.                                         }else if(Dval>1400&&Dval<1800)        //1680为标准值,1680us
  86.                                         {
  87.                                                 RmtRec<<=1;        //左移一位.
  88.                                                 RmtRec|=1;        //接收到1
  89.                                         }else if(Dval>2200&&Dval<2600)        //得到按键键值增加的信息 2500为标准值2.5ms
  90.                                         {
  91.                                                 RmtCnt++;                 //按键次数增加1次
  92.                                                 RmtSta&=0XF0;        //清空计时器               
  93.                                         }
  94.                                 }else if(Dval>4200&&Dval<4700)                //4500为标准值4.5ms
  95.                                 {
  96.                                         RmtSta|=1<<7;        //标记成功接收到了引导码
  97.                                         RmtCnt=0;                //清除按键次数计数器
  98.                                 }                                                 
  99.                         }
  100.                         RmtSta&=~(1<<4);
  101.                 }                                                                                                            
  102.         }
  103. TIM_ClearFlag(TIM2,TIM_IT_Update|TIM_IT_CC2);            
  104. }

  105. //处理红外键盘
  106. //返回值:
  107. //         0,没有任何按键按下
  108. //其他,按下的按键键值.
  109. u8 Remote_Scan(void)
  110. {        
  111.         u8 sta=0;      
  112.   u8 t1,t2;  
  113.         if(RmtSta&(1<<6))//得到一个按键的所有信息了
  114.         {
  115.             t1=RmtRec>>24;                        //得到地址码
  116.             t2=(RmtRec>>16)&0xff;        //得到地址反码
  117.             if((t1==(u8)~t2)&&t1==REMOTE_ID)//检验遥控识别码(ID)及地址
  118.             {
  119.                 t1=RmtRec>>8;
  120.                 t2=RmtRec;        
  121.                 if(t1==(u8)~t2)sta=t1;//键值正确         
  122.                         }   
  123.                         if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
  124.                         {
  125.                                 RmtSta&=~(1<<6);//清除接收到有效按键标识
  126.                                 RmtCnt=0;                //清除按键次数计数器
  127.                         }
  128.                         RmtSta&=~(1<<6);//清除接收到有效按键标识       
  129.         }
  130.        
  131.   return sta;
  132. }
复制代码

所有资料51hei提供下载:
基础功能_RTC-修改-定时器.rar (336.2 KB, 下载次数: 22)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表