1、利用SysTick定时器编写倒计时程序,如初始设置为2分30秒,每秒在屏幕上输出一次时间,倒计时为0后,红灯亮,停止屏幕输出,并关闭SysTick定时器的中断。
1、利用SysTick定时器编写倒计时程序。
Includes.h
//(系统保留)
G_VAR_PREFIX vuint16_t gcRecvLen;
G_VAR_PREFIX vuint16_t gcRecvDCLen;
G_VAR_PREFIX vuint8_t gcReccrc32[4];
G_VAR_PREFIX vuint8_t gcRecvBuf[MCU_SECTORSIZE];
G_VAR_PREFIX vuint8_t gTime[3];
//时间数组
//(用户增加)
//(用户增加)
G_VAR_PREFIX vuint8_t cTime[3];
G_VAR_PREFIX vuint8_t ctime;
G_VAR_PREFIX vuint8_t ltime;
Isr.c
void SysTick_Handler()
{
//printf("***\n");
static uint8_t SysTickCount = 0;
SysTickCount++; //Tick单元+1
wdog_feed(); //看门狗“喂狗”
if (SysTickCount >= 100)
{
SysTickCount = 0;
gtime = gTime[0]*3600 + gTime[1]*60 + gTime[2];
ltime = ctime - gtime;
cTime[0] = ltime / 3600;
cTime[1] = (ltime - cTime[0] * 3600)/60;
cTime[2] = ltime- cTime[0] * 3600 - cTime[1] * 60;
SecAdd1(gTime);
}
}
void SecAdd1(uint8_t *p)
{
*(p+2)+=1; //秒+1
if(*(p+2)>=60) //秒溢出
{
*(p+2)=0; //清秒
*(p+1)+=1; //分+1
if(*(p+1)>=60) //分溢出
{
*(p+1)=0; //清分
*p+=1; //时+1
if(*p>=24) //时溢出
{
*p=0; //清时
}
}
}
}
Main.c
ctime = 61; //总倒计时
ltime = 0;
cTime[0] = 0; //时
cTime[1] = 0; //分
cTime[2] = 0; //秒
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化红灯
systick_init(10); //设置systick为10ms中断
for(;;) //for(;;)(开头)
{
if (gTime[2] == mSec) continue;
mSec=gTime[2];
if(ltime != 0){
printf("%d:%d:%d\n",cTime[0],cTime[1],cTime[2]);
}else{
printf("倒计时结束,红灯亮\n");
gpio_set(LIGHT_RED,LIGHT_ON);
for(;;) { }
}
} //for(;;)结尾
2、利用RTC显示日期(年月日、时分秒),每秒更新。并设置某个时间的闹钟。闹钟时间到时,屏幕上显示有你的姓名的文字,并点亮绿灯。
Isr.c
void RTC_WKUP_IRQHandler(void)
{
uint8_t hour,min,sec;
uint8_t year,month,date,week;
char *p;
if(RTC_PeriodWKUP_Get_Int()) //唤醒中断的标志
{
RTC_PeriodWKUP_Clear(); //清除唤醒中断标志
RTC_Get_Date(&year,&month,&date,&week); //获取RTC记录的日期
RTC_Get_Time(&hour,&min,&sec); //获取RTC记录的时间
p=NumToStr("%02d/%02d/%02d %02d:%02d:%02d 星期%d\n",year,month,date,hour,min,sec,week);
uart_send_string(UART_User,p);
printf("%02d/%02d/%02d %02d:%02d:%02d 星期%d\n",year,month,date,hour,min,sec,week);
}
}
void RTC_Alarm_IRQHandler(void)
{
if(RTC_Alarm_Get_Int(A)) //闹钟A的中断标志位
{
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF);
RTC_Alarm_Clear(A); //清闹钟A的中断标志位
printf("闹钟A触发\n");
gpio_set(LIGHT_GREEN,LIGHT_ON);
printf("邓学文\n");
}
if(RTC_Alarm_Get_Int(B)) //闹钟A的中断标志位
{
RTC_Alarm_Clear(B); //清闹钟A的中断标志位
printf("This is ALARM_B!!!\n");
}
}
Main.c
uint32_t mMainLoopCount; //主循环次数变量
uint8_t mFlag; //灯的状态标志
uart_init(UART_User,115200);
//(1.5)用户外设模块初始化
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化蓝灯
uart_init(UART_User,115200);
RTC_Init(); //RTC初始化
RTC_Set_Time(16,51,0); //设置时间为16:51:0
RTC_Set_Date(24,6,6,4); //设置日期
//(1.6)使能模块中断
RTC_PeriodWKUP_Enable_Int(); //使能唤醒中断
uart_enable_re_int(UART_User);
RTC_Alarm_Enable_Int(0);
RTC_Set_Alarm(0,4,16,52,0);
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
RTC_Set_PeriodWakeUp(1); //配置WAKE UP中断,每秒
RTC_Set_Alarm(0,4,16,52,0);
3、利用PWM脉宽调制,交替显示红灯的5个短闪和5个长闪。
uint8_t dFlag=1;
for(uint8_t i=1;i<=5;i++) //for(;;)(开头)
{
pwm_update(PWM_USER,m_duty); //调节占空比
m_duty=m_duty+5.0; //占空比每次递增5
if (m_duty>=90.0) m_duty=1.0; //当占空比大于90后置为1,重新进行循环。
for (m_i=0;m_i<3;m_i++) //m_i<3为了控制未知周期内相同占空比的波形只打印三次
{
m_K=0; //保证每次输出打印完整的PWM波,再进入下一个循环
do
{
mFlag=gpio_get(PWM_USER);
if ((mFlag==1)&&(Flag==1))
{
// 高电平亮
Flag=0;
m_K++;
//小灯反转
gpio_reverse(LIGHT_RED);
if(dFlag==1){
Delay_ms(1000);
printf("第%d次长闪\n",i);
dFlag=0;
continue;
}
dFlag=1;
printf("第%d次短闪\n",i);
}
else if ((mFlag==0)&&(Flag==0))
{
// 低电平暗
Flag=1;
m_K++;
gpio_reverse(LIGHT_RED);
}
}
while (m_K<1);
}
} //for(;;)结尾
4、GEC39定义为输出引脚,GEC10定义为输入引脚,用杜邦线将两个引脚相连,验证捕捉实验程序Incapture-Outcmp-20211110,观察输出的时间间隔。
观察输出的时间间隔: 大致5秒一个周期,在一个周期内蓝灯闪烁频率逐渐提高 【短闪->快闪】