找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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)


评分

参与人数 1黑币 +30 收起 理由
gvin + 30 绝世好帖!

查看全部评分

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

使用道具 举报

沙发
ID:1 发表于 2018-8-29 17:10 | 只看该作者
补全原理图或者详细说明一下电路连接即可获得100+黑币
回复

使用道具 举报

板凳
ID:267330 发表于 2018-9-14 09:03 | 只看该作者
学习学习
回复

使用道具 举报

地板
ID:393539 发表于 2018-9-14 14:21 | 只看该作者
mark  学习
回复

使用道具 举报

5#
ID:306028 发表于 2018-9-14 17:37 | 只看该作者
nice, 学习一波
回复

使用道具 举报

6#
ID:183432 发表于 2018-9-20 15:37 | 只看该作者
不错不错
回复

使用道具 举报

7#
ID:33544 发表于 2018-9-20 16:58 | 只看该作者
不错不错学习了
回复

使用道具 举报

8#
ID:425297 发表于 2019-6-2 15:20 | 只看该作者
膜拜大佬
回复

使用道具 举报

9#
ID:496408 发表于 2019-6-11 23:38 | 只看该作者
看标题觉得很厉害,下载之后发现没有protues接线也没原理图,确实不知道怎么拿来用,期待大佬补上原理图或者protues接线图
回复

使用道具 举报

10#
ID:261930 发表于 2019-6-12 08:03 | 只看该作者
好帖谢谢分享。
回复

使用道具 举报

11#
ID:560549 发表于 2019-6-12 08:49 | 只看该作者
mark !
回复

使用道具 举报

12#
ID:445069 发表于 2019-6-21 10:08 | 只看该作者
好全面的参考代码。在懂得原理的情况下,可以借鉴。
回复

使用道具 举报

13#
ID:392473 发表于 2019-6-22 12:59 | 只看该作者
感谢楼主,努力学习中!
回复

使用道具 举报

14#
ID:473159 发表于 2019-6-24 07:02 | 只看该作者
没实际意义,网上原子的免费例程就是这些东东,这也是楼主提供不了单一电路图的原因
回复

使用道具 举报

15#
ID:489682 发表于 2019-6-24 09:22 | 只看该作者
如楼主真想帮助大家就发完整一些的资料。单片机开发是软硬件紧密结合的,光有软件不够
回复

使用道具 举报

16#
ID:384522 发表于 2019-8-19 18:47 | 只看该作者
内容不全?
回复

使用道具 举报

17#
ID:58110 发表于 2020-6-18 08:04 | 只看该作者
这个附件净坑人
点击下载,弹出下载提示,等待,没有下载文件

刷新页面,依然没有下载
再点下载,再扣黑B,扣了我N次,结果还没有下载下来
回复

使用道具 举报

18#
ID:310120 发表于 2020-6-19 14:45 | 只看该作者
感谢分享,学习了
回复

使用道具 举报

19#
ID:545054 发表于 2020-6-19 18:01 | 只看该作者
太棒了,谢谢楼主
回复

使用道具 举报

20#
ID:784555 发表于 2020-6-19 22:44 | 只看该作者
谢谢分享
回复

使用道具 举报

21#
ID:780228 发表于 2020-6-20 18:37 | 只看该作者
有没有proteus仿真
回复

使用道具 举报

22#
ID:147215 发表于 2020-6-21 10:38 | 只看该作者
谢谢分享!,,,,
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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