STM32的HAL库开发---高级定时器---输出比较模式实验

news2025/2/11 9:48:08

一、高级定时器输出比较模式实验原理

定时器的输出比较模式总共有8种,本文使用其中的翻转模式,当TIMXCCR1=TIMXCNT时,翻转OC1REF的电平,OC1REF为输出参考信号,高电平有效,OC1REF信号连接到0C1上面,然后控制CH1输出,CH1通过IO口复用功能,连接到IO口上面,最后输出到外部。

计时器工作在递增模式:

当CNT的值不断递增,递增到于输出比较寄存器CCR1的值相同时,IO电平翻转,然后CNT值继续递增,递增到ARR时,产生计数器溢出事件,计数器值从0开始重新递增,通过这种方式产生方波或者称为PWM波。

周期:IO口输出高电平和低电平总和为一个方波周期,从图上可以看出,一个方波周期为两次计数器溢出的事件,也就是2*(ARR + 1)*t,t为计时器计一个数所需时间。

占空比:再翻转模式下,占空比固定为50%,不可以改变。

总结:PWM波周期或频率由ARR决定,占空比固定50%,相位由CCRX决定。

二、高级定时器输出比较模式实验配置步骤

1、HAL_TIM_OC_Init()函数,配置定时器基础工作参数。

2、HAL_TIM_OC_Msplnit()函数,配置NVIC、CLOCK、GPIO等

3、HAL_TIM_OC_Configchannel()函数,配置输出比较模式。

4、__HAL_TIM_ENABLE_OCxPRELOAD()宏定义,使能通道预装载。

5、HAL_TIM_OC_Start()函数,使能输出、主输出、计数器。

6、__HAL_TIM_SET_COMPARE()宏定义,修改捕获/比较寄存器的值。

三、高级定时器输出比较模式实验

实验:通过定时器8通道1/2/3/4输出相位分别为25%50%75%100%PWM

1、寄存器版本

#include "./BSP/TIMER/atim.h"

