使用STM32F103C8T6定时器实现LED周期性闪烁和PWM流水灯效果

目录

  • 一、问题描述
  • (一)定时器实现LED灯的周期闪烁
  • (二)输出PWM波形实现流水灯
  • 二、定时器实现LED灯的周期闪烁
  • (一)STM32定时器介绍
  • 1.简介
  • 2.定时器分类
  • 2.1基本定时器
  • 2.2通用定时器
  • 2.3高级定时器
  • 3.定时器时基
  • 4.计数器模式
  • (二)新建工程
  • 1.创建项目
  • 2.相关设置
  • (三)代码编写
  • (四)线路连接
  • 1.USB to TTL ——STM32F103C8T6
  • 2.STM32F103C8T6——LED
  • (五)实现效果
  • 1.烧录
  • 2.效果展示
  • 三、输出PWM波形实现流水灯
  • (一)PWM简介
  • 1.PWM含义
  • 2.基本原理
  • 3.优点及应用范围
  • 4.PWM配置介绍
  • 4.1 PWM输出的模式区别
  • 4.2. PWM的计数模式
  • 5.PWM的一般步骤
  • (二)STM32上的PWM
  • 1.PWM产生
  • 1.1PWM相关寄存器
  • 2.STM32f103c8t6的PWM口
  • (三)新建工程
  • 1.新建项目
  • 2.相关设置
  • (四) 代码编写
  • (五) 线路连接
  • (六)实现效果
  • 1.烧录
  • 2.效果展示
  • 四、总结
  • 五、参考资料
  • 一、问题描述

    (一)定时器实现LED灯的周期闪烁

    1. 通过定时器Timer方式实现时间的精准控制,相当于给CPU上了一个闹钟,CPU平时处理其它任务,当定时时间到了以后,处理定时相关的任务。请设置一个5秒的定时器,每隔5秒从串口发送“hello windows!”;同时设置一个2秒的定时器,让LED等周期性地闪烁。

    (二)输出PWM波形实现流水灯

    1. 使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。

    二、定时器实现LED灯的周期闪烁

    (一)STM32定时器介绍

    1.简介

    STM32f103系列一共有8个16位的定时器;其中TIM6、TIM7是基本定时器,TIM2、3、4、5是通用定时器,TIM1、8是高级定时器;这些定时器使STM32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电机控制及编码器接口等功能,适用于工业控制领域。

    2.定时器分类

    STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。
    定时器分类

    2.1基本定时器

    基本定时器只具备最基本的定时功能,就是累加的时钟脉冲数超过预定值时,能触发中断或触发DMA请求;
    芯片内部与DAC外设相连,可通过触发输出驱动DAC,也可以作为其他通用定时器的时钟基准;
    使用的时钟源都是TIMxCLK,时钟源经过预分频器输入至脉冲计数器TIMx_CNT,基本定时器只能工作在向上计数模式,在重载寄存器TIMx_ARR中保存的是定时器的溢出值;
    工作时,脉冲计数器TIMx_CNT由时钟触发进行计数,当计数器的值x等于重载寄存器中保存的数值N时,产生溢出事件,可触发中断或DMA请求,然后计数器重新置0,重新向上计数;

    ①时钟源
    定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1 预分频器后分频提供,如果APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟TIMxCLK=36*2=72M。
    ②计数器时钟
    定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
    ③计数器
    计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
    ④自动重装载寄存器
    自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
    5. 定时时间的计算
    定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来 记 录 中断 的 次 数,那 么 就 可以 计 算 出我们 需 要 的定 时 时 间等于 :1/CK_CLK * (ARR+1)*time。

    2.2通用定时器

    通用定时器除了基本的定时,它主要用在测量输入脉冲的频率、脉宽与输出PEM脉冲的场合,还具有编码器的接口,如下图所示:


    1.捕获/比较寄存器
    它在输入时被用于捕获(存储)输入脉冲在电平发生翻转时脉冲计数器的当前计数值,从而实现脉冲的频率测量;
    在输出时被用来存储一个脉冲数值,把这个数值用于与脉冲计数器的当前计数值进行比较,根据比较结果进行不同的电平输出。
    2.PWM输出过程分析
    若配置脉冲计数器为向上计数,而重载寄存器被配置为N,即计数器的当前值x在时钟源的驱动下不断累加,当计数器的值大于N时,回充值计数器的数值为0并重新计数;
    在计数器计数的同时,计数器的计数值x会与比较寄存器TIMx_CCR预先存储的数值A进行比较。当计数器的值小于A时,输出高电平(或低电平),相反则反之;
    循环下去即得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉宽则为比较寄存器的值A乘以触发脉冲的时钟周期,即输出PEM的占空比为A/(N+1).
    3.PWM输入过程分析
    当定时器被配置为输入功能时,可以用于检测输入到GPIO引脚的信号,此时捕获/比较寄存器TIMx_CRR被用作捕获功能,简称捕获寄存器。
    下图为PWM输入时的脉冲宽度检测时序图;

    工作过程:要测量的PWM脉冲通过GPIO引脚输入到定时器的脉冲检测通道,为图中的TI1;
    在输入脉冲TI1的上升沿到达时,触发IC1和IC2输入捕获中断,这时把脉冲计数器的计数值复位为0,于是计数器的计数值X在时钟源的驱动下从0开始不断累加,直到TI1出现下降沿,触发IC2捕获事件,此时TIMx_CCR2把计数器的当前值2存储起来,计数器继续累加,直到TI1出现第二个上升沿,出发了IC1捕获事件,得到的当前计数值被保存到TIMX_CCR1中。
    根据保存的数值很容易得到占空比和周期。
    4.定时器的时钟源
    通用定时器可以使用外部脉冲作为定时器的时钟源;
    使用外部时钟源时,要使用寄存器进行触发边沿、滤波器带宽的配置。

    2.3高级定时器

    此类定时器除了具有基本、通用定时器的所有功能外,还具有三相6步电机的接口、刹车功能及用于PWM驱动电路的死区时间控制,使其非常使用于电机控制。

    高级定时器结构如下图所示:

    相比较另外两种定时器,主要多出了BRK、DTG两个结构,具有了控制死区时间的控制功能;

    死区时间:在三相桥的PWM驱动电路中,上下两个桥臂的PWM驱动信号是互补的,即上下桥臂轮流导通,但实际上为了防止出现上下两个臂同时导通(会造成短路),在上下两臂切换时留一小段时间,上下臂都施加关断信号。

    在保证不出现短路的情况下,死区时间越短越好,时间太长会导致OCx或OCxN输出不正常.

    3.定时器时基

    内部时钟(CK_INT)
    外部时钟模式 1:外部输入脚(TIx)
    外部时钟模式 2:外部触发输入(ETR)
    内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。 这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。

    4.计数器模式

    向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件
    向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件
    中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数

    (二)新建工程

    1.创建项目


    选择目的芯片,本文选用STM32F103C8T6

    2.相关设置

    1. RCC设置

    2. SYS设置

    3. 端口设置
      选择PA4为LED端口,设置为GPIO_Output

    4. 定时器设置
      这里使用TIM2定时器2和TIM3定时器3来实现定时的功能。选中定时器2;配置定时器2的时钟源为内部时钟;设置分频系数为71,向上计数模式,计数周期为5000,实现2秒

      分频系数那里虽然写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。

    5. 中断设置

    6. USART1设置

    7. 时钟设置

    8. 其他
      注意路径中不要含有中文

    (三)代码编写

    1. 直接打开上步生成的工程文件,在main.c添加定时器启动代码
    	HAL_TIM_Base_Start_IT(&htim2);
    	HAL_TIM_Base_Start_IT(&htim3);
    
    

    1. 添加串口输出hello windows代码
    	uint8_t hello[20]="hello windows!\r\n";
    
    

    3.定时器中断回调函数

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	static uint32_t time_cnt =0;
    	static uint32_t time_cnt3 =0;
    	if(htim->Instance == TIM2)
    	{
    		if(++time_cnt >= 400)
    		{
    			time_cnt =0;
    			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);
    		}
    	}
    	if(htim->Instance == TIM3)
    	{
    		if(++time_cnt3 >= 1000)
    		{
    			time_cnt3 =0;
        HAL_UART_Transmit(&huart1,hello,20,100000);
    		}
    			
    	}
    }
    
    


    编译一下

    (四)线路连接

    1.USB to TTL ——STM32F103C8T6

           3V3 —— 3V3
           GND—— GND
           RXD——A9
           TXD ——A10
    

    2.STM32F103C8T6——LED

     LED灯短脚 —— A4
     LED灯长脚 —— 3V3  
    

    (五)实现效果

    1.烧录

    2.效果展示

    LED周期闪烁

    LED闪烁

    串口输出

    串口输出hello windows

    三、输出PWM波形实现流水灯

    (一)PWM简介

    1.PWM含义

    PWM(Pulse Width Modulation)即脉冲宽度调制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术;它是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。

    2.基本原理

    PWM就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也可以这样理解,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。

    3.优点及应用范围

    由于其控制简单、灵活和动态响应好等优点而成为电力电子技术应用最广泛的控制方式,其应用领域包括测量,通信, 功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此学习PWM具有十分重要的现实意义。

    4.PWM配置介绍

    在上步中介绍了STM32的定时器,并提到PWM输出是STM32的定时器的功能之一,为了实现PWM功能,需要使用定时器中的比较寄存器(TIMx_CCRx)。
    捕获/比较模式寄存器总共2个,TIMx_CCMR1和TIMx_CCMR2
    TIMx_CCMR1控制CH1和CH2,TIMx_CCMR2控制CH3和CH4。该寄存器的某些位在不同模式下功能不一样,上面一层对应输出而下面一层对应输入;
    其中模式设置位OCxM位,此位由3位组成,一共可以配置成7种模式,我们使用的是PWM模式,所以这三位必须为110/111。
    当定时器以PWM模式工作时,会自动将TIMx_CCRx的值与TIMx_CNT(计数寄存器)中的值做比较,当TIMx_CNT中的值小于TIMx_CCRx的值时,PWM输出引脚输出高电平,大于时则输出低电平。因此知道了PWM信号的周期和占空比可以通过设置比较寄存器TIMx_CCRx和定时器重载寄存器TIMx_ARR来控制。PWM的占空比可以通过下图公式计算:

    4.1 PWM输出的模式区别

    PWM模式1:在向上计数时,一旦
    TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;
    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)
    PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;
    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平
    注意:PWM的模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合CCER寄存器的CCxP位的值来确定
    例如:若PWM模式1,且CCER寄存器的CCxP位为0,则当TIMx_CNT<TIMx_CCR1时,输出高电平;同样的,若PWM模式1,且CCER寄存器的CCxP位为2,则当TIMx_CNT<TIMx_CCR1时,输出低电平

    4.2. PWM的计数模式

    向上计数模式:
    下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时PWM信号参考OCxREF为高,否则为低。如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0’。

    向下计数模式:
    在PWM模式1,当TIMx_CNT>TIMx_CCRx时参考信号OCxREF为低,否则为高。如果TIMx_CCRx中的比较值大于TIMx_ARR中的自动重装载值,则OCxREF保持为’1’。该模式下不能产生0%的PWM波形。

    中央对齐模式:
    当TIMx_CR1寄存器中的CMS位不为’00’时,为中央对齐模式(所有其他的配置对OCxREF/OCx信号都有相同的作用)。根据不同的CMS位设置,比较标志可以在计数器向上计数时被置’1’、在计数器向下计数时被置’1’、或在计数器向上和向下计数时被置’1’。TIMx_CR1寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。

    5.PWM的一般步骤

    1. 使能定时器和相关IO口时钟。调用函数:
      RCC_APB1PeriphClockCmd()
      RCC_APB2PeriphClockCmd();

    2. 初始化IO口为复用功能输出。调用函数:GPIO_Init();

    这里是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟,同时设置重映射;调用函数:RCC_APB2PeriphClockCmd(); GPIO_PinRemapConfig();

    1. 初始化定时器。调用函数:ARR,PSC等:TIM_TimeBaseInit();

    2. 初始化输出比较参数。调用函数:TIM_OC2Init();

    3. 使能预装载寄存器。调用函数:TIM_OC2PreloadConfig();

    4. 使能定时器。调用函数:TIM_Cmd();

    5. 不断改变比较值CCRx,达到不同的占空比效果;调用函TIM_SetCompare2()

    (二)STM32上的PWM

    1.PWM产生

    STM32的定时器除了TIM6和7,其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
    普通IO也可以输出PWM,只是产生PWM一般用转用芯片(开关电源上用的较多)或者单片机的PWM内置模块如定时器,很小直接用MCU的IO口线直接输出因为那样太耗MCU资源了。
    脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。通用定时器产生PWM 的定时器框图如下:(其他定时器框图类似)

    1.1PWM相关寄存器

    包含三个寄存器:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位,(在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。在TIMx_CCMRx寄存器中的OCxM位写入110(PWM模式1)或111(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。

    捕获/比较模式寄存器(TIMx_CCMRx)
    下图为TIMx_CCMR1寄存器的各位描述:这里需要使用的是模式设置位OCxM,总共有两种PWM模式,这两种PWM 模式的区别就是输出电平的极性相反。
    捕获/比较使能寄存器(TIMx_CCER)
    下图为TIMx_CCER寄存器的各位描述:

    该寄存器控制着各个输入输出通道的开关。这里只用到了CC2E位,该位是输入/捕获 2 输出使能位,要想PWM 从 I/O 口输出,这个位必须设置为 1。
    捕获/比较寄存器(TIMx_CCRx)
    下图为TIMx_CCR1寄存器的各位描述

    在输出模式下,该寄存器的值与 CNT 的值比较,根据比较结果在OC1端口上产生输出信号。利用这点,我们通过修改这个寄存器的值实现控制 PWM 的输出脉宽。

    2.STM32f103c8t6的PWM口

    详细配置如下:
    TIM1_CH1->PA8;
    TIM1_CH2->PA9;
    TIM1_CH3->PA10;
    TIM1_CH4->PA11;
    
    TIM2_CH1->PA0;
    TIM2_CH2->PA1;
    TIM2_CH3->PA2;
    TIM2_CH4->PA3;
    
    TIM3_CH1->PA6;
    TIM3_CH2->PA7;
    TIM3_CH3->PB0;
    TIM3_CH4->PB1;
    
    TIM4_CH1->PB6;
    TIM4_CH1->PB7;
    TIM4_CH1->PB8;
    TIM4_CH1->PB9;
    
    

    (三)新建工程

    1.新建项目

    步骤与上部分新建项目一致

    2.相关设置

    1. RCC设置

    2. SYS设置

    3. TIM3设置

    4. TIM4设置

    5. 时钟设置

    6. 其他
      注意路径中不要含有中文

    (四) 代码编写

    1. 打开工程文件
    2. main.c文件添加变量
    uint16_t pwm=0;   //占空比
    
    

    1. 开启TIM3和TIM4的PWM的通道1
    	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); 
        HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1); 
    
    

    1. while中写入调用代码
    while (pwm< 500)
    	  {
    		  pwm++;
    		  __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);  
        __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);  			
    		  HAL_Delay(1);
    	  }
    	  while (pwm)
    	  {
    		  pwm--;
    		  __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);    
           __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);  
    			
    		  HAL_Delay(1);
    	  }
    	  HAL_Delay(200);
    
    

    1. 编译一下

    (五) 线路连接

    3V3 —3V3

    GND —GND

    RXD —A9

    TXD —A10

    LED灯短脚 —A6

    LED灯长脚 —3V3

    PB6 —PC13

    (六)实现效果

    1.烧录

    2.效果展示

    呼吸灯

    四、总结

    本文章介绍了STM32F103C8T6定时器实现led的周期闪烁及PWM实现流水灯,学习了有关定时器的知识,相较上几个实验,这个更加简单,当结果出来与预期一致时,也会感到欣喜,虽然比上几个实验简单,但是也包含了许多的知识,受益匪浅。

    五、参考资料

    https://blog.csdn.net/XMJYever/article/details/105843993
    https://blog.csdn.net/qq_45237293/article/details/111997424
    https://blog.csdn.net/weixin_50438937/article/details/118881923
    http://www.mcublog.cn/stm32/2021_01/stm32cubemx-dingshiqi-led/
    《零死角玩转 STM32F103—指南者》

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32F103C8T6定时器实现LED周期性闪烁和PWM流水灯效果

    发表评论