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.pswp.cn/diannao/82611.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82611.shtml
英文地址,請注明出處:http://en.pswp.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 創建靜態任務…