//配置定时器8通道1 PC6、PC7、PC8、PC9为翻转模式输出
void Advanced_TIM_Init(void)
{
	//开启TIM8时钟
	RCC->APB2ENR |= (1 << 13);
	
	//开启ARR寄存器缓冲功能
	TIM8->CR1 |= (1 << 7);
	
	//设置PSC预分频系数
	TIM8->PSC = 71;
	
	//设置重装载寄存器值 配置PWM方波为500HZ
	//在翻转模式下 两个ARR溢出时间为PWM一个周期
	TIM8->ARR = (1000000 / (500 * 2)) - 1;
	
	/**************TIM8_CH1*****************/
	//CC1S 设置捕获比较为输出模式
	TIM8->CCMR1 &= ~(0x03 << 0);
	
	//OC1PE 开启输出比较寄存器预装载功能
	TIM8->CCMR1 |= (1 << 3);
	
	//OC1M 设置为翻转模式
	TIM8->CCMR1 |= (0X03 << 4);
	TIM8->CCMR1 &= ~(1 << 6);
		
	//设置CCR1捕获/比较寄存器值 25%相位
	TIM8->CCR1 = 0.25 * (1000000 / (500 * 2)) - 1;
	//TIM8->CCR1 =1;
	
	//设置输出极性为高电平有效 CC1P
	TIM8->CCER &= ~(1 << 1);
	
	//使能输出比较 CC1E
	TIM8->CCER |= (1 << 0);
	
	/**************TIM8_CH2*****************/
	//CC2S 设置捕获比较为输出模式
	TIM8->CCMR1 &= ~(0x03 << 8);
	
	//OC2PE 开启输出比较寄存器预装载功能
	TIM8->CCMR1 |= (1 << 11);
	
	//OC2M 设置为翻转模式
	TIM8->CCMR1 |= (0X03 << 12);
	TIM8->CCMR1 &= ~(1 << 14);		
	
	//设置CCR2捕获/比较寄存器值 50%相位
	TIM8->CCR2 = 0.50 * (1000000 / (500 * 2)) - 1;
	
	//设置输出极性为高电平有效 CC2P
	TIM8->CCER &= ~(1 << 5);
	
	//使能输出比较 CC2E
	TIM8->CCER |= (1 << 4);
	
	/**************TIM8_CH3*****************/
	//CC3S 设置捕获比较为输出模式
	TIM8->CCMR2 &= ~(0x03 << 0);
	
	//OC3PE 开启输出比较寄存器预装载功能
	TIM8->CCMR2 |= (1 << 3);
	
	//OC3M 设置为翻转模式
	TIM8->CCMR2 |= (0X03 << 4);
	TIM8->CCMR2 &= ~(1 << 6);
		
	//设置CCR3捕获/比较寄存器值 75%相位
	TIM8->CCR3 = 0.75 * (1000000 / (500 * 2)) - 1;
	
	//设置输出极性为高电平有效 CC3P
	TIM8->CCER &= ~(1 << 9);
	
	//使能输出比较 CC3E
	TIM8->CCER |= (1 << 8);
	
	/**************TIM8_CH4*****************/
	//CC4S 设置捕获比较为输出模式
	TIM8->CCMR2 &= ~(0x03 << 8);
	
	//OC4PE 开启输出比较寄存器预装载功能
	TIM8->CCMR2 |= (1 << 11);
	
	//OC4M 设置为翻转模式
	TIM8->CCMR2 |= (0X03 << 12);
	TIM8->CCMR2 &= ~(1 << 14);	
	
	//设置CCR4捕获/比较寄存器值 100%相位
	TIM8->CCR4 = 1 * (1000000 / (500 * 2)) - 1;
	
	//设置输出极性为高电平有效 CC4P
	TIM8->CCER &= ~(1 << 13);
	
	//使能输出比较 CC4E
	TIM8->CCER |= (1 << 12);
	
	//软件更新事件  主要为将PSC的值转移到影子寄存器里边
	TIM8->EGR |= (1 << 0);
		
	//MOE 开启主输出
	TIM8->BDTR |= (1 << 15);

	//开启GPIOC时钟
	RCC->APB2ENR |= (1 << 4);
	
	//设置PC6为复用推挽输出
	GPIOC->CRL |= (0X03 << 24);
	GPIOC->CRL |= (1 << 27);
	GPIOC->CRL &= ~(1 << 26);
	
	//设置PC7为复用推挽输出
	GPIOC->CRL |= (0X03 << 28);
	GPIOC->CRL |= (1 << 31);
	GPIOC->CRL &= ~(1 << 30);
	
	//设置PC8为复用推挽输出
	GPIOC->CRH |= (0X03 << 0);
	GPIOC->CRH |= (1 << 3);
	GPIOC->CRH &= ~(1 << 2);
	
	//设置PC9为复用推挽输出
	GPIOC->CRH |= (0X03 << 4);
	GPIOC->CRH |= (1 << 7);
	GPIOC->CRH &= ~(1 << 6);
	
	//使能计数器
	TIM8->CR1 |= (1 << 0);	
	
}




2、库函数版本

 atim.h头文件程序

#ifndef __ATIM_H
#define __ATIM_H

#include "stm32f1xx.h"
void Advanced_TIM_Init(void);

#endif

atim.c

#include "./BSP/TIMER/atim.h"

