|
這兩天閑暇沒事,用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
}
}
}
|
|