从51到STM32:PWM平滑迁移方案
引言
对于习惯使用51单片机的开发者而言,转向STM32时可能会面临开发环境和硬件差异的挑战。本文以PWM(脉宽调制)功能为例,分享从51到STM32的平滑迁移方案,帮助开发者快速适应STM32的开发模式。
一、PWM实现原理对比
1.1 51单片机的PWM实现
在51中,通常通过定时器中断+手动翻转IO电平实现PWM:
// 51示例代码(定时器0模式1)
void Timer0_Init() {TMOD &= 0xF0;TMOD |= 0x01; // 定时器0模式1TH0 = 0xFF; // 重载值TL0 = 0xFF;ET0 = 1; // 开启定时器中断EA = 1;TR0 = 1;
}void Timer0_ISR() interrupt 1 {static uint8_t pwm_count = 0;TH0 = 0xFF; // 重置计时值TL0 = 0xFF;pwm_count++;if(pwm_count == duty_cycle) {PWM_PIN = 0; // 拉低电平} else if(pwm_count == period) {PWM_PIN = 1; // 拉高电平pwm_count = 0;}
}
1.2 STM32的硬件PWM优势
STM32内置硬件PWM模块,通过定时器自动输出波形,无需CPU干预:
-
更高精度(16位计数器)
-
多通道同步输出
-
支持互补输出(用于电机控制)
-
自动重载减少中断开销
二、迁移关键步骤
2.1 硬件资源映射
| 51资源 | STM32等效资源 |
|---|---|
| 定时器0 | TIM1/TIM2/TIM3等 |
| IO引脚 | 支持复用的TIMx_CHx引脚 |
2.2 配置步骤对比
51单片机流程:
-
配置定时器模式
-
设置中断服务程序
-
手动控制IO电平
STM32标准库流程:
-
启用时钟(TIMx和GPIO)
-
配置定时器基本参数
-
设置PWM模式
-
配置输出比较单元
-
启动定时器
三、STM32 PWM配置示例(标准库)
3.1 初始化代码
// 以TIM3_CH2(PA7)为例
void PWM_Init(uint16_t arr, uint16_t psc) {GPIO_InitTypeDef GPIO_InitStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;TIM_OCInitTypeDef TIM_OCInitStruct;// 1. 开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 2. 配置GPIOGPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);// 3. 配置定时器基础TIM_TimeBaseStruct.TIM_Period = arr; // 自动重装载值TIM_TimeBaseStruct.TIM_Prescaler = psc; // 预分频系数TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);// 4. 配置PWM模式TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStruct.TIM_Pulse = 0; // 初始占空比TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OC2Init(TIM3, &TIM_OCInitStruct); // 通道2// 5. 启动定时器TIM_Cmd(TIM3, ENABLE);
}// 设置占空比
void PWM_SetDuty(uint16_t duty) {TIM_SetCompare2(TIM3, duty);
}
3.2 使用HAL库简化开发(CubeMX生成)
// 使用CubeMX配置后自动生成代码
void MX_TIM3_Init(void) {htim3.Instance = TIM3;htim3.Init.Prescaler = 71; // 72MHz/(71+1)=1MHzhtim3.Init.CounterMode = TIM_COUNTERMODE_UP;htim3.Init.Period = 999; // 1MHz/1000=1kHz PWMhtim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;HAL_TIM_PWM_Init(&htim3);TIM_OC_InitTypeDef sConfigOC;sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 500; // 初始占空比50%sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
}
四、迁移注意事项
-
时钟树配置:STM32需明确时钟源和分频系数
-
占空比计算:STM32占空比 = (Pulse / (Period+1)) * 100%
-
引脚复用功能:必须通过AFIO配置复用模式
-
中断优先级:若使用PWM中断,需配置NVIC
-
硬件滤波:STM32支持PWM输出滤波(TIMx_CCMRx寄存器)
五、调试技巧
-
使用示波器验证波形频率和占空比
-
通过STM32CubeMX可视化配置参数
-
利用调试器实时修改变量值(如Period/Pulse)
-
结合DMA实现无CPU干预的PWM控制
总结
从51到STM32的PWM开发迁移,核心在于从软件模拟转向硬件外设的思维转变。通过合理利用STM32的硬件定时器资源,不仅可以减少CPU开销,还能实现更高精度的PWM控制。建议结合STM32CubeMX工具快速入门,再逐步深入理解寄存器级配置。
如果从来没有用过stm32推荐观看STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili
来配置文件。51是配置寄存器,stm32官方有标准库可以调用,开发更加方便。
相关文章:
从51到STM32:PWM平滑迁移方案
引言 对于习惯使用51单片机的开发者而言,转向STM32时可能会面临开发环境和硬件差异的挑战。本文以PWM(脉宽调制)功能为例,分享从51到STM32的平滑迁移方案,帮助开发者快速适应STM32的开发模式。 一、PWM实现原理对比 …...
openCV中如何实现滤波
图像滤波用于去除噪声和图像平滑,OpenCV 提供了多种滤波器: 1.1. 均值滤波: import cv2# 读取图像 image cv2.imread("example.jpg")# 均值滤波 blurred_image cv2.blur(image, (5, 5)) # (5, 5) 是滤波核的大小 滤波核大小的…...
BGP配置华为——路由汇总
实验拓扑 实验要求 1.R1,R2,R3间运行BGP,搭建EBGP邻居 2.R3一段的网络实现自动聚合,R1一端的网络实现手动路由聚合 3.启用as-set防环 实验配置 配置相关IP 过程省略,结果如图 R1 R2 R3 配置EBGP [R1]bgp 100 [R1-bgp]router 10.10.1…...
机器学习核心算法解析
机器学习核心算法解析 机器学习是人工智能的核心技术之一,它通过从数据中学习模式并做出预测或决策。本文将深入解析机器学习的核心算法,包括监督学习、无监督学习和强化学习,并通过具体案例和代码示例帮助读者理解这些算法的实际应用。 1. …...
【C++学习篇】C++11
目录 编辑 1. 初始化列表{} 1.1 C98中的{} 1.2 C11中的{} 2. C11中的std::initializer_list 3. 右值引用和移动语义 3.1 左值和右值 3.2 左值引用和右值引用 3.3 引用延长生命周期 3.4 左值和右值的参数匹配 3.5 右值引⽤和移动语义的使⽤场景 3.5.1 左值引⽤…...
SQLite 数据库:优点、语法与快速入门指南
文章目录 一、引言二、SQLite 的优点 💯三、SQLite 的基本语法3.1 创建数据库3.2 创建表3.3 插入数据3.4 查询数据3.5 更新数据3.6 删除数据3.7 删除表 四、快速入门指南4.1 安装 SQLite4.2 创建数据库4.3 创建表4.4 插入数据4.5 查询数据4.6 更新数据4.7 删除数据4…...
数据结构——二叉树(2025.2.12)
目录 一、树 1.定义 (1)树的构成 (2)度 2.二叉树 (1)定义 (2)二叉树的遍历 (3)遍历特性 二、练习 1.二叉树 (1)创建二叉树…...
图神经网络简介
一、说明 本文介绍了GNN网络一些要素,其中与CNN进行过一些对比,并且对GNN的一些统计原理进行介绍。 二、介绍 对于不同类型的训练数据集,卷积神经网络 (CNN) 擅长处理方形或网格状或欧几里得结构化数据,…...
小程序报错The JavaScript function Pointer_stringify(ptrToSomeCString)
小程序报错The JavaScript function Pointer _stringify(ptrToSomeCString) 介绍修改地址总结 介绍 这个报错是我在打包小程序在手机上运行时报的错,这个地方问题是个小问题,其实就是Pointer_stringify(ptrToSomeCString) 函数过时…...
DeepSeek 与网络安全:AI 驱动的智能防御
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 随着人工智能(AI)的快速发展,深度学习技术正渗透到多个领域,从医疗诊断到…...
Redission看门狗
在 Redisson 中,lock.tryLock() 和 lock.lock() 是两种不同的加锁方式,它们的行为有所不同: lock.lock():这是阻塞方法,当调用时,如果锁当前不可用,线程将被阻塞,直到获取到锁。如果…...
LeetCode 热题 100_组合总和(58_39_中等_C++)(递归(回溯))
LeetCode 热题 100_组合总和(58_39) 题目描述:输入输出样例:题解:解题思路:思路一(递归(回溯)): 代码实现代码实现(思路一(…...
使用PHP爬虫获取1688商品分类:实战案例指南
在电商领域,商品分类信息是商家进行市场调研、选品分析和竞争情报收集的重要基础。1688作为国内领先的B2B电商平台,提供了丰富且详细的商品分类数据。通过PHP爬虫技术,我们可以高效地获取这些分类信息,为商业决策提供有力支持。 …...
Nginx location 和 proxy_pass 配置详解
概述 Nginx 配置中 location 和 proxy_pass 指令的不同组合方式及其对请求转发路径的影响。 配置效果 1. location 和 proxy_pass 都带斜杠 / location /api/ {proxy_pass http://127.0.0.1:8080/; }访问地址:www.hw.com/api/upload转发地址:http://…...
云创智城充电系统:基于 SpringCloud 的高可用、可扩展架构详解-多租户、多协议兼容、分账与互联互通功能实现
在新能源汽车越来越普及的今天,充电基础设施的管理和运营变得越来越重要。云创智城充电系统,就像一个超级智能管家,为新能源充电带来了全新的解决方案,让充电这件事变得更方便、更高效、更安全。 一、厉害的技术架构,让…...
AIP-143 标准代号
编号143原文链接AIP-143: Standardized codes状态批准创建日期2019-07-24更新日期2019-07-24 许多常见的概念,如语言、国家、货币等,都有用于数据通信和处理的通用代号(通常由国际标准化组织正式定义)。这些代号解决了在书面语言…...
机器视觉--数字图像格式
图像格式 在数字图像的世界里,不同的图像格式有着各自的特点和适用场景。了解这些图像格式,对于我们在处理图像时选择合适的存储和传输方式至关重要。下面就让我们来详细探讨一下常见的几种数字图像格式。 一、BMP 文件(Bitmap)…...
Kotlin 2.1.0 入门教程(十七)接口
接口 接口可以包含抽象方法的声明,也可以包含方法的实现。 接口与抽象类的不同之处在于,接口无法存储状态。接口可以拥有属性,但这些属性要么必须是抽象的,要么就得提供访问器的实现。 接口使用 interface 关键字来定义&#x…...
渗透测试工具:SQLmap安装教程及使用
在渗透测试的世界里,SQL注入攻击无疑是最常见且最具威胁的安全漏洞之一。幸运的是,SQLmap 这个强大的自动化工具,能够帮助我们快速识别和利用这些漏洞。如果你也想了解如何用 SQLmap 进行渗透测试,那么这篇文章就是为你准备的&…...
4.SpringSecurity在分布式环境下的使用
参考 来源于黑马程序员: 手把手教你精通新版SpringSecurity 分布式认证概念说明 分布式认证,即我们常说的单点登录,简称SSO,指的是在多应用系统的项目中,用户只需要登录一次,就可以访 问所有互相信任的应…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
