基于STM32F1实现秒表及万年历功能【寄存器版】

    xiaoxiao2021-04-15  399

    源码地址:GitHub源码

    前言

    实验基于STM32F103开发板,Keil4。这里仅作为记录实验过程,代码上传至GitHub,尽量优化代码,本人小白,有不当之处请指教

    实验目标

    1.实现秒表功能: 分、秒和毫秒计时 按K1键开始计时 按K2键计录一个时间,再按继续记录下一时间,共可记录五个时间 按K3键停止计时 停止后,K2,K3可以前后翻看五个时间

    2.实现万能历功能 能显示年、月、日 或 时、分、秒,通过按键切换显示内容 按键可以调整和设置日期和时间

    功能分析

    1、先进行系统时钟、延时函数、LED的初始化,然后配置按键外部中断,通过两个按键外部中断实现计时及终止计时功能。 时间的记录则用一个二维数组分别记录时、分、秒,根据题目要求显示。 2、万年历功能主要是通过三个按键KEY3控制切换,KEY2和KEY1分别对年、月、日、时、分、秒或加或减操作,需要对闰年进行判断。减操作仅影响当前操作的数,不影响其他的。如 day–,当month==0,执行month=12。【这里尚未对当前操作位做特殊操作,比如年份闪烁表示正在对其进行操作,之后补充】

    关键代码

    秒表

    /****************普通按键初始化函数******************** * 通用定时器中断初始化 * 这里时钟选择为APB1的2倍,而APB1为36M * arr:自动重装值。 * psc:时钟预分频数 * 这里使用的是定时器3! ******************************************************/ void TimerxInit(u16 arr, u16 psc) { RCC->APB1ENR |= 1<<1; //TIM3时钟使能 TIM3->ARR = arr; //设定计数器自动重装值,10为1ms TIM3->PSC = psc; //预分频器7200,得到10KHZ的计数时钟 TIM3->DIER |= 1<<0; //允许更新中断 TIM3->CR1 |= 0x01; //使能定时器3 MY_NVIC_Init(1, 3, TIM3_IRQChannel, 2); //抢占1,子优先级3,组2 RCC->APB2ENR|=1<<4; //使能PORTC时钟 GPIOC->CRL&=0XFFFFF000;//PC0-2设置成输入 GPIOC->CRL|=0X00000888; Ex_NVIC_Config(GPIO_C,0,FTIR);//下降沿触发 Ex_NVIC_Config(GPIO_C,1,FTIR);//下降沿触发 Ex_NVIC_Config(GPIO_C,2,FTIR);//下降沿触发 MY_NVIC_Init(0,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2 MY_NVIC_Init(2,2,EXTI2_IRQChannel,2);//抢占2,子优先级1,组2 } void EXTI2_IRQHandler(void){ delay_ms(10);//消抖 if(key1==0){ //按键1 key1=1; second = 0; minute = 0; hour = 0; while(1){ DisplayDigitalClock(hour, minute, second); delay_ms(10);//消抖 t=KeyScan(); if(t==2){ timeRec[0][count] = hour; timeRec[1][count] = minute; timeRec[2][count] = second; count++; // 记录时间个数+1 actCount = count-1; //actCount表示实际记录的时间个数 EXTI->PR=1<<1; //清除LINE1上的中断标志位 } } } EXTI->PR=1<<2; //清除LINE2上的中断标志位 } void EXTI0_IRQHandler(void){ delay_ms(10);//消抖 if(key3==0){ //按键3 while(1){ DisplayDigitalClock(hour, minute, second); //计时停在当前计时时间 t=KeyScan(); if(t==2){ //先翻看前一个记录时间 while(1){ DisplayDigitalClock(timeRec[0][count], timeRec[1][count], timeRec[2][count]); if(t==2){ if(count>0){ //判断记录下限 --count; } EXTI->PR=1<<1;//清除LINE1上的中断标志位 } if(t==3){ if(count<actCount){ //判断记录上限 ++count; } EXTI->PR=1<<0;//清除LINE0上的中断标志位 } t=KeyScan(); } } } } EXTI->PR=1<<0; //清除LINE0上的中断标志位 }

    万年历

    /// 注释部分为功能2【万年历】部分的代码 // 判断是否为闰年 int IsLeapYear(int year){ if((year%4 == 0 && year%100 != 0) || year %400 == 0){ return 1; } return 0; } // 对day++的合法性做判断 void JudgeDay(){ int i; for(i=0; i<12; i++){ if(i==0||i==2||i==4||i==6||i==7||i==9||i==11){ //31天的月份 if((day>31)&&(curMonth==i)){ day=1; curMonth++; if(curMonth==13){ curMonth=1; year++; } } }else if(i==1){ if(day>28&&(curMonth==2)){ //2月 if(IsLeapYear(year)==0){ //且不是闰年 day=1; curMonth=3; } } }else { // 30的月份 if((day>30)&&(curMonth==i+1)){ day=1; curMonth++; } } } } // 对day--的合法性的操作 void JudgeDay2(){ int i; if(day==0){ for(i=0; i<12; i++){ if(i==0||i==2||i==4||i==6||i==7||i==9||i==11){ day=31; }else if(i==1){ if(IsLeapYear(year)==1){ day=29; }else { day=28; } }else { day=30; } } } } void TIM3_IRQHandler( void ) { if( TIM3->SR & 0x0001) //溢出中断 { second++; if( second>59 ) { second = 0; minute++; if( minute>59 ) { minute = 0; hour++; if( hour>23 ) { hour = 0; day++; JudgeDay(); } } } } TIM3->SR &= ~(1<<0); //清除中断标志位 } // 处理按键3切换时间和日期的终端函数 void EXTI0_IRQHandler(void){ u8 t , cnt = 0; delay_ms(10);//消抖 if(key3==0){ //按键3 while(1){ t = KeyScan(); if(t==3){ cnt++; if(cnt==7) break; } if(cnt>3) DisplayDigitalClock2(); else DisplayCalendar(year, curMonth, day); if(t==2){// 加操作 if(cnt==1) year++; else if(cnt==2){ curMonth++; if(curMonth==13){ curMonth=1; year++; } }else if(cnt==3){ day++; JudgeDay(); }else if(cnt>3){ if(cnt==4){ hour++; if( hour>23 ){ hour = 0; day++; JudgeDay(); } }else if(cnt==5){ minute++; if( minute>59 ){ minute = 0; hour++; if( hour>23 ){ hour = 0; day++; JudgeDay(); } } }else if(cnt==6){ second++; if( second>59 ){ second = 0; minute++; if( minute>59 ) { minute = 0; hour++; if( hour>23 ){ hour = 0; day++; JudgeDay(); } } } } } }else if(t==1){// 减操作 if(cnt==1) year--; else if(cnt==2) { curMonth--; if(curMonth==0) {curMonth=12;year--;} }else if(cnt==3){ day--;JudgeDay2(); }else if(cnt>3){ if(cnt==4){ if( hour==0 ){hour=23; } else { hour--;} }else if(cnt==5){ if( minute==0 )minute=59; else minute--; }else if(cnt==6){ if(second==0){ second=59;} else { second--; } } } } } } EXTI->PR=1<<0; //清除LINE0上的中断标志位 }

    最新回复(0)