//配置定时器8通道1 PC6为翻转模式输出
TIM_HandleTypeDef htim;
void Advanced_TIM_Init(void)
{
	htim.Instance = TIM8;
	htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	htim.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim.Init.Period = 1000000/(500 * 2) - 1;
	htim.Init.Prescaler = 71;
	
	HAL_TIM_OC_Init(&htim);
	
	TIM_OC_InitTypeDef sConfig = {0};
	
	sConfig.OCMode = TIM_OCMODE_TOGGLE;
	sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
	sConfig.Pulse =  0.25 * (TIM8->ARR + 1) - 1;
	
	//配置TIM8 CH1为翻转输出模式
	HAL_TIM_OC_ConfigChannel(&htim,&sConfig,TIM_CHANNEL_1);
	
	//配置TIM8 CH2为翻转输出模式
	sConfig.Pulse = 0.50 * (TIM8->ARR + 1) - 1;
	HAL_TIM_OC_ConfigChannel(&htim,&sConfig,TIM_CHANNEL_2);
	
	//配置TIM8 CH3为翻转输出模式
	sConfig.Pulse = 0.75 * (TIM8->ARR + 1) - 1;
	HAL_TIM_OC_ConfigChannel(&htim,&sConfig,TIM_CHANNEL_3);
	
	//配置TIM8 CH4为翻转输出模式
	sConfig.Pulse = 1 * TIM8->ARR;
	HAL_TIM_OC_ConfigChannel(&htim,&sConfig,TIM_CHANNEL_4);
	
	//使能捕获/比较寄存器通道1预装载
	__HAL_TIM_ENABLE_OCxPRELOAD(&htim,TIM_CHANNEL_1);
	
	//使能捕获/比较寄存器通道2预装载
	__HAL_TIM_ENABLE_OCxPRELOAD(&htim,TIM_CHANNEL_2);
	
	//使能捕获/比较寄存器通道3预装载
	__HAL_TIM_ENABLE_OCxPRELOAD(&htim,TIM_CHANNEL_3);
	
	//使能捕获/比较寄存器通道4预装载
	__HAL_TIM_ENABLE_OCxPRELOAD(&htim,TIM_CHANNEL_4);
	
	TIM8->EGR |= (1 << 0);
	
	//启动TIM8 CH1计数器 主输出 输出比较
	HAL_TIM_OC_Start(&htim, TIM_CHANNEL_1);
	
	//启动TIM8 CH2计数器 主输出 输出比较
	HAL_TIM_OC_Start(&htim, TIM_CHANNEL_2);
	
	//启动TIM8 CH3计数器 主输出 输出比较
	HAL_TIM_OC_Start(&htim, TIM_CHANNEL_3);
	
	//启动TIM8 CH4计数器 主输出 输出比较
	HAL_TIM_OC_Start(&htim, TIM_CHANNEL_4);
}

void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
{
	//开启定时器8时钟
	__HAL_RCC_TIM8_CLK_ENABLE();
	
	//开启GPIOC时钟
	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	GPIO_InitTypeDef GPIO_Init = {0};
	
	GPIO_Init.Mode = GPIO_MODE_AF_PP;
	GPIO_Init.Pin = GPIO_PIN_6;
	//设置为输出模式时 这个没有用 可以不写 
	GPIO_Init.Pull = GPIO_NOPULL;
	GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
	
	//设置PC6为复用推挽输出
	HAL_GPIO_Init(GPIOC, &GPIO_Init);
	
	GPIO_Init.Pin = GPIO_PIN_7;
	//设置PC7为复用推挽输出
	HAL_GPIO_Init(GPIOC, &GPIO_Init);
	
	GPIO_Init.Pin = GPIO_PIN_8;
	//设置PC8为复用推挽输出
	HAL_GPIO_Init(GPIOC, &GPIO_Init);
	
	GPIO_Init.Pin = GPIO_PIN_9;
	//设置PC9为复用推挽输出
	HAL_GPIO_Init(GPIOC, &GPIO_Init);
	
}

 main.c主函数程序

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/atim.h"

extern TIM_HandleTypeDef htim;
int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
	sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    led_Init();                         /* LED初始化 */
	Advanced_TIM_Init();				//高级定时器初始化
//	__HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, 0);
//    __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_2, 500 - 1);
//    __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_3, 750 - 1);
//    __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_4, 1000 - 1);
    while(1)
    { 
		LED0(1);
		LED1(0);
		delay_ms(500);
		
		LED0(0);
		LED1(1);
		delay_ms(500);
    }
}

