找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STM32 USB校时RTC时钟

[复制链接]
跳转到指定楼层
楼主
ID:80436 发表于 2015-5-21 16:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式



这两天闲暇没事,用STM32写了个校时时钟的小程序。基本功能:手动校时,usb校时(可设定闹钟),掉电保存数据。自己配套了个校时上位机,如图:截取电脑实时时间,并设定闹钟时间,再由串口通讯传给STM32.

使用到的STM32资源:定时器2作数码管显示实时扫描,USART1用来校时,PWR,BKP,作掉电数据保存,RTC秒中断作为时钟时基。
中断优先级概述:1级优先:串口中断 2级优先:秒中断 3级优先:定时器2     PS:波特率默认115200
以下是代码:
——————————————————————————

/*WRITER:YQ
#include "stm32f10x.h"
#define PORTA GPIOA->ODR //定义PORTA指向GPIOA的数据寄存器
#define PORTD GPIOD->ODR //定义PORTC指向GPIOC的数据寄存器
#define PORTC GPIOC->ODR
#define key1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)   //定义按键  key1 切换键
#define key2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)   // key2 退出键
#define key3 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)   // key3 确定键
#define key4 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)   // key4 闹钟键
const u8 table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 Mode,nude;
int wan,wan1,qian,bai,shi,ge,time,i,butter,buzzer;
USART_InitTypeDef USART_InitStructure;
uint8_t TxBuf[13];
uint8_t RxBuf[13];
uint8_t num1;
int newtime,Alarm;
/**********************************************************************
* 名    称:GPIO_Configuration()
* 功    能:配置输入输出
* 入口参数:
* 出口参数:
-----------------------------------------------------------------------
* 说明:使用库函数,配置IO口
***********************************************************************/
void GPIO_Configuration()
{
  GPIO_InitTypeDef GPIO_InitStructure;
SystemInit();   
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 |RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
                         RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;  //D1 D2
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);      

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;   //D3,D4   
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          //USART1 TX
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);      //A端口
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;          //USART1 RX
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //复用开漏输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);           //A端口
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;  //D1 D2
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2 | GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;   
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}
void RTC_Configuration() //RTC初始化
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);  //开备份寄存器和电源管理时钟
BKP_DeInit(); //备份寄存器缺省值填入
PWR_BackupAccessCmd(ENABLE);  //使能RTC和备份寄存器的访问
RCC_LSEConfig(RCC_LSE_ON);    //使能LSE晶振
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//等待LSE晶振就绪
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);    //把LSE晶振作为RTC的时钟源
RCC_RTCCLKCmd(ENABLE);   //使能RTC时钟
   
RTC_WaitForSynchro();
RTC_WaitForLastTask();    //等待最近一次写操作完成
RTC_ITConfig(RTC_IT_SEC,ENABLE);//RTC秒中断使能
RTC_WaitForLastTask();
   RTC_SetCounter(newtime);  //更新时钟
RTC_WaitForLastTask();   //等待最近一次写操作完成
RTC_SetPrescaler(32767);  //
RTC_WaitForLastTask();
RTC_SetAlarm(Alarm);
   RTC_WaitForLastTask();
}
void RTC_Configuration1() //RTC初始化
{

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
   PWR_BackupAccessCmd(ENABLE);
   RCC_LSEConfig(RCC_LSE_ON);
   RCC_GetFlagStatus(RCC_FLAG_LSIRDY);
   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
   RCC_RTCCLKCmd(ENABLE);
   RTC_WaitForSynchro();
   RTC_WaitForLastTask();
   RTC_ITConfig(RTC_IT_SEC,ENABLE);
   RTC_WaitForLastTask();
   RTC_SetPrescaler(32767);
   RTC_WaitForLastTask();
   RTC_SetAlarm(3600);
   RTC_WaitForLastTask();
   RTC_ITConfig(RTC_IT_ALR,ENABLE);
   RTC_WaitForLastTask();
}
void TIM2_Configuration() //定时器初始化
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); // 使能定时器时钟
TIM_TimeBaseStructure.TIM_Period = 9;    // 自动重载值
TIM_TimeBaseStructure.TIM_Prescaler = 7199;   // 时钟预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //采样分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);  //
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);    //使能定时器2中断
TIM_Cmd(TIM2,ENABLE);         //使能定时器2这个外设

}
void USART_Configuration()
{

USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  /* Configure USART1 */
  USART_Init(USART1, &USART_InitStructure);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
   USART_Cmd(USART1, ENABLE);
}
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);   // 抢占式优先级别
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//指定中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;// 指定响应优先级别1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);   // 抢占式优先级别
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//指定中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 指定响应优先级别1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;// 指定响应优先级别1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
void Delay(__IO uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}
void GPIOYB(unsigned int t)
{
    unsigned int c;
for(c=0;c<t;c++)
{
    GPIO_SetBits(GPIOE, GPIO_Pin_0);//                    
    Delay(0x1AFF);
    GPIO_ResetBits(GPIOE, GPIO_Pin_0);  
    Delay(0x1AFF);
}
}

