STM32单片机:基本定时器应用:单脉冲模式(STM32L4xx)

通过前面的章节,我们了解可以通过控制基本定时器的一些寄存器,从而实现周期性的更新事件或中断,比如精确定时或模拟生成PWM。

基本定时器除了可以实现周期性的更新事件或中断外,还提供了一种单脉冲的工作方式。

在连续的周期性工作模式下,当启动定时器后,定时器的计数器寄存器(TIMx_CNT) 立即开始增计数,当计数值达到通过自动重新加载寄存器(TIMx_ARR) 加载到对应的影子寄存器的值时,产生更新事件和中断,并且**计数器寄存器(TIMx_CNT)**重新从0开始计数,如此循环往复。

在单脉冲的工作方式下,当启动定时器后,定时器的计数器寄存器(TIMx_CNT) 立即开始增计数,当计数值达到通过自动重新加载寄存器(TIMx_ARR) 加载到对应的影子寄存器的值时,产生更新事件和中断,同时自动停止定时器,也即**计数器寄存器(TIMx_CNT)**停止计数,直到再次启动定时器。


实例演示:PA1:连接一个按键,PC6:连接一个发光二极管。每当连接PA1的按键按下时,PC6输出低电平,同时启动TIM6的单脉冲(脉冲宽度=500ms)工作方式,当脉冲持续时间到达后,产生中断,中断程序里将PC6输出高电平,单脉冲的一个工作流程结束,定时器自动停止。等待下一次启动。实验效果:每当按键按下时,LED点亮500ms,然后熄灭。


实现的代码如下:

main.c: 主程序

复制代码
//-----------------------------------------------------------------------------
// 本工程实现功能:
//
// 1. 启动外部高频晶体HSE(24.576MHz)
//
// 2. 将时钟频率HSE/8=3.072MHz输出到MCO(PA8)
//
// 3. 选择时钟频率HSE作为系统时钟SYSCLK
//
// 4. 基本定时器TIM6设置为单脉冲模式
//
// 5. 将一个按键接入PA1, 按键按下时, 利用TIM6的单脉冲工作方式,
//
//    通过PC6输出一个宽度为500ms的脉冲, PC6连接一个LED发光二极管, 此LED被点亮
//
// 本工程运行环境:  IAR for ARM 8.32.1
//
// 本工程运行MCU:   STM32L431RCT6
//
//-----------------------------------------------------------------------------
void main(void)
{
    DEV_GPIO_Init();

    DEV_TIM6_Init();

    while(1)
    {
        // 判断连接在PA1的按键是否按下
        if ((GPIO_IDR(GPIOA)&BIT1)==0)
        {
            // PC6 = 0
            DEV_GPIO_BitClr(GPIOC, GPIO_PIN_6);

            // 启动TIM6计数器
            TIM_CR1(TIM6) |= TIM_CR1_CEN;

            // 等待按键抬起
            while ((GPIO_IDR(GPIOA)&BIT1)==0);
        }
    }
}

GPIO.c: GPIO初始化

复制代码
//-----------------------------------------------------------------------------
// 初始化GPIO
//-----------------------------------------------------------------------------
void DEV_GPIO_Init(void)
{
    //-------------------------------------------
    // GPIO-A 初始化
    //-------------------------------------------
    DEV_GPIO_EnableClock(GPIOA);

    // GPIO-A【Pin1】: 按键输入
    DEV_GPIO_Config(GPIOA, GPIO_PIN_1, GPIO_MODER_INPUT, GPIO_OTYPER_OPENDRAIN, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);

    // GPIO-A【Pin8】: MCO
    DEV_GPIO_Config(GPIOA, GPIO_PIN_8, GPIO_MODER_AF, GPIO_OTYPER_PUSHPULL, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);

    //-------------------------------------------
    // GPIO-C 初始化
    //-------------------------------------------
    DEV_GPIO_EnableClock(GPIOC);

    // GPIO-C【Pin6,7,8,9】: LED灯
    DEV_GPIO_Config(GPIOC, GPIO_PIN_6, GPIO_MODER_OUTPUT, GPIO_OTYPER_PUSHPULL, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);
    DEV_GPIO_Config(GPIOC, GPIO_PIN_7, GPIO_MODER_OUTPUT, GPIO_OTYPER_PUSHPULL, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);
    DEV_GPIO_Config(GPIOC, GPIO_PIN_8, GPIO_MODER_OUTPUT, GPIO_OTYPER_PUSHPULL, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);
    DEV_GPIO_Config(GPIOC, GPIO_PIN_9, GPIO_MODER_OUTPUT, GPIO_OTYPER_PUSHPULL, GPIO_OSPEEDR_VERYHIGH, GPIO_PUPDR_PULLUP, GPIO_AFR_0, 1);
}

