一、实验目的
- 熟悉定时中断计时的工作编程方法。
- 掌握PWM编程方法。
二、实验设备和资料
软硬件工具和实验一相同,包括:
- 硬件部分:PC或笔记本电脑一台、AHL-STM32L431开发套件一套
- 软件部分:从苏州大学嵌人式学习社区网站,按照教材1.1.2节内容,下载相关的电子资源。并进行集成开发环境的安装。
- 电子资料:\04-Software\CH07文件夹中的各程序
- 参考教材:嵌入式技术基础与实践(第6版),王宜怀等. 清华大学出版社
三、实验内容
1、利用SysTick定时器编写倒计时程序,如初始设置为2分30秒,每秒在屏幕上输出一次时间,倒计时为0后,红灯亮,停止屏幕输出,并关闭SysTick定时器的中断。
2、利用RTC显示日期(年月日、时分秒),每秒更新。并设置某个时间的闹钟。闹钟时间到时,屏幕上显示有你的姓名的文字,并点亮绿灯。
3、利用PWM脉宽调制,交替显示红灯的5个短闪和5个长闪。
4、GEC39定义为输出引脚,GEC10定义为输入引脚,用杜邦线将两个引脚相连,验证捕捉实验程序Incapture-Outcmp-20211110,观察输出的时间间隔。
四、程序源码
1. isr.c文件
#include "includes.h"
int min=2,sec=30;//设置2分30秒
int count=0;
volatile int time=0;//判断倒计时是否结束的标志
int number=1;//倒计时次数
void SysTick_Handler()
{
if(time)return;//倒计时结束
count++;
if (count >= 10)
{
count = 0;
sec--;
if (sec < 0)
{
sec = 59; // 重置秒数为59,以避免负数
min--;
if (min < 0)
{
min = 0; // 重置分钟数为0
time = 1; // 设置时间过期标志
SysTick->CTRL &= ~(1UL << 1); // 清除_TICKINT位,关闭SysTick中断
gpio_set(LIGHT_RED,LIGHT_ON);//红灯亮
return;
}
}
// 打印当前时间
printf("倒计时: %02d:%02d\n", min, sec);
}
}
main.c文件
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
int main()
{
DISABLE_INTERRUPTS;
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);
NVIC_SetPriority(SysTick_IRQn,15UL);
SysTick->CTRL=0;
SysTick->VAL=0;
SysTick->LOAD=480000UL;//10ms算作一秒
SysTick->CTRL|=0b111;
ENABLE_INTERRUPTS;
while(1);
}
2. isr.c文件
#include "includes.h"
void User_SysFun(uint8_t ch);
uint8_t CreateFrame(uint8_t Data,uint8_t * buffer); //组帧函数声明
int second=0;
void RTC_WKUP_IRQHandler()
{
if(RTC_PeriodWKUP_Get_Int())
{
RTC_PeriodWKUP_Clear();
uint8_t hour,min,sec,year,month,date,week;
second++;
RTC_Get_Time(&hour,&min,&sec);
RTC_Get_Date(&year,&month,&date,&week);
printf("%02d年%02d月%02d日星期%d %02d:%02d:%02d\n",year,month,date,week,hour,min,sec);
}
}
void RTC_Alarm_IRQHandler()
{
if(RTC_Alarm_Get_Int(0))
{
RTC_Alarm_Clear(0);
printf("luo");
gpio_set(LIGHT_GREEN,LIGHT_ON);
}
}
main.c文件
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
int main()
{
DISABLE_INTERRUPTS;
RTC_Init();
RTC_Set_Date(24,5,25,6);//2024年5月25号星期6
RTC_Set_Time(16,05,0);16点05分0秒
RTC_PeriodWKUP_Enable_Int();
RTC_Alarm_Enable_Int(0);
RTC_Set_Alarm(0,6,16,05,10);设置闹钟为星期6,16点05分10秒
RTC_Set_PeriodWakeUp(1);
ENABLE_INTERRUPTS;
while(1);
}
3. main.c文件
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
int main()
{
double duty=50.0;//占空比
int count=0;//闪烁次数
int type=0;//闪烁类型,0为短,1为长
pwm_init(PWM_USER,750,1500,duty,PWM_EDGE,PWM_PLUS);
gpio_init(LIGHT_RED,1,1);
while(1)
{
if (gpio_get(PWM_USER))
{
// PWM输出高电平,LED亮
gpio_set(LIGHT_RED, 1);
}
else
{
// PWM输出低电平,LED灭
gpio_set(LIGHT_RED, 0);
}
// 根据当前的type,执行短闪或长闪
if (type == 0)
{
// 执行短闪
pwm_update(PWM_USER,10.0);
count++;
if (count == 5)
{
// 完成5个短闪,切换到长闪
type = 1;
count = 0;
}
}
else
{
// 执行长闪
pwm_update(PWM_USER,90.0);
count++;
if (count == 5)
{
// 完成5个长闪,切换回短闪
type = 0;
count = 0;
}
}
}
}
五、运行结果
用适当的文字、截图、图片等描述实验的结果。
实验内容1结果链接。倒计时并不是正常的倒计时,我把每一秒变成了10ms。
实验内容2结果链接。实验2设定10秒后灯亮输出姓名。
实验内容3结果链接。
实验内容4结果链接。
由视频可知,输出时间间隔以5秒为单位,随着时间的增加,灯闪烁越来越快,输出的结果越来越快。
六、分析思考
这次实验了解到了AHL-STM32L431的计时器,定时器和脉冲调制等功能。尤其是脉冲宽度调制,脉冲宽度调制是这里面内容在现实生活中在我看来最重要,同时我在理解代码方面也是比较困难的,所幸成功书写,可能结果不尽如人意,但是还是有了些许理解。脉冲宽度调制是通过调节电平占空比从而调节电压大小,这个方法会使用在交流电的产生中,交流发电机可以凭此控制输出的交流电压。