stm32实战项目:无刷驱动

目录

系统时钟配置

PWM模块初始化

ADC模块配置

霍尔接口配置

速度环定时器

换相逻辑实现

主控制循环


系统时钟配置

  • 启用72MHz主频:RCC_Configuration()设置PLL
  • 外设时钟使能:TIM1/ADC/GPIO时钟
#include "stm32f10x.h"void RCC_Configuration(void)
{// 时钟复位配置RCC_DeInit();// 1. 开启HSE并等待就绪RCC_HSEConfig(RCC_HSE_ON);while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);// 2. 配置PLL:HSE作为源,9倍频RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);// 3. 设置FLASH预取指和等待周期(必须)FLASH_SetLatency(FLASH_Latency_2);FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);// 4. 时钟分频配置RCC_HCLKConfig(RCC_SYSCLK_Div1);    // AHB=72MHzRCC_PCLK1Config(RCC_HCLK_Div2);    // APB1=36MHzRCC_PCLK2Config(RCC_HCLK_Div1);    // APB2=72MHz// 5. 启动PLL并切换时钟源RCC_PLLCmd(ENABLE);while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while(RCC_GetSYSCLKSource() != 0x08);// 6. 外设时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 |    // TIM1时钟RCC_APB2Periph_ADC1 |    // ADC1时钟RCC_APB2Periph_GPIOA |   // GPIOA时钟(示例)RCC_APB2Periph_GPIOC,    // GPIOC时钟(示例)ENABLE);
}// 主函数初始化调用示例
int main(void)
{RCC_Configuration();// 其他初始化代码...while(1);
}

PWM模块初始化

  • 定时器1通道1-3配置:
    TIM_OCInitTypeDef.Pulse = 50%占空比
    TIM_BDTRInitStruct配置死区时间(50-100ns)
  • 互补输出使能:
    TIM_CCxNCmd(TIM1, ENABLE)
#include "stm32f10x.h"void PWM_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;TIM_OCInitTypeDef TIM_OCStruct;TIM_BDTRInitTypeDef TIM_BDTRStruct;// 1. GPIO配置(以PA8/PA7为例)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_7; // CH1/CH1NGPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);// 2. 定时器基础配置(72MHz时钟)RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);TIM_TimeBaseStruct.TIM_Period = 1000-1;      // ARR决定PWM频率TIM_TimeBaseStruct.TIM_Prescaler = 0;        // 无分频TIM_TimeBaseStruct.TIM_ClockDivision = 0;TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStruct);// 3. PWM通道配置(50%占空比)TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OCStruct.TIM_Pulse = 500; // 50% of ARR(1000)TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OC1Init(TIM1, &TIM_OCStruct); // 通道1TIM_OC2Init(TIM1, &TIM_OCStruct); // 通道2TIM_OC3Init(TIM1, &TIM_OCStruct); // 通道3// 4. 死区时间配置(约55.5ns)TIM_BDTRStruct.TIM_DeadTime = 0x04; // DTG=4: 4*Tdts (Tdts=13.89ns@72MHz)TIM_BDTRStruct.TIM_Break = TIM_Break_Disable;TIM_BDTRStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;TIM_BDTRStruct.TIM_OSSRState = TIM_OSSRState_Disable;TIM_BDTRStruct.TIM_OSSIState = TIM_OSSIState_Disable;TIM_BDTRStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;TIM_BDTRConfig(TIM1, &TIM_BDTRStruct);// 5. 互补输出使能TIM_CCxNCmd(TIM1, TIM_Channel_1, ENABLE); // CH1NTIM_CCxNCmd(TIM1, TIM_Channel_2, ENABLE); // CH2NTIM_CCxNCmd(TIM1, TIM_Channel_3, ENABLE); // CH3N// 6. 启动定时器TIM_Cmd(TIM1, ENABLE);TIM_CtrlPWMOutputs(TIM1, ENABLE); // MOE置位
}

ADC模块配置

  • 规则组通道选择:
    ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 1...)
  • DMA循环模式设置:
    DMA_InitStruct.Mode = DMA_Mode_Circular

// 示例:配置ADC1规则组的3个通道(顺序:通道5→通道1→通道11)
ADC_RegularChannelConfig(ADC1, ADC_Channel_5,  1); // 第1个转换
ADC_RegularChannelConfig(ADC1, ADC_Channel_1,  2); // 第2个转换
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 3); // 第3个转换ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_NbrOfChannel = 3; // 规则组总通道数
ADC_Init(ADC1, &ADC_InitStruct);DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 循环模式
DMA_InitStruct.DMA_BufferSize = 3;           // 缓冲区大小(与规则组通道数匹配)
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址固定
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;         // 内存地址递增
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16位数据
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel1, &DMA_InitStruct);// 设置外设地址(ADC数据寄存器)
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
// 设置内存地址(自定义缓冲区)
extern uint16_t adc_buffer[3];
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)adc_buffer;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动转换DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE); // 绑定ADC到DMA

