一.利用SYSTICK编写倒计时程序,如初始设置为2min30s,每秒在屏幕上输出一次时间,倒计时为0后,红灯亮,停止屏幕输出,并关闭SYSTICK定时器中断
MAIN:
int main(void)
{
//关总中断
DISABLE_INTERRUPTS;
wdog_stop();
//"时分秒"缓存初始化(00:02:30)
gTime[0] = 0; //时
gTime[1] = 2; //分
gTime[2] = 30; //秒
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF);
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF); //初始化灯,全灭
//初始化 SysTick
SysTick->CTRL = 0; //清零,包括禁止中断以及计时
SysTick->LOAD = SystemCoreClock * 0.1; //写入重载值,计时时长为0.1秒
SysTick->VAL = 999UL; //清除当前值
while(SysTick->VAL != 0); //等待 SysTick 当前值清零完成
printf("SysTick 当前值:%d\n", SysTick->VAL);
SysTick->CTRL |= (1UL << 2U); //选择内核时钟
SysTick->CTRL |= (1UL << 1) | 1UL; //使能 SysTick 中断和计时
//开总中断
ENABLE_INTERRUPTS;
printf("ZGY,045\n");
printf("倒计时:%d:%d:%d\n",gTime[0],gTime[1],gTime[2]);
gpio_set(LIGHT_GREEN,LIGHT_ON); //设置绿灯亮
//主循环部分
for(;;)
{
}
}
ISR:
void SysTick_Handler()
{
static uint8_t SysTickCount = 0;
SysTickCount++; //Tick单元+1
wdog_feed(); //看门狗“喂狗”
if (SysTickCount >= 10)
{
SysTickCount = 0;
if(gTime[2] == 0)
{
if(gTime[1] == 0)
{
if(gTime[0] == 0)
{
printf("倒计时结束,红灯亮\n");
gpio_set(LIGHT_GREEN,LIGHT_OFF); //设置绿灯暗
gpio_set(LIGHT_RED,LIGHT_ON); //设置红灯亮
SysTick->CTRL = 0; //清零,包括禁止中断以及计时
printf("ZGY,045\n");
return;
}
gTime[0]--;
gTime[1] = 59U;
}
gTime[1]--;
gTime[2] = 59U;
}
else
{
gTime[2]--;
}
printf("倒计时:%d:%d:%d\n",gTime[0],gTime[1],gTime[2]);
if((gTime[2] % 2) == 0)
{
gpio_set(LIGHT_GREEN,LIGHT_ON); //设置绿灯亮
}
else
{
gpio_set(LIGHT_GREEN,LIGHT_OFF); //设置绿灯暗
}
}
}
二.利用RTC显示日期,每秒更新。并设置某个时间的闹钟。闹钟时间到,有名字,并点亮绿灯。
MAIN:
int main(void)
{
//关总中断
DISABLE_INTERRUPTS;
//用户外设模块初始化
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化红灯
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //初始化绿灯
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF); //初始化蓝灯
RTC_Init(); //RTC初始化
RTC_Set_Time(23,59,59); //设置时间为0:0:0
RTC_Set_Date(24,6,6,4); //设置日期
//使能模块中断
RTC_PeriodWKUP_Enable_Int(); //使能唤醒中断
RTC_Alarm_Enable_Int(A);
//开总中断
ENABLE_INTERRUPTS;
RTC_Set_PeriodWakeUp(1); //配置WAKE UP中断,每秒中断一次
RTC_Set_Alarm(A,5,0,0,10); //设置闹钟A
//主循环
for(;;) //for(;;)(开头)
{
}
}
ISR:
void RTC_WKUP_IRQHandler(void)
{
uint8_t hour,min,sec;
uint8_t year,month,date,week;
if(RTC_PeriodWKUP_Get_Int()) //唤醒中断的标志
{
RTC_PeriodWKUP_Clear(); //清除唤醒中断标志
RTC_Get_Date(&year,&month,&date,&week); //获取RTC记录的日期
RTC_Get_Time(&hour,&min,&sec); //获取RTC记录的时间
gpio_set(LIGHT_GREEN,LIGHT_OFF); //绿灯暗
if((sec % 2) == 0)
{
gpio_set(LIGHT_RED,LIGHT_ON); //红灯亮
}
else
{
gpio_set(LIGHT_RED,LIGHT_OFF); //红灯暗
}
printf("%02d/%02d/%02d %02d:%02d:%02d 星期%d\n",year,month,date,hour,min,sec,week);
}
}
void RTC_Alarm_IRQHandler(void)
{
gpio_set(LIGHT_RED,LIGHT_OFF); //红灯暗
gpio_set(LIGHT_GREEN,LIGHT_ON); //绿灯亮
if(RTC_Alarm_Get_Int(A)) //闹钟A的中断标志位
{
RTC_Alarm_Clear(A); //清闹钟A的中断标志位
printf("闹钟A 绿灯亮 ZGY\n");
}
if(RTC_Alarm_Get_Int(B)) //闹钟B的中断标志位
{
RTC_Alarm_Clear(B); //清闹钟B的中断标志位
printf("闹钟A 绿灯亮 ZGY\n");
}
}
三.利用PWM脉宽调制,交替显示红灯的五个短闪和长闪。
MAIN:
int main(void)
{
//(1.1)声明main函数使用的局部变量
uint8_t mFlag; //灯的状态标志
uint8_t Flag; //希望采集的电平高低标志
double m_duty; //占空比
uint32_t m_i; //控制在未知周期内不同占空比的波形只打印有限次
uint8_t m_K; //确保每次能正确打印输出PWM波形
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
Flag=1;
mFlag=0; //灯的状态标志
//(1.5)用户外设模块初始化
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //初始化红灯暗
pwm_init(PWM_USER,1500,1000,10.0,PWM_CENTER,PWM_MINUS); //PWM输出初始化
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
m_K=0;
m_duty=10.0; //占空比设置为10%
for(;;)
{
pwm_update(PWM_USER,m_duty); //调节占空比
for (m_i=0;m_i<10;m_i++) //m_i<10为了控制小灯闪烁5次
{
m_K=0; //保证每次输出打印完整的PWM波,再进入下一个循环
do
{
mFlag=gpio_get(PWM_USER); //获取灯的状态标志
if ((mFlag==1)&&(Flag==1))
{
printf("高电平:1\n");
Flag=0;
m_K++;
gpio_reverse(LIGHT_RED);//小灯反转
}
else if ((mFlag==0)&&(Flag==0))
{
printf("低电平:0\n");
Flag=1;
m_K++;
gpio_reverse(LIGHT_RED);
}
}
while (m_K<1);
}
m_duty = 100.0-m_duty; //不断循环每5次灯闪烁调节占空比
}
}
四.GEC39定义为输出引脚,GEC10定义为输入引脚,用杜邦线将两个引脚相连,验证捕捉实验程序,观察输出时间间隔。