实验三 定时器及PWM实验

一、实验目的

  1. 熟悉定时中断计时的工作编程方法。
  2. 掌握PWM编程方法。

二、实验设备和资料

软硬件工具和实验一相同,包括:

  1. 硬件部分:PC或笔记本电脑一台、AHL-STM32L431开发套件一套
  2. 软件部分:从苏州大学嵌人式学习社区网站,按照教材1.1.2节内容,下载相关的电子资源。并进行集成开发环境的安装。
  3. 电子资料:\04-Software\CH07文件夹中的各程序
  4. 参考教材:嵌入式技术基础与实践(第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;//设置230

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. 倒计时-CSDN直播

实验内容1结果链接。倒计时并不是正常的倒计时,我把每一秒变成了10ms。

  1. 日期加闹钟-CSDN直播

实验内容2结果链接。实验2设定10秒后灯亮输出姓名

  1. 灯闪烁-CSDN直播

实验内容3结果链接。

  1. 杜邦线连接结果-CSDN直播

实验内容4结果链接。

由视频可知,输出时间间隔以5秒为单位,随着时间的增加,灯闪烁越来越快,输出的结果越来越快。

六、分析思考

这次实验了解到了AHL-STM32L431的计时器,定时器和脉冲调制等功能。尤其是脉冲宽度调制,脉冲宽度调制是这里面内容在现实生活中在我看来最重要,同时我在理解代码方面也是比较困难的,所幸成功书写,可能结果不尽如人意,但是还是有了些许理解。脉冲宽度调制是通过调节电平占空比从而调节电压大小,这个方法会使用在交流电的产生中,交流发电机可以凭此控制输出的交流电压。

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解答这个问题。 首先,PWM(Pulse-Width Modulation)是一种调制技术,可以用来控制电路中的电压或电流。在呼吸灯实验中,我们可以使用 PWM 技术来控制 LED 的亮度,实现呼吸灯效果。 在 STM32 中,可以使用定时器模块来实现 PWM 功能。具体步骤如下: 1. 选择一个可用的定时器模块,并配置其时钟源和预分频器。 2. 配置定时器模块为 PWM 模式,并设置 PWM 的周期和占空比。 3. 配置定时器模块的输出通道,将其连接到 LED 灯的控制引脚上。 4. 启动定时器模块,开始 PWM 输出。 下面是一个简单的呼吸灯实验代码示例: ```c #include "stm32f10x.h" #define LED_PIN GPIO_Pin_13 #define LED_PORT GPIOC void delay(uint32_t ms) { uint32_t i; while (ms--) { for (i = 0; i < 1000; i++); } } void led_pwm_breath(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能定时器时钟和 GPIO 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 配置 LED 控制引脚为推挽输出 GPIO_InitStructure.GPIO_Pin = LED_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LED_PORT, &GPIO_InitStructure); // 配置定时器基本参数 TIM_TimeBaseStructure.TIM_Period = 1000; TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // 配置定时器输出通道为 PWM 模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 500; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); // 启动定时器 TIM_Cmd(TIM1, ENABLE); while (1) { // 增加占空比 for (int i = 0; i <= 1000; i += 10) { TIM_SetCompare1(TIM1, i); delay(10); } // 减小占空比 for (int i = 1000; i >= 0; i -= 10) { TIM_SetCompare1(TIM1, i); delay(10); } } } int main(void) { led_pwm_breath(); return 0; } ``` 在上面的代码中,我们使用 TIM1 定时器模块来控制 LED 的亮度。首先,我们配置 TIM1 的时钟源和预分频器,使其时钟频率为 1MHz。然后,我们将 LED 控制引脚 PC13 配置为推挽输出模式,将其连接到 TIM1 的通道 1 上。 接着,我们配置 TIM1 的输出通道 1 为 PWM1 模式,并设置 PWM 的周期为 1000(即 1kHz),占空比为 50%。最后,我们启动 TIM1 定时器,并在一个无限循环中不断增加和减小 PWM 的占空比,实现呼吸灯效果。 希望这个例子对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值