霍尔接口配置

  • GPIO输入模式:
    GPIO_Init(GPIOx, GPIO_Pin_x, GPIO_Mode_IPU)
  • EXTI中断触发:
    EXTI_Trigger = EXTI_Trigger_Rising_Falling

霍尔传感器 → GPIO上拉输入 → EXTI双沿中断 → NVIC优先级配置 → 中断服务函数 → 换向逻辑

GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIO时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // 霍尔传感器连接的PA0/PA1/PA2
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 输入模式下速度可忽略,但需设置
GPIO_Init(GPIOA, &GPIO_InitStruct);EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;// 将GPIO引脚映射到EXTI中断线(以PA0为例)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);EXTI_InitStruct.EXTI_Line = EXTI_Line0; // 对应PA0
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 双沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);// 配置NVIC中断优先级
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) != RESET) {uint8_t hall_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 读取霍尔信号// 执行换向逻辑(例如BLDC电机驱动)EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志}
}

速度环定时器

  • 定时器2基础配置:
    TIM_TimeBaseInit(TIM2, 1kHz)
  • 中断服务程序:
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE)
// 系统时钟假设为72MHz(STM32F1系列)
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_InitStruct.TIM_Prescaler = 7200 - 1;    // 分频系数7200 → 72MHz/7200=10kHz
TIM_InitStruct.TIM_Period = 10 - 1;         // 自动重载值 → 10kHz/10=1kHz
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_InitStruct);// 使能TIM2更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 允许定时器溢出中断[citation:9][citation:10]// 配置NVIC中断优先级
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
void TIM2_IRQHandler(void) {if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {// 执行速度环PID计算或数据采集SpeedControl_Algorithm(); // 用户自定义速度环处理函数TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除中断标志[citation:9][citation:10]}
}

换相逻辑实现

  • Hall状态机:
    switch(Hall_Value & 0x07){
    case 0b101: PWM_SetPhaseA_High();...
    }
const PhaseAction phase_table[6] = {{0b101, PWM_A, OFF_C},  // 状态0{0b100, PWM_B, OFF_A},  // 状态1// ...其他状态
};

switch(Hall_Value & 0x07) {case 0b101:  // 对应霍尔状态HA=1, HB=0, HC=1PWM_SetPhaseA_High();  // 上桥臂A相PWM调制,下桥臂B相常通PWM_SetPhaseB_Low();PWM_SetPhaseC_Off();   // C相关闭(互补逻辑)break;case 0b100:  // 其他状态类似调整// ...
}

主控制循环

  • while(1){
    ADC_Convert();
    Speed_PID_Calc();
    Current_Limit_Check();
    }
void Current_Limit_Check() {if (ADC_Current > MAX_CURRENT) {PWM_Disable();  // 立即关闭功率输出Fault_LED_On(); // 故障指示System_Reset(); // 可选:进入安全状态或重启}
}

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

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

相关文章

LC-3 中常见指令

当然可以!以下是 LC-3 中常见指令(汇编格式)与对应的二进制编码格式 的总结表,通俗易懂地介绍每条指令的用途、操作码(opcode)以及格式结构。 ✅ 常见 LC-3 指令与对应的二进制格式 指令名称操作码&#x…

深入解析Docker:核心架构与最佳实践

文章目录 前言一、Docker 解决了什么问题?二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘:联合文件系统(UnionFS)2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组(Cgroups)2.3.3 内核…

从零打造企业级Android木马:数据窃取与远程控制实战

简介 木马病毒已从简单的恶意软件演变为复杂的攻击工具,尤其在2025年企业级攻击中,木马病毒正成为黑客组织的主要武器之一。 本文将深入探讨如何制作具备数据窃取和远程控制功能的Android木马,从基础原理到企业级防御绕过技术,同时提供详细的代码实现,帮助开发者理解木马…

ES常识5:主分词器、子字段分词器

文章目录 一、主分词器:最基础的文本处理单元主分词器的作用典型主分词器示例 二、其他类型的分词器:解决主分词器的局限性1. 子字段分词器(Multi-fields)2. 搜索分词器(Search Analyzer)3. 自定义分词器&a…

【第三十五周】Janus-pro 技术报告阅读笔记

Janus-Pro 摘要Abstract文章信息引言方法Janus 架构Janus 训练Janus-Pro 的改进 实验结果总结 摘要 本篇博客介绍了Janus-Pro,这是一个突破性的多模态理解与生成统一模型,其核心思想是通过解耦双路径视觉编码架构解决传统方法中语义理解与像素生成的任务…

MySQL 数据操纵与数据库优化

MySQL数据库的DML 一、创建(Create) 1. 基本语法 INSERT INTO 表名 [(列名1, 列名2, ...)] VALUES (值1, 值2, ...); 省略列名条件:当值的顺序与表结构完全一致时,可省略列名(需包含所有字段值)批量插…

(9)被宏 QT_DEPRECATED_VERSION_X_6_0(“提示内容“) 修饰的函数,在 Qt6 中使用时,会被编译器提示该函数已过时

(1)起因是看到 Qt 的官方源代码里有这样的写法: #if QT_DEPRECATED_SINCE(6, 0) //里面的都是废弃的成员函数QT_WARNING_PUSHQT_WARNING_DISABLE_DEPRECATEDQT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType inst…

【bibtex4word】在Word中高效转换bib参考文献,Texlive环境安装bibtex4word插件

前言 现已退出科研界,本人水货一个。希望帮到有缘人 本篇关于如何将latex环境中的参考文献bib文件转化为word,和一些踩坑记录。 可以看下面的资料进行配置,后面的文字是这些资料的补充说明。 参考文章:https://blog.csdn.net/g…

Python 自动化脚本开发秘籍:从入门到实战进阶(6/10)

摘要:本文详细介绍了 Python 自动化脚本开发的全流程,从基础的环境搭建到复杂的实战场景应用,再到进阶的代码优化与性能提升。涵盖数据处理、文件操作、网络交互、Web 测试等核心内容,结合实战案例,助力读者从入门到进…

理解反向Shell:隐藏在合法流量中的威胁

引言 在网络安全领域,​​反向Shell(Reverse Shell)​​ 是一种隐蔽且危险的攻击技术,常被渗透测试人员和攻击者用于绕过防火墙限制,获取对目标设备的远程控制权限。与传统的“正向Shell”(攻击者主动连接…

无人机电池储存与操作指南

一、正确储存方式 1. 储存电量 保持电池在 40%-60% 电量(单片电压约3.8V-3.85V)存放,避免满电或空电长期储存。 满电存放会加速电解液分解,导致鼓包;**空电**存放可能引发过放(电压低于3.0V/片会永久…

怎样选择成长股 读书笔记(一)

文章目录 第一章 成长型投资的困惑一、市场不可预测性的本质困惑二、成长股的筛选悖论三、管理层评估的认知盲区四、长期持有与估值波动的博弈五、实践中的认知升级路径总结:破解困惑的行动框架 第二章 如何阅读应计制利润表一、应计制利润表的本质与核心原则1. 权责…

深入浅出之STL源码分析6_模版编译问题

1.模版编译原理 当我们在代码中使用了一个模板,触发了一个实例化过程时,编译器就会用模板的实参(Arguments)去替换(Substitute)模板的形参(Parameters),生成对应的代码。…

无人甘蔗小车履带式底盘行走系统的研究

1.1 研究背景与意义 1.1.1 研究背景 甘蔗作为全球最重要的糖料作物之一,在农业经济领域占据着举足轻重的地位。我国是甘蔗的主要种植国家,尤其是广西、广东、云南等地,甘蔗种植面积广泛,是当地农业经济的重要支柱产业。甘蔗不仅…

LVGL(lv_slider滑动条)

文章目录 一、lv_slider 是什么?二、创建一个滑块设置滑块的范围和初始值 三、响应滑块事件四、设置样式示例:更改滑块颜色和滑块按钮样式 五、纵向滑块(垂直方向)六、双滑块模式(范围选择)七、获取滑块的值…

每日算法-250511

每日算法 - 250511 记录一下今天刷的几道LeetCode题目,主要是关于贪心算法和数组处理。 1221. 分割平衡字符串 题目 思路 贪心 解题过程 我们可以遍历一次字符串,维护一个计数器 balance。当遇到字符 L 时,balance 增加;当遇…

Keepalived + LVS + Nginx 实现高可用 + 负载均衡

目录 Keepalived Keepalived 是什么(高可用) 安装 Keepalived LVS LVS 是什么(负载均衡) 安装 LVS Keepalived LVS Nginx 实现 高可用 负载均衡 Keepalived Keepalived 是什么(高可用) Keepaliv…

【杂谈】-DeepSeek-GRM:让AI更高效、更普及的先进技术

DeepSeek-GRM:让AI更高效、更普及的先进技术 文章目录 DeepSeek-GRM:让AI更高效、更普及的先进技术1、DeepSeek-GRM:先进的AI框架解析2、DeepSeek-GRM:AI开发的变革之力3、DeepSeek-GRM:广泛的应用前景4、企业自动化解…

【MySQL】页结构详解:页的大小、分类、头尾信息、数据行、查询、记录及数据页的完整结构

📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…

【FreeRTOS】基于G431+Cubemx自用笔记

系列文章目录 留空 文章目录 系列文章目录前言一、从头开始创建一个FreeRTOS工程1.1 在 "Timebase Source" 中,选择其他TIM1.2 配置FreeRTOS的参数1. 3 添加任务 二、动态任务的创建/删除2.1 函数介绍2.1.1 创建动态任务xTaskCreate()2.1.2 创建静态任务…