在配置过程中发现,如果捕获比较寄存器的值在初始化的时候设置成0,会导致相位错误,设置成1就不会。但是在初始化之后再将比较寄存器的值设置成0,相位正确。这个问题具体原因还没找到,如果有人有思路,可以私信我。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2295418.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[论文阅读] Knowledge Fusion of Large Language Models

Knowledge Fusion of Large Language Models (FuseLLM) Methodology 整体Pipeline如下图所示 不同的动物代表不同的LLM。左边第一&#xff0c;第二分别是Ensemble以及Weight Merging方法。最右侧为本文提出的FuseLLM。 Ensemble: 融合多个models的预测结果&#xff0c;比如…

elementui:el-table支持搜索、切换分页多选功能,以及数据回显

1、el-table相关代码&#xff0c;需注意:row-key"(row) > { return row.id }" 以及 :reserve-selection"true" <div class"boxList"><div class"search-form"><!-- 搜索表单 --><el-form :inline"true&q…

(ICLR=2025)生成的表征对齐:训练扩散Transformer比你想象的更简单

生成的表征对齐&#xff1a;训练扩散Transformer比你想象的更简单 paper是KAIST发表在ICLR 2025的工作 paper title:REPRESENTATION ALIGNMENT FOR GENERATION: TRAINING DIFFUSION TRANSFORMERS IS EASIER THAN YOU THINK Code&#xff1a;链接 ABSTRACT 最近的研究表明&…

白嫖RTX 4090?Stable Diffusion:如何给线稿人物快速上色?

大家都知道&#xff0c;在设计的初期&#xff0c;我们通常会先绘制草图&#xff0c;然后再进行上色处理&#xff0c;最终才开始进行最终的设计工作。在这个上色的过程中&#xff0c;配色是至关重要的一环。这不仅方便了内部同事的评审&#xff0c;也让产品方和客户可以直观地了…

Bash (Bourne-Again Shell)、Zsh (Z Shell)

文章目录 1. 历史背景2. 主要区别3. 功能对比自动补全插件和主题路径扩展提示符定制 4. 性能5. 使用场景6. 如何切换 Shell7. 总结 以下是 Bash 和 Zsh 之间的主要区别&#xff0c;列成表格方便对比&#xff1a; 特性BashZsh默认Shell大多数Linux发行版默认ShellmacOS默认She…

pikachu[皮卡丘] 靶场全级别通关教程答案 以及 学习方法 如何通过渗透测试靶场挑战「pikachu」来精通Web渗透技巧? 一篇文章搞完这些问题

目录 Pikachu靶场 部署 暴力破解漏洞 学习地址: 靶场练习: 基于表单的暴力破解 验证码绕过(on server) 验证码绕过(on Client) token防爆破? XSS跨站脚本攻击 学习地址: 靶场练习&#xff1a; 反射型xss(get) 反射性xss(post) 存储型xss DOM型xss xss盲打 x…

汽车零部件工厂如何借助安灯呼叫按钮盒提升生产响应速度

在现代汽车零部件工厂的生产环境中&#xff0c;高效的信息传递和快速的响应速度是确保生产顺畅运行的关键。然而&#xff0c;传统的口头呼喊或现场沟通方式往往存在信息传递慢、现场嘈杂、责任人难以及时找到等问题&#xff0c;尤其在设备故障或缺料时&#xff0c;这些问题会导…

Idea 2024.3 使用CodeGPT插件整合Deepseek

哈喽&#xff0c;大家好&#xff0c;我是浮云&#xff0c;最近国产大模型Deepseek异常火爆&#xff0c;作为程序员我也试着玩了一下&#xff0c;首先作为简单的使用&#xff0c;大家进入官网&#xff0c;点击开始对话即可进行简单的聊天使用&#xff0c;点击获取手机app即可安装…

「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

docker /var/lib/docker/overlay2目录把磁盘空间占满问题

1、查看服务器磁盘空间 df -h果然100%了,docker系统文件把磁盘空间占满了。 2、进入overlay2目录&#xff0c;查找那个容器工作目录占用最高 cd /var/lib/docker/overlay2du -h --max-depth1详见下图 好家伙占用110G&#xff01;复制目录名称2c3c48ccac533c5d4a366d45a19bb9…

