找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3412|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM32 USB校時RTC時鐘

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:80436 發(fā)表于 2015-5-21 16:46 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式



這兩天閑暇沒事,用STM32寫了個校時時鐘的小程序;竟δ埽菏謩有r,usb校時(可設(shè)定鬧鐘),掉電保存數(shù)據(jù)。自己配套了個校時上位機(jī),如圖:截取電腦實(shí)時時間,并設(shè)定鬧鐘時間,再由串口通訊傳給STM32.

使用到的STM32資源:定時器2作數(shù)碼管顯示實(shí)時掃描,USART1用來校時,PWR,BKP,作掉電數(shù)據(jù)保存,RTC秒中斷作為時鐘時基。
中斷優(yōu)先級概述:1級優(yōu)先:串口中斷 2級優(yōu)先:秒中斷 3級優(yōu)先:定時器2     PS:波特率默認(rèn)115200
以下是代碼:
——————————————————————————

/*WRITER:YQ
#include "stm32f10x.h"
#define PORTA GPIOA->ODR //定義PORTA指向GPIOA的數(shù)據(jù)寄存器
#define PORTD GPIOD->ODR //定義PORTC指向GPIOC的數(shù)據(jù)寄存器
#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()
* 功    能:配置輸入輸出
* 入口參數(shù):
* 出口參數(shù):
-----------------------------------------------------------------------
* 說明:使用庫函數(shù),配置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;    //復(fù)用推挽輸出
  GPIO_Init(GPIOA, &GPIO_InitStructure);      //A端口
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;          //USART1 RX
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //復(fù)用開漏輸入
  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;   // 時鐘預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //采樣分頻
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);  //
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);    //使能定時器2中斷
TIM_Cmd(TIM2,ENABLE);         //使能定時器2這個外設(shè)

}
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);   // 搶占式優(yōu)先級別
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//指定中斷源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;// 指定響應(yīng)優(yōu)先級別1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);   // 搶占式優(yōu)先級別
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//指定中斷源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 指定響應(yīng)優(yōu)先級別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;// 指定響應(yīng)優(yōu)先級別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()
* 功    能:主函數(shù)
* 入口參數(shù):
* 出口參數(shù):
-----------------------------------------------------------------------
* 說明:
***********************************************************************/
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; //計(jì)算出重新設(shè)定的時間值
    RCC_BackupResetCmd(ENABLE);  //清除備份域的數(shù)據(jù)
  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進(jìn)行數(shù)碼管的動態(tài)掃描
{           
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
TIM_ClearFlag(TIM2,TIM_IT_Update); //清定時器中斷標(biāo)志
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; //計(jì)算出重新設(shè)定的時間值
  Alarm=TxBuf[11]+TxBuf[10]*10+(TxBuf[9]+TxBuf[8]*10)*60+(TxBuf[7]+TxBuf[6]*10)*3600;
    RCC_BackupResetCmd(ENABLE);  //清除備份域的數(shù)據(jù)
  RTC_Configuration(); //配置RTC
    }

  
   
   
   
}   
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表