/**********************************************************************
* 名    称:main()
* 功    能:主函数
* 入口参数:
* 出口参数:
-----------------------------------------------------------------------
* 说明:
***********************************************************************/
int main (void)
{
    GPIO_Configuration();
    NVIC_Configuration();
TIM2_Configuration();
    RTC_Configuration1();
    USART_Configuration();
while(1)
{
   if(key1==0)
  {
  while(!key1);
   
     Mode=1;   //模式切换,Mode=1为校时模式 Mode=0为正常模式  
  while(key2)
  {
   if(key1==0)
  {
  while(!key1);
  butter++;
  if(butter>3)
  butter=0;
  }
  switch(butter)
  {
   case 0:  
     if(key3==0)
     {
     while(!key3);
     bai++;
     if(bai>9)
     bai=0;
     }  
     break;
   
   case 1:  
     if(key3==0)
     {
     while(!key3);
     qian++;
     if(qian>5)
     qian=0;
     }   
     break;
     
   case 2:   
     if(key3==0)
     {
     while(!key3);
     wan++;
     if(wan>9)
     wan=0;
     }   
     break;
   case 3:
   
     if(key3==0)
     {
     while(!key3);
     wan1++;
     if(wan1>2)
     wan1=0;
     }   
     break;
     
   default:     break;
  }
  }
  newtime=ge+shi*10+(bai+qian*10)*60+(wan+wan1*10)*3600; //计算出重新设定的时间值
    RCC_BackupResetCmd(ENABLE);  //清除备份域的数据
  RTC_Configuration(); //配置RTC  
  Mode=0;
  }
  
   

   
  
   
if (BKP_ReadBackupRegister(BKP_DR1) != 0xf312)  //检测特殊值,如果不是证明是第一次上电
{
    RTC_Configuration(); //配置RTC
    BKP_WriteBackupRegister(BKP_DR1, 0xf312); //写入特殊值,下次不再配置RTC

}

   
      

   
}
}
void TIM2_IRQHandler(void)  //用定时器1ms进行数码管的动态扫描
{           
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
TIM_ClearFlag(TIM2,TIM_IT_Update); //清定时器中断标志
if(Mode==0)
{
time=RTC_GetCounter();
ge=time%3600%60%10;
shi=time%3600%60/10;
bai=time%3600/60%10;
qian=time%3600/60/10;
wan=time/3600%10;
wan1=time/3600/10;
}
if(wan1==2&&wan==4)
{
wan1=0;
wan=0;
qian=0;
bai=0;
shi=0;
ge=0;
}
switch(i)
{
case 0: PORTD=0;PORTA=table[wan1];
      PORTD|=(1<<7); break;
case 1: PORTD=0;PORTA=table[wan];
   PORTD|=(1<<8); break;
case 2: PORTD=0;PORTA=table[qian];
   PORTD|=(1<<10); break;
case 3: PORTD=0;PORTA=table[bai];
   PORTD|=(1<<9); break;
default: break;
}

  i++;
  if(i==4)
  i=0;
}

}
void RTC_IRQHandler(void)
{  
  if(RTC_GetITStatus(RTC_IT_SEC) != RESET)  
  {     
    PORTC^=(1<<7);
   RTC_ClearITPendingBit(RTC_IT_SEC);
    RTC_WaitForLastTask();  
  
  }
  
  if(RTC_GetITStatus(RTC_IT_ALR) != RESET)  
  {  
   for(buzzer=0;buzzer<50;buzzer++)
{  
    GPIOYB(100);
Delay(0xfffff);
}
    RTC_ClearITPendingBit(RTC_IT_ALR);
    RTC_WaitForLastTask();  
  
  }
}
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {     
       RxBuf[num1++]=USART_ReceiveData(USART1);
    if(num1==12)
    {
    for(num1=0;num1<12;num1++)
    TxBuf[num1]=RxBuf[num1]-48;           
    num1=0;
    }
     if(num1==0)
    {
  newtime=TxBuf[5]+TxBuf[4]*10+(TxBuf[3]+TxBuf[2]*10)*60+(TxBuf[1]+TxBuf[0]*10)*3600; //计算出重新设定的时间值
  Alarm=TxBuf[11]+TxBuf[10]*10+(TxBuf[9]+TxBuf[8]*10)*60+(TxBuf[7]+TxBuf[6]*10)*3600;
    RCC_BackupResetCmd(ENABLE);  //清除备份域的数据
  RTC_Configuration(); //配置RTC
    }

  
   
   
   
}   
}



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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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