Redis深入学习

目录 Redis是什么&#xff1f; Redis使用场景 Redis线程模型 Redis执行命令是单线程的为什么还这么快&#xff1f; Redis持久化 Redis 事务 Key 过期策略 Redis 和 mysql 如何保证数据一致&#xff1f; 缓存穿透 缓存击穿 缓存雪崩 Redis是什么&#xff1f; redis是一…

EasyExcel 导出合并层级单元格

EasyExcel 导出合并层级单元格 一、案例 案例一 1.相同订单号单元格进行合并 合并结果 案例二 1.相同订单号的单元格进行合并2.相同订单号的总数和总金额进行合并 合并结果 案例三 1.相同订单号的单元格进行合并2.相同订单号的商品分类进行合并3.相同订单号的总数和总金额…

青少年编程与数学 02-009 Django 5 Web 编程 01课题、概要

青少年编程与数学 02-009 Django 5 Web 编程 01课题、概要 一、Django 5Django 5 的主要特性包括&#xff1a; 二、MVT模式三、官方网站四、内置功能数据库 ORM&#xff08;对象关系映射&#xff09;用户认证和授权表单处理模板引擎URL 路由缓存框架国际化和本地化安全性功能管…

2.7学习

crypto buu-还原大师 仔细阅读题目&#xff0c;这里有一段字符串&#xff0c;但是其中有四个大写字母被替换成了‘&#xff1f;’&#xff0c;那么我们写脚本&#xff1a;首先将四个问号均换成26个大写字母并且组成不同的组合&#xff0c; 所以有四个循环让四个问号都遍历26个…

oracle ORA-27054报错处理

现象 在oracle执行expdp&#xff0c;rman备份&#xff0c;xtts的时候,由于没有足够的本地空间&#xff0c;只能使用到NFS的文件系统但有时候会出现如下报错 ORA-27054: NFS file system where the file is created or resides is not mounted with correct options根据提示信…

使用LLaMA Factory踩坑记录

前置条件&#xff1a;电脑显卡RTX 4080 问题&#xff1a;LLaMA-Factory在运行的时候&#xff0c;弹出未检测到CUDA的报错信息 结论&#xff1a;出现了以上的报错&#xff0c;主要可以归结于以下两个方面&#xff1a; 1、没有安装GPU版本的pytorch&#xff0c;下载的是CPU版本…

电路研究9.3——合宙Air780EP中的AT开发指南(含TCP 示例)

根据合宙的AT研发推荐&#xff0c; AT指令基本上也简单看完了&#xff0c;这里开始转到AT的开发了。 AT 命令采用标准串口进行数据收发&#xff0c;将以前复杂的设备通讯方式转换成简单的串口编程&#xff0c; 大大简化了产品的硬件设计和软件开发成本&#xff0c;这使得几乎所…

Reqable使用实践

一、背景 日常开发中&#xff0c;难免要抓取请求数据&#xff0c;查看接口数据&#xff0c;从而更好定位问题&#xff0c;基于这个原因&#xff0c;查找了一些抓包工具&#xff0c;例如&#xff1a; HttpCanary、 Steam 、Fiddler等&#xff0c;不是要钱&#xff0c;就是只对苹…

【蓝桥杯嵌入式】2_LED

全部代码网盘自取 链接&#xff1a;https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码&#xff1a;3ii2 1、电路图 74HC573是八位锁存器&#xff0c;当控制端LE脚为高电平时&#xff0c;芯片“导通”&#xff0c;LE为低电平时芯片“截止”即将输出状态“锁存”…

B树详解及其C语言实现

目录 一、B树的基本原理 二、B树操作过程图形化演示 三、B树的应用场景 四、C语言实现B树及示例 五、代码执行结果说明 六、应用实例&#xff1a;文件系统目录索引 七、总结 一、B树的基本原理 B树&#xff08;B-Tree&#xff09; 是一种自平衡的树数据结构&#xff0c;…