• Air001 TIM16通用定时器作PWM输出和延时使用配置方法


    Air001 TIM16通用定时器作PWM输出和延时使用配置方法


    • ✨本文将通过2个工程配置案例分别实现:TIM16通用定时器作PWM输出和延时使用。
    • 👉🏻本次利用STM32CubeMX工具,选择一款M0内核的芯片,配置一个所需功能的工程,然后从所生成的工程中将所需的目标驱动文件拷贝到Air001工程中使用,这样就快速部署完成了一个所需功能的工程框架。可以避免自己手写配置出bug的可能,通用性还是非常高,甚至PWM输出映射引脚都不需要做修改,当然也不排除STM32CubeMX生成的代码有bug问题。
    • 🔰对于代码通用性,一定要参照Air001数据手册上的资源外设描述对比来确定,不能盲从。

    🔖通过现有的SDK资源,所能提供的公开资料里面,只有定时器1和定时器3的相关内容,结合数据手册上看,定时器16/17作为通用定时器,还是有一些差异。
    在这里插入图片描述

    • 🌿查看Air001芯片数据手册,定时器16 PWM输出通道1,PA6引脚复用AF5,与STM32F030R8,一致,如果是其他定时器,不一样的话,需要注意修改对应的复用引脚。
      在这里插入图片描述
      在这里插入图片描述
    • 🌿对应生成的代码:
      在这里插入图片描述

    🛠STM32CubeMX配置定时器16 PWM功能选项

    • 🔖这里以STM32F030R8T6为例。

    • 🌿配置定时器16参数,对应PWM功能,主要是使能定时器以及选择通道,其他参数根据需求配置即可。
      在这里插入图片描述
      在这里插入图片描述

    • 🔧配置好后,生成独立的.c和.h文件
      在这里插入图片描述

    • 🌿找到工程生成文件目录,驱动文件分别在srcinc文件夹内,拷贝对应的tim.ctim.h文件到,Air001工程项目中使用。

    • 🌿回到Air001工程,将tim.c添加进来,将头文件路径包含进来,需要修改的地方,主要是调整主时钟频率,对应PWM频率和占空比根据个人需求修改即可。
      在这里插入图片描述

    • 🔧这样一个基本的工程框架就搭建好了。
    • 📝main主程序
    int main(void)
    {
        uint16_t plusewidth = 5000;//脉冲宽度;f=1000 000/5000=200Hz
        uint16_t plusedelay = 500;//脉宽
        /* 初始化所有外设,Flash接口,SysTick */
        HAL_Init();
    
        /* 系统时钟配置 */
        APP_SystemClockConfig();
        MX_GPIO_Init();
        MX_TIM16_Init();
        __HAL_TIM_SET_AUTORELOAD(&htim16, plusewidth - 1); //调整分频系数,可以改变arr以改变频率
        __HAL_TIM_SET_COMPARE(&htim16, TIM_CHANNEL_1, plusedelay); //PWM脉冲宽度,修改占空比比较值
    
            HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
    //    if(HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1) != HAL_OK)
    //    {
    //        Error_Handler();
    //    }
    
        while(1)
        {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 🌿PA7引脚PWM信息:
      在这里插入图片描述
    • 📚工程代码
    链接:https://pan.baidu.com/s/1FboUjQMLb1pQu2coVDlh3Q 
    提取码:xqpn
    
    • 1
    • 2

    📓Air001 TIM16通用定时器作延时使用

    • 🔖配置工程方法,可以如法炮制。
    • STM32CubeMX工具,配置定时器相关参数:
      在这里插入图片描述
    • 🌿步骤步骤重复,参考上面的方法导入到Air001工程中即可。
    • 🔨在tim.c中添加如下延时函数内容,并将函数名拷贝到tim.h中。
    /* USER CODE BEGIN 1 */
    //us级延时函数
    //us需要延时的us数
    void delay_us(uint16_t us)
    {
    	uint16_t n;
    	n = us/100;//修正误差值
    	//设置定时器预分频系数,TIM16时钟为8MHz,分频后时钟为1MHz即1us
        //不同CPU的时钟可能不一样,PSC的值=定时器时钟/1MHz -1
        //8M的定时器设置PSC为8-1
    	TIM16->PSC = (8 -1);
    	//设置自动重装载值,定时器计数器的值自增到ARR时,会产生更新事件,ARR的值就是需要延时的时间
    	
    	TIM16->ARR = us - 2*n;
    	
    	//重新初始化定时器计数器并生成寄存器更新事件,确保预分频值被采用,此时定时器将采用刚刚写入的预分频值,如果此处不更新,那么定时器需要等待下次更新事件的到来才会重新加载预分频值
    	TIM16->EGR |= (1<<0);
    	//清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零
    	TIM16->SR = 0;
    	
    	//CR1的bit3(OPM)置一,计数器在发生下一更新事件时停止计数,单脉冲模式
    	TIM16->CR1 |= (1<<3);
    	//CR1的bit0(CEN)置一,启动定时器开始计数
    	TIM16->CR1 |= (1<<0);
    	//等待更新事件到来,计数器的值自增到自动重装载寄存器的时候,会产生更新事件,此时延时时间已到
    	while((TIM16->SR & 0x01)==0);
    	//清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零
    	TIM16->SR &= ~(1<<0);
    }
     
    //ms级延时函数
    //最大延时时间 65535ms
    void delay_ms(uint16_t ms)
    {
    	//设置定时器预分频系数,TIM16时钟为8MHz,分频后时钟为1KHz即1ms
        //不同CPU的时钟可能不一样
    	TIM16->PSC = (8000-1);//8000 000/8000=1KHz
    	//设置自动重装载值,定时器计数器的值自增到ARR时,会产生更新事件,ARR的值就是需要延时的时间的一半
    	TIM16->ARR = ms;
    	
    	//重新初始化定时器计数器并生成寄存器更新事件,确保预分频值被采用,此时定时器将采用刚刚写入的预分频值,如果此处不更新,那么定时器需要等待下次更新事件的到来才会重新加载预分频值
    	TIM16->EGR |= (1<<0);
    	//清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零
    	TIM16->SR = 0;
    	
    	//CR1的bit3(OPM)置一,计数器在发生下一更新事件时停止计数,单脉冲模式
    	TIM16->CR1 |= (1<<3);
    	//CR1的bit0(CEN)置一,启动定时器开始计数
    	TIM16->CR1 |= (1<<0);
    	//等待更新事件到来,计数器的值自增到自动重装载寄存器的时候,会产生更新事件,此时延时时间已到
    	while((TIM16->SR & 0x01)==0);
    	//清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零
    	TIM16->SR &= ~(1<<0);
    }
    
    /* USER CODE END 1 */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 📝main函数:
    int main(void)
    {
    
        /* 初始化所有外设,Flash接口,SysTick */
        HAL_Init();
        /* 初始化GPIO */
        MX_GPIO_Init();
        /* 系统时钟配置 */
        APP_SystemClockConfig();
        MX_TIM16_Init();
        while(1)
        {
            /* LED翻转 */
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
            delay_us(500);
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
            delay_ms(250); /* 延时250ms */
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
            delay_ms(250); /* 延时250ms */
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
            delay_us(500);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 🎞采集的PB3引脚的波形:
      在这里插入图片描述
    • 📚定时器16作延时函数使用工程
    链接:https://pan.baidu.com/s/132W6L3jC1196mrcDzrC3qg 
    提取码:onsu
    
    • 1
    • 2
    ✨按照上述方法和实现原理,对于Air001 定时器17,配置相同功能的方法一样,这里不再赘述。

    🌼定时器16 微秒延时配置

    #define DLY_TIM_Handle  (&htim16)
    TIM_HandleTypeDef htim16;
    /* TIM16 init function */
    void MX_TIM16_Init(void)
    {
    
        /* USER CODE BEGIN TIM16_Init 0 */
    
        /* USER CODE END TIM16_Init 0 */
        __HAL_RCC_TIM16_CLK_ENABLE();
    
        /* USER CODE BEGIN TIM16_Init 1 */
    
        /* USER CODE END TIM16_Init 1 */
        htim16.Instance = TIM16;
        htim16.Init.Prescaler = 8 - 1;//配置8MHz时钟主频情况下
        htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
        htim16.Init.Period = 65535;
        htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        htim16.Init.RepetitionCounter = 0;
        htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
        if(HAL_TIM_Base_Init(&htim16) != HAL_OK) {
            Error_Handler();
        }
    
    
        /* USER CODE BEGIN TIM16_Init 2 */
    
        /* USER CODE END TIM16_Init 2 */
    
    
    }
    void delay_us(uint16_t nus)
    {
        __HAL_TIM_SET_COUNTER(DLY_TIM_Handle, 0);
        __HAL_TIM_ENABLE(DLY_TIM_Handle);
        while(__HAL_TIM_GET_COUNTER(DLY_TIM_Handle) < nus) {
        }
        __HAL_TIM_DISABLE(DLY_TIM_Handle);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    📗利用滴答定时器实现微秒级延时

    • 📍参考:https://blog.csdn.net/qq153471503/article/details/102930097
    #define CPU_FREQUENCY_MHZ    8		// 时钟主频
    void delay_us(__IO uint32_t delay)
    {
        int last, curr, val;
        int temp;
    
        while (delay != 0)
        {
            temp = delay > 900 ? 900 : delay;
            last = SysTick->VAL;
            curr = last - CPU_FREQUENCY_MHZ * temp;
            if (curr >= 0)
            {
                do
                {
                    val = SysTick->VAL;
                }
                while ((val < last) && (val >= curr));
            }
            else
            {
                curr += CPU_FREQUENCY_MHZ * 1000;
                do
                {
                    val = SysTick->VAL;
                }
                while ((val <= last) || (val > curr));
            }
            delay -= temp;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述


    • 🔖此文章仅作为个人学习探索知识的总结,不作为他人引用者的理论依据,由于学识所限,难免会出现错误或纰漏,欢迎大家指正。
  • 相关阅读:
    中国智慧城市研究战略及十四五规划分析报告2022-2028年新版
    【Maven教程】(九):使用 Maven 进行测试 ~
    如何理解深度学习的训练过程
    仿制 Google Chrome 的恐龙小游戏
    Java进阶篇--AQS(AbstractQueuedSynchronizer)
    【洛谷 P1591】阶乘数码 题解(模拟+高精度)
    黑白简约个人网页制作 大学生个人网页设计模板 学生个人博客网页成品 简单个人网站作品下载 静态HTML CSS个人网页作业源代码
    2022年认证杯SPSSPRO杯数学建模B题(第二阶段)唐宋诗的定量分析与比较研究求解全过程文档及程序
    力扣(LeetCode)13. 罗马数字转整数(C++)
    SQL Try Catch
  • 原文地址:https://blog.csdn.net/weixin_42880082/article/details/133799560