单片机
返回首页

STM32实战项目:无刷电机驱动详解

2025-09-29

系统时钟配置

启用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=72MHz

    RCC_PCLK1Config(RCC_HCLK_Div2);    // APB1=36MHz

    RCC_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/CH1N

    GPIO_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); // 通道1

    TIM_OC2Init(TIM1, &TIM_OCStruct); // 通道2

    TIM_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); // CH1N

    TIM_CCxNCmd(TIM1, TIM_Channel_2, ENABLE); // CH2N

    TIM_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=1

        PWM_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(); // 可选:进入安全状态或重启

    }

}


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章