- void Xtl_init()
- {
- Sysctrl_XTLDriverCfg(SysctrlXtlAmp3, SysctrlXtalDriver3);
- Sysctrl_SetXTLStableTime(SysctrlXtlStableCycle4096);
- Sysctrl_ClkSourceEnable(SysctrlClkXTL,TRUE);
- Sysctrl_SysClkSwitch(SysctrlClkXTL);
- Flash_WaitCycle(FlashWaitCycle0);
- }
LCD和LED初始化方法和LCD显示数字方法省略,和之前测试用的相同,初始化按键的IO,开启按键下降沿中断
- void key_init(void)
- {
- stc_gpio_cfg_t stcGpioCfg;
- Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
- stcGpioCfg.enDir = GpioDirIn;
- stcGpioCfg.enDrv = GpioDrvL;
- stcGpioCfg.enPu = GpioPuDisable;
- stcGpioCfg.enPd = GpioPdDisable;
- Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg);
- Gpio_EnableIrq(STK_USER_PORT, STK_USER_PIN, GpioIrqFalling);
- EnableNvic(PORTA_IRQn, IrqLevel2, TRUE);
- }
按键中断处理,下降沿中断触发后开启LPTimer计时
- void PortA_IRQHandler(void)
- {
- if(TRUE == Gpio_GetIrqStatus(STK_USER_PORT, STK_USER_PIN))
- {
- Gpio_ClearIrq(STK_USER_PORT, STK_USER_PIN);
- if(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == FALSE)
- {
- Lptim_Cmd(M0P_LPTIMER0, TRUE);
- clock_key_clickcount += 1;
- if(clock_key_clickcount == 2)
- {
- key_double_clicked();//双击
- clock_key_clickcount = 0;
- }
- }
- }
- }
初始化LPTimer,设定触发时间为0.0625秒
- void lptimer_init()
- {
- stc_lptim_cfg_t stcLptCfg;
- DDL_ZERO_STRUCT(stcLptCfg);
- ///< 使能LPTIM0 外设时钟
- Sysctrl_ClkSourceEnable(SysctrlClkXTL,TRUE);
- Sysctrl_SetPeripheralGate(SysctrlPeripheralLpTim0, TRUE);
- stcLptCfg.enPrs = LptimPrsDiv256;
- stcLptCfg.enGate = LptimGateLow;
- stcLptCfg.enGatep = LptimGatePLow;
- stcLptCfg.enTcksel = LptimXtl;
- stcLptCfg.enTogen = LptimTogEnLow;
- stcLptCfg.enCt = LptimTimerFun;
- stcLptCfg.enMd = LptimMode2; //工作模式为模式2:自动重载16位计数器/定时器
- stcLptCfg.u16Arr = 0x10000 - 8; //预装载寄存器值
- Lptim_Init(M0P_LPTIMER0, &stcLptCfg);
- Lptim_ClrItStatus(M0P_LPTIMER0); //清除中断标志位
- Lptim_ConfIt(M0P_LPTIMER0, TRUE); //允许LPTIMER中断
- EnableNvic(LPTIM_0_1_IRQn, IrqLevel3, TRUE);
- }
在LPTimer中断中查询按键状态,当检测到按键松开时计时停止,通过计时长短判断是点击操作还是长按操作,按键松开后并过了双击检测时间后关闭LPTimer
- void LpTim0_IRQHandler(void)
- {
- if (TRUE == Lptim_GetItStatus(M0P_LPTIMER0))
- {
- Lptim_ClrItStatus(M0P_LPTIMER0);//清除LPTimer的中断标志位
- if(clock_lptimer_counter < 0xFF)
- clock_lptimer_counter += 1;
- if(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == FALSE)
- {
- if(clock_key_keepdowncount < 0xFF)
- clock_key_keepdowncount += 1;
- if(clock_key_keepdowncount == 16)
- {
- clock_key_clickcount = 0;
- key_long_pressed();//长按
- }
- }
- else
- {
- if(clock_lptimer_counter > 8)
- {
- if(clock_key_keepdowncount<16 && clock_key_clickcount == 1)
- {
- key_single_clicked();//单击
- }
- clock_key_clickcount = 0;
- clock_lptimer_counter = 0;
- Lptim_Cmd(M0P_LPTIMER0, FALSE);
- }
- clock_key_keepdowncount = 0;
- }
- }
- }
按键的单机双击长按处理
单击处理:闹钟响起时单击关闭响起状态,未进入设置模式时控制闹钟的开启与关闭,用第三个小数点显示闹钟开启状态,设置模式时增加数字
- void key_single_clicked()
- {
- uint8_t temp,tempmax;
- if(clock_alarmed)
- {
- Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
- clock_alarmed = 0;
- }
- else if(clock_settingmode == 0)
- {
- clock_alarmon = 1-clock_alarmon;
- Rtc_AlmIeCmd(clock_alarmon);
- lcdshowdot(3,clock_alarmon);
- }
- else
- {
- if(clock_settingtpos == 0)
- {
- temp = clock_hour&0xF0;
- if((clock_hour&0x0F)>3)
- tempmax = 0x10;
- else
- tempmax = 0x20;
- if(temp < tempmax)
- temp += 0x10;
- else
- temp = 0x00;
- clock_hour = temp|(clock_hour&0x0F);
- }
- else if(clock_settingtpos == 1)
- {
- temp = clock_hour&0x0F;
- if(temp<9)
- temp += 1;
- else
- temp = 0;
- if((clock_hour&0xF0)==0x20&&temp>3)
- clock_hour = temp;
- else
- clock_hour = temp|(clock_hour&0xF0);
- }
- else if(clock_settingtpos == 2)
- {
- temp = clock_minute&0xF0;
- if(temp<0x50)
- temp += 0x10;
- else
- temp = 0x00;
- clock_minute = temp|(clock_minute&0x0F);
- }
- else
- {
- temp = clock_minute&0x0F;
- if(temp<9)
- temp += 1;
- else
- temp = 0;
- clock_minute = temp|(clock_minute&0xF0);
- }
- if(clock_settingmode == 1)
- clock_time_cahnged = 1;
- clock_settinshownum = 0;
- show_setting_time();
- }
- }
双击处理:向后移动设置位
- void key_double_clicked()
- {
- if(clock_settingtpos < 3)
- clock_settingtpos += 1;
- else
- clock_settingtpos = 0;
- }
长按处理:在时间设置-闹钟设置-退出设置间切换,用第1和第2小数点显示当前设置的是时间还是闹钟
- void key_long_pressed()
- {
- stc_rtc_time_t readtime;
- stc_rtc_alarmtime_t alarmtime;
- if(clock_settingmode == 0)
- {
- Rtc_ReadDateTime(&readtime);
- clock_hour = readtime.u8Hour;
- clock_minute = readtime.u8Minute;
- clock_settingmode = 1;
- clock_settingtpos = 0;
- clock_time_cahnged = 0;
- lcdshowdot(0,1);
- lcdshowdot(1,1);
- }
- else if(clock_settingmode == 1)
- {
- if(clock_settingmode > 0)
- {
- Rtc_ReadDateTime(&readtime);
- readtime.u8Hour = clock_hour;
- readtime.u8Minute = clock_minute;
- readtime.u8Second = 0x00;
- Rtc_SetTime(&readtime);
- clock_showseconddot = 1;
- }
- Rtc_GetAlarmTime(&alarmtime);
- clock_hour = alarmtime.RtcAlarmHour;
- clock_minute = alarmtime.RtcAlarmMinute;
- clock_settingmode = 2;
- clock_settingtpos = 0;
- lcdshowdot(0,0);
- lcdshowdot(2,1);
- }
- else
- {
- alarmtime.RtcAlarmHour = clock_hour;
- alarmtime.RtcAlarmMinute = clock_minute;
- alarmtime.RtcAlarmSec = 0x00;
- alarmtime.RtcAlarmWeek = 0x7F;
- Rtc_SetAlarmTime(&alarmtime);
- clock_settingmode = 0;
- lcdshowdot(0,0);
- lcdshowdot(2,0);
- }
- }
设置RTC中断周期0.5秒,用于控制中间那两个点的闪烁表示秒和设置时间时对应位位的闪动
- void rtc_init()
- {
- stc_rtc_initstruct_t RtcInitStruct;
- stc_rtc_alarmtime_t RtcAlmStruct;
- DDL_ZERO_STRUCT(RtcInitStruct); //变量初始值置零
- DDL_ZERO_STRUCT(RtcAlmStruct);
- Sysctrl_SetPeripheralGate(SysctrlPeripheralRtc,TRUE);//RTC模块时钟打开
- RtcInitStruct.rtcAmpm = RtcPm; //24小时制
- RtcInitStruct.rtcClksrc = RtcClkXtl; //外部32768晶振
- RtcInitStruct.rtcPrdsel.rtcPrdsel = RtcPrdx; //周期中断类型PRDX
- RtcInitStruct.rtcPrdsel.rtcPrdx = 0u; //周期中断时间间隔 0.5秒
- RtcInitStruct.rtcTime.u8Second = 0x00; //配置RTC时间
- RtcInitStruct.rtcTime.u8Minute = 0x00;
- RtcInitStruct.rtcTime.u8Hour = 0x09;
- RtcInitStruct.rtcTime.u8Day = 0x11;
- RtcInitStruct.rtcTime.u8DayOfWeek = 0x05;
- RtcInitStruct.rtcTime.u8Month = 0x08;
- RtcInitStruct.rtcTime.u8Year = 0x23;
- RtcInitStruct.rtcCompen = RtcCompenEnable; // 使能时钟误差补偿
- RtcInitStruct.rtcCompValue = 0; //补偿值 根据实际情况进行补偿
- Rtc_Init(&RtcInitStruct);
-
- RtcAlmStruct.RtcAlarmSec = 0x00;
- RtcAlmStruct.RtcAlarmMinute = 0x00;
- RtcAlmStruct.RtcAlarmHour = 0x08;
- RtcAlmStruct.RtcAlarmWeek = 0x7f; //从周一到周日
- Rtc_SetAlarmTime(&RtcAlmStruct); //配置闹铃时间
- Rtc_AlmIeCmd(FALSE); //禁止闹钟中断
-
- EnableNvic(RTC_IRQn, IrqLevel3, TRUE); //使能RTC中断向量
- Rtc_Cmd(TRUE); //使能RTC开始计数
- }
RTC中断处理,每次中断翻转两点的显示状态,并更新时间,判断是否在设置模式,如果在设置模式同时翻转对应位的显示状态
- void show_setting_time()
- {
- clock_settinshownum = 1 - clock_settinshownum;
- lcdshow09num((clock_settingtpos==0&&clock_settinshownum==0)?0xFF:((clock_hour>>4)&0x0F),0);
- lcdshow09num((clock_settingtpos==1&&clock_settinshownum==0)?0xFF:clock_hour&0x0F,1);
- lcdshow09num((clock_settingtpos==2&&clock_settinshownum==0)?0xFF:((clock_minute>>4)&0x0F),2);
- lcdshow09num((clock_settingtpos==3&&clock_settinshownum==0)?0xFF:clock_minute&0x0F,3);
- }
- void show_time()
- {
- stc_rtc_time_t readtime;
- clock_showseconddot = 1 - clock_showseconddot;
- if(clock_settingmode == 0)
- {
- Rtc_ReadDateTime(&readtime);
- lcdshow09num(((readtime.u8Hour>>4)&0x0F),0);
- lcdshow09num(readtime.u8Hour&0x0F,1);
- lcdshow09num(((readtime.u8Minute>>4)&0x0F),2);
- lcdshow09num(readtime.u8Minute&0x0F,3);
- lcdshowdot(1,clock_showseconddot);
- }
- else
- {
- show_setting_time();
- }
- }
- void Rtc_IRQHandler(void)
- {
- if(Rtc_GetPridItStatus() == TRUE)
- {
- Rtc_ClearPrdfItStatus(); //清除中断标志位
- if(clock_alarmed)
- Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,!Gpio_ReadOutputIO(STK_LED_PORT, STK_LED_PIN));
- show_time();
- }
- if (Rtc_GetAlmfItStatus() == TRUE) //闹铃中断
- {
- Rtc_ClearAlmfItStatus(); //清中断标志位
- if(clock_alarmon > 0)
- clock_alarmed = 1;
- }
- }
主函数
- int32_t main(void)
- {
- Xtl_init();
- Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
- Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
- led_init();
- key_init();
- lptimer_init();
- lcd_io_init();
- lcd_init();
- rtc_init();
- Lcd_ClearDisp();
- lcdshow09num(0,3);
- lcdshow09num(0,2);
- lcdshow09num(0,1);
- lcdshow09num(0,0);
- lcdshowdot(1,1);
- Lpm_GotoDeepSleep(TRUE);
- while(1)
- {
- ;
- }
- }
运行效果:
正常时钟显示
开启关闭闹钟
设定时间
设定闹钟
闹钟响起