//-----------------------------------------------------------------------------
// GPIO位输出1
//-----------------------------------------------------------------------------
void DEV_GPIO_BitSet(ulong ul_GPIOx, ulong ul_PINx)
{
    GPIO_BSRR(ul_GPIOx) = ul_PINx;
}

//-----------------------------------------------------------------------------
// GPIO位输出0
//-----------------------------------------------------------------------------
void DEV_GPIO_BitClr(ulong ul_GPIOx, ulong ul_PINx)
{
    GPIO_BRR(ul_GPIOx) = ul_PINx;
}

TIM6.c: TIM6初始化

复制代码
//----------------------------------------------------------------------------
// 初始化TIM6: 基本定时器(单脉冲模式)
//
// PC6单脉冲的脉冲宽度=500ms
//
// 时钟源:  APB1-PCLK1 = 6.144MHz【80 MHz Max】
//
// RCC_CFGR_PPRE1 的分频系数  = 1 时  CLK = APB1-PCLK1
// RCC_CFGR_PPRE1 的分频系数 != 1 时  CLK = APB1-PCLK1 * 2
// 因为: 本系统 RCC_CFGR_PPRE1 的分频系数 = RCC_CFGR_PPRE1_DIV4 , 不等于1
// 所以: CLK = APB1-PCLK1 * 2 = 6.144MHz * 2 = 12.288MHz
//----------------------------------------------------------------------------
void DEV_TIM6_Init(void)
{
    // 允许TIM6时钟
    RCC_APB1ENR1 |= RCC_APB1ENR1_TIM6EN;

    // TIM_CR1.ARPE = 0, TIM_CR1.URS = 0, TIM_CR1.UDIS = 0
    // 禁止预加载模式: 写入TIM_ARR的值直接到达影子寄存器
    TIM_CR1(TIM6) = 0;

    // 单脉冲模式
    TIM_CR1(TIM6) |= TIM_CR1_OPM;

    // 定时器时钟 = 输入时钟 / (PSC+1) = 12.288MHz / 1024 = 12 kHz
    TIM_PSC(TIM6) = 1023;

    // 定时500ms的计数值 = 500 ms * 12 kHz = 6000
    TIM_ARR(TIM6) = 6000;

    // 将计数器TIM_CNT(TIM6)清0
    TIM_EGR(TIM6) |= TIM_EGR_UG;

    // 清除更新中断标志
    TIM_SR(TIM6) = 0;

    // 允许更新中断
    TIM_DIER(TIM6) = 0;
    TIM_DIER(TIM6) |= TIM_DIER_UIE;

    // 开TIM6中断
    NVIC_EnableIRQ(TIM6_DAC_IRQn);
}

//-----------------------------------------------------------------------------
// TIM6中断服务程序
//-----------------------------------------------------------------------------
void TIM6_DAC_IRQHandler(void)
{
    // 清除更新中断标志
    TIM_SR(TIM6) = 0;

    // PC6 = 1
    DEV_GPIO_BitSet(GPIOC, GPIO_PIN_6);
}
相关推荐
xuxg20052 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT3 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen4 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠6 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_6 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技9 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计9 小时前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
風清掦10 小时前
【江科大STM32学习笔记-05】EXTI外部中断11
笔记·stm32·学习
小龙报10 小时前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业10 小时前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件