标题: STM32单片机程序:温度、万年历、PWM、输入捕捉高电平、ADC、DAC、EEPROM、IIC [打印本页]

作者: handily    时间: 2018-8-29 09:47
标题: STM32单片机程序:温度、万年历、PWM、输入捕捉高电平、ADC、DAC、EEPROM、IIC
STM32单片机程序:温度、万年历、PWM、输入捕捉高电平、ADC、DAC、EEPROM、IIC



单片机源程序如下:
  1. #include "SysTick.h"
  2. #include "public.h"
  3.                     

  4.           
  5. _calendar calendar;//时钟结构体

  6. static void RTC_NVIC_Config(void)
  7. {       
  8.         NVIC_InitTypeDef NVIC_InitStructure;
  9.         NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;                //RTC全局中断
  10.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;        //先占优先级1位,从优先级3位
  11.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //先占优先级0位,从优先级4位
  12.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能该通道中断
  13.         NVIC_Init(&NVIC_InitStructure);                //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  14. }


  15. /*******************************************************************************
  16. * 函 数 名         : RTC_Init
  17. * 函数功能                   : RTC初始化
  18. * 输    入         : 无
  19. * 输    出         : 0,初始化成功
  20.                                  1,LSE开启失败
  21. *******************************************************************************/
  22. u8 RTC_Init(void)
  23. {
  24.         //检查是不是第一次配置时钟
  25.         u8 temp=0;
  26.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟   
  27.         PWR_BackupAccessCmd(ENABLE);        //使能后备寄存器访问  
  28.         if (BKP_ReadBackupRegister(BKP_DR1) != 0xA0A0)                //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
  29.         {                        
  30.                 //????RTC
  31.                 //RTC_Configuration();                
  32.                 BKP_DeInit();        //复位备份区域        
  33.                 RCC_LSEConfig(RCC_LSE_ON);        //设置外部低速晶振(LSE),使用外设低速晶振
  34.                 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)        //检查指定的RCC标志位设置与否,等待低速晶振就绪
  35.                 {
  36.                         temp++;
  37.                         delay_ms(10);
  38.                 }
  39.                 if(temp>=250)return 1;//初始化时钟失败,晶振有问题            
  40.                 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);                //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
  41.                 RCC_RTCCLKCmd(ENABLE);        //使能RTC时钟  
  42.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  43.                 RTC_WaitForSynchro();                //等待RTC寄存器同步  
  44.                 RTC_ITConfig(RTC_IT_SEC, ENABLE);                //使能RTC秒中断
  45.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  46.                 RTC_EnterConfigMode();// 允许配置       
  47.                 RTC_SetPrescaler(32767); //设置RTC预分频的值
  48.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  49.                 RTC_Set(2018,8,20,14,39,55);  //设置时间       
  50.                 RTC_ExitConfigMode(); //退出配置模式  
  51.                 BKP_WriteBackupRegister(BKP_DR1, 0XA0A0);        //向指定的后备寄存器中写入用户程序数据
  52.         }
  53.         else//系统继续计时
  54.         {
  55.                 RTC_WaitForSynchro();        //等待最近一次对RTC寄存器的写操作完成
  56.                 RTC_ITConfig(RTC_IT_SEC, ENABLE);        //使能RTC秒中断
  57.                 RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成
  58.         }
  59.         RTC_NVIC_Config();//RCT中断分组设置                                                         
  60.         RTC_Get();//更新时间       
  61.         return 0; //ok

  62. }                                                     
  63. //RTC时钟中断
  64. //每秒触发一次  
  65. //extern u16 tcnt;
  66. int jishu;
  67. void RTC_IRQHandler(void)
  68. {                 
  69.         if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断
  70.         {                                                       
  71.                 RTC_Get();//更新时间  
  72.                 printf("RTC Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间       
  73.                 LCD_ShowFontHZ(82,270,"日期");
  74.                 LCD_ShowxNum(0,300,calendar.w_year,2,24,0);               
  75.                 LCD_ShowString(24,300,tftlcd_data.width,tftlcd_data.height,24,"-");
  76.                 LCD_ShowxNum(36,300,calendar.w_month,2,24,0);       
  77.                 LCD_ShowString(60,300,tftlcd_data.width,tftlcd_data.height,24,"-");
  78.                 LCD_ShowxNum(72,300,calendar.w_date,2,24,0);       
  79.                 //小时
  80.                 LCD_ShowxNum(146,300,calendar.hour,2,24,0);       
  81.                 LCD_ShowString(170,300,tftlcd_data.width,tftlcd_data.height,24,":");
  82.                 LCD_ShowxNum(182,300,calendar.min,2,24,0);       
  83.                 LCD_ShowString(206,300,tftlcd_data.width,tftlcd_data.height,24,":");
  84.                 LCD_ShowxNum(218,300,calendar.sec,2,24,0);       
  85.                 //星期
  86.                 LCD_ShowFontHZ(70,340,"星期");
  87.                 LCD_ShowNum(135,343,calendar.week,2,24);       
  88.                
  89.                 //原定时器1s计数
  90.                 jishu++;
  91.                 LCD_ShowxNum(110,120,jishu,5,24,0);
  92.                 LCD_ShowString(50,120,tftlcd_data.width,tftlcd_data.height,24,"time:");
  93.                 LCD_ShowString(180,120,tftlcd_data.width,tftlcd_data.height,24,"s");
  94.                
  95.                
  96.         }
  97.         if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断
  98.         {
  99.                 RTC_ClearITPendingBit(RTC_IT_ALR);                //清闹钟中断                 
  100.                 RTC_Get();                                //更新时间   
  101.                 printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间       
  102.                
  103.           }                
  104.                        
  105.         RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);                //清闹钟中断
  106.         RTC_WaitForLastTask();                                                                                           
  107. }
  108. //判断是否是闰年函数
  109. //月份   1  2  3  4  5  6  7  8  9  10 11 12
  110. //闰年   31 29 31 30 31 30 31 31 30 31 30 31
  111. //非闰年 31 28 31 30 31 30 31 31 30 31 30 31
  112. //输入:年份
  113. //输出:该年份是不是闰年.1,是.0,不是
  114. u8 Is_Leap_Year(u16 year)
  115. {                          
  116.         if(year%4==0) //必须能被4整除
  117.         {
  118.                 if(year%100==0)
  119.                 {
  120.                         if(year%400==0)return 1;//如果以00结尾,还要能被400整除           
  121.                         else return 0;   
  122.                 }else return 1;   
  123.         }else return 0;       
  124. }                                   


  125. //月份数据表                                                                                         
  126. u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表          
  127. //平年的月份日期表
  128. const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};

  129. /*******************************************************************************
  130. * 函 数 名         : RTC_Set
  131. * 函数功能                   : RTC设置日期时间函数(以1970年1月1日为基准,把输入的时钟转换为秒钟)
  132.                                                 1970~2099年为合法年份
  133. * 输    入         : syear:年  smon:月  sday:日
  134.                                         hour:时   min:分         sec:秒                       
  135. * 输    出         : 0,成功
  136.                                  1,失败
  137. *******************************************************************************/
  138. u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  139. {
  140.         u16 t;
  141.         u32 seccount=0;
  142.         if(syear<1970||syear>2099)return 1;          
  143.         for(t=1970;t<syear;t++)        //把所有年份的秒钟相加
  144.         {
  145.                 if(Is_Leap_Year(t)) seccount+=31622400;//闰年的秒钟数
  146.                 else seccount+=31536000;                          //平年的秒钟数
  147.         }
  148.         smon-=1;
  149.         for(t=0;t<smon;t++)           //把前面月份的秒钟数相加
  150.         {
  151.                 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
  152.                 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数          
  153.         }
  154.         seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
  155.         seccount+=(u32)hour*3600;//小时秒钟数
  156.     seccount+=(u32)min*60;         //分钟秒钟数
  157.         seccount+=sec;//最后的秒钟加上去

  158.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟  
  159.         PWR_BackupAccessCmd(ENABLE);        //使能RTC和后备寄存器访问
  160.         RTC_SetCounter(seccount);        //设置RTC计数器的值

  161.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成         
  162.         return 0;            
  163. }

  164. //初始化闹钟                  
  165. //以1970年1月1日为基准
  166. //1970~2099年为合法年份
  167. //syear,smon,sday,hour,min,sec:闹钟的年月日时分秒   
  168. //返回值:0,成功;其他:错误代码.
  169. u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
  170. {
  171.         u16 t;
  172.         u32 seccount=0;
  173.         if(syear<1970||syear>2099)return 1;          
  174.         for(t=1970;t<syear;t++)        //把所有年份的秒钟相加
  175.         {
  176.                 if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
  177.                 else seccount+=31536000;                          //平年的秒钟数
  178.         }
  179.         smon-=1;
  180.         for(t=0;t<smon;t++)           //把前面月份的秒钟数相加
  181.         {
  182.                 seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
  183.                 if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数          
  184.         }
  185.         seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
  186.         seccount+=(u32)hour*3600;//小时秒钟数
  187.     seccount+=(u32)min*60;         //分钟秒钟数
  188.         seccount+=sec;//最后的秒钟加上去                             
  189.         //设置时钟
  190.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);        //使能PWR和BKP外设时钟   
  191.         PWR_BackupAccessCmd(ENABLE);        //使能后备寄存器访问  
  192.         //上面三步是必须的!
  193.        
  194.         RTC_SetAlarm(seccount);

  195.         RTC_WaitForLastTask();        //等待最近一次对RTC寄存器的写操作完成         
  196.        
  197.         return 0;            
  198. }


  199. //得到当前的时间
  200. //返回值:0,成功;其他:错误代码.
  201. u8 RTC_Get(void)
  202. {
  203.         static u16 daycnt=0;
  204.         u32 timecount=0;
  205.         u32 temp=0;
  206.         u16 temp1=0;          
  207.     timecount=RTC_GetCounter();         //得到计数器中的秒钟值
  208.         temp=timecount/86400;   //得到天数(秒钟数对应的)一天86400s
  209.         if(daycnt!=temp)//超过一天了
  210.         {          
  211.                 daycnt=temp;
  212.                 temp1=1970;        //从1970年开始
  213.                 while(temp>=365)
  214.                 {                                 
  215.                         if(Is_Leap_Year(temp1))//是闰年
  216.                         {
  217.                                 if(temp>=366)temp-=366;//闰年的秒钟数
  218.                                 else {temp1++;break;}  
  219.                         }
  220.                         else temp-=365;          //平年
  221.                         temp1++;  
  222.                 }   
  223.                 calendar.w_year=temp1;//得到年份
  224.                 temp1=0;
  225.                 while(temp>=28)//超过了一个月
  226.                 {
  227.                         if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
  228.                         {
  229.                                 if(temp>=29)temp-=29;//闰年的秒钟数
  230.                                 else break;
  231.                         }
  232.                         else
  233.                         {
  234.                                 if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
  235.                                 else break;
  236.                         }
  237.                         temp1++;  
  238.                 }
  239. ……………………

  240. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
8.20 DAC+ADC+定时器+温度+日期+输入捕捉+数码管+按键+TFT屏+蜂鸣器.rar (2.31 MB, 下载次数: 291)



作者: admin    时间: 2018-8-29 17:10
补全原理图或者详细说明一下电路连接即可获得100+黑币
作者: jiangkeqin_sy    时间: 2018-9-14 09:03
学习学习
作者: niqingqing    时间: 2018-9-14 14:21
mark  学习
作者: 13622983180    时间: 2018-9-14 17:37
nice, 学习一波
作者: 骑猪购物    时间: 2018-9-20 15:37
不错不错
作者: wis98    时间: 2018-9-20 16:58
不错不错学习了
作者: gvin    时间: 2019-6-2 15:20
膜拜大佬
作者: justablackcat    时间: 2019-6-11 23:38
看标题觉得很厉害,下载之后发现没有protues接线也没原理图,确实不知道怎么拿来用,期待大佬补上原理图或者protues接线图
作者: ccf_1989    时间: 2019-6-12 08:03
好帖谢谢分享。
作者: lczs    时间: 2019-6-12 08:49
mark !
作者: ontheroad    时间: 2019-6-21 10:08
好全面的参考代码。在懂得原理的情况下,可以借鉴。
作者: zgqmzx    时间: 2019-6-22 12:59
感谢楼主,努力学习中!
作者: yoxi    时间: 2019-6-24 07:02
没实际意义,网上原子的免费例程就是这些东东,这也是楼主提供不了单一电路图的原因
作者: hello_51hei    时间: 2019-6-24 09:22
如楼主真想帮助大家就发完整一些的资料。单片机开发是软硬件紧密结合的,光有软件不够
作者: H823603932    时间: 2019-8-19 18:47
内容不全?

作者: lyMarvin    时间: 2020-6-18 08:04
这个附件净坑人
点击下载,弹出下载提示,等待,没有下载文件

刷新页面,依然没有下载
再点下载,再扣黑B,扣了我N次,结果还没有下载下来
作者: nimisi    时间: 2020-6-19 14:45
感谢分享,学习了

作者: 妖精的尾号    时间: 2020-6-19 18:01
太棒了,谢谢楼主

作者: suying.    时间: 2020-6-19 22:44
谢谢分享
作者: zhuzhuzhuqi    时间: 2020-6-20 18:37
有没有proteus仿真
作者: onepcb    时间: 2020-6-21 10:38
谢谢分享!,,,,




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1