f 物联网-stm32实战项目:无刷驱动 - Powered by qidao123.com技术社区

stm32实战项目:无刷驱动

打印 上一主题 下一主题

主题 2036|帖子 2036|积分 6108

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录

体系时钟配置
PWM模块初始化
ADC模块配置
霍尔接口配置
速度环定时器
换相逻辑实现
主控制循环


体系时钟配置



  • 启用72MHz主频:RCC_Configuration()设置PLL
  • 外设时钟使能:TIM1/ADC/GPIO时钟
  1. #include "stm32f10x.h"
  2. void RCC_Configuration(void)
  3. {
  4.     // 时钟复位配置
  5.     RCC_DeInit();
  6.    
  7.     // 1. 开启HSE并等待就绪
  8.     RCC_HSEConfig(RCC_HSE_ON);
  9.     while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
  10.    
  11.     // 2. 配置PLL:HSE作为源,9倍频
  12.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
  13.    
  14.     // 3. 设置FLASH预取指和等待周期(必须)
  15.     FLASH_SetLatency(FLASH_Latency_2);
  16.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  17.    
  18.     // 4. 时钟分频配置
  19.     RCC_HCLKConfig(RCC_SYSCLK_Div1);    // AHB=72MHz
  20.     RCC_PCLK1Config(RCC_HCLK_Div2);    // APB1=36MHz
  21.     RCC_PCLK2Config(RCC_HCLK_Div1);    // APB2=72MHz
  22.    
  23.     // 5. 启动PLL并切换时钟源
  24.     RCC_PLLCmd(ENABLE);
  25.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
  26.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  27.     while(RCC_GetSYSCLKSource() != 0x08);
  28.    
  29.     // 6. 外设时钟使能
  30.     RCC_APB2PeriphClockCmd(
  31.         RCC_APB2Periph_TIM1 |    // TIM1时钟
  32.         RCC_APB2Periph_ADC1 |    // ADC1时钟
  33.         RCC_APB2Periph_GPIOA |   // GPIOA时钟(示例)
  34.         RCC_APB2Periph_GPIOC,    // GPIOC时钟(示例)
  35.         ENABLE
  36.     );
  37. }
  38. // 主函数初始化调用示例
  39. int main(void)
  40. {
  41.     RCC_Configuration();
  42.     // 其他初始化代码...
  43.     while(1);
  44. }
复制代码
PWM模块初始化



  • 定时器1通道1-3配置:
    TIM_OCInitTypeDef.Pulse = 50%占空比
    TIM_BDTRInitStruct配置死区时间(50-100ns)
  • 互补输出使能:
    TIM_CCxNCmd(TIM1, ENABLE)
  1. #include "stm32f10x.h"
  2. void PWM_Configuration(void)
  3. {
  4.     GPIO_InitTypeDef GPIO_InitStruct;
  5.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
  6.     TIM_OCInitTypeDef TIM_OCStruct;
  7.     TIM_BDTRInitTypeDef TIM_BDTRStruct;
  8.     // 1. GPIO配置(以PA8/PA7为例)
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  10.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_7; // CH1/CH1N
  11.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  12.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  13.     GPIO_Init(GPIOA, &GPIO_InitStruct);
  14.     // 2. 定时器基础配置(72MHz时钟)
  15.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  16.     TIM_TimeBaseStruct.TIM_Period = 1000-1;      // ARR决定PWM频率
  17.     TIM_TimeBaseStruct.TIM_Prescaler = 0;        // 无分频
  18.     TIM_TimeBaseStruct.TIM_ClockDivision = 0;
  19.     TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
  20.     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStruct);
  21.     // 3. PWM通道配置(50%占空比)
  22.     TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
  23.     TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
  24.     TIM_OCStruct.TIM_Pulse = 500; // 50% of ARR(1000)
  25.     TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
  26.     TIM_OC1Init(TIM1, &TIM_OCStruct); // 通道1
  27.     TIM_OC2Init(TIM1, &TIM_OCStruct); // 通道2
  28.     TIM_OC3Init(TIM1, &TIM_OCStruct); // 通道3
  29.     // 4. 死区时间配置(约55.5ns)
  30.     TIM_BDTRStruct.TIM_DeadTime = 0x04; // DTG=4: 4*Tdts (Tdts=13.89ns@72MHz)
  31.     TIM_BDTRStruct.TIM_Break = TIM_Break_Disable;
  32.     TIM_BDTRStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
  33.     TIM_BDTRStruct.TIM_OSSRState = TIM_OSSRState_Disable;
  34.     TIM_BDTRStruct.TIM_OSSIState = TIM_OSSIState_Disable;
  35.     TIM_BDTRStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  36.     TIM_BDTRConfig(TIM1, &TIM_BDTRStruct);
  37.     // 5. 互补输出使能
  38.     TIM_CCxNCmd(TIM1, TIM_Channel_1, ENABLE); // CH1N
  39.     TIM_CCxNCmd(TIM1, TIM_Channel_2, ENABLE); // CH2N
  40.     TIM_CCxNCmd(TIM1, TIM_Channel_3, ENABLE); // CH3N
  41.     // 6. 启动定时器
  42.     TIM_Cmd(TIM1, ENABLE);
  43.     TIM_CtrlPWMOutputs(TIM1, ENABLE); // MOE置位
  44. }
复制代码
ADC模块配置



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

  1. // 示例:配置ADC1规则组的3个通道(顺序:通道5→通道1→通道11)
  2. ADC_RegularChannelConfig(ADC1, ADC_Channel_5,  1); // 第1个转换
  3. ADC_RegularChannelConfig(ADC1, ADC_Channel_1,  2); // 第2个转换
  4. ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 3); // 第3个转换
  5. ADC_InitTypeDef ADC_InitStruct;
  6. ADC_InitStruct.ADC_NbrOfChannel = 3; // 规则组总通道数
  7. ADC_Init(ADC1, &ADC_InitStruct);
  8. DMA_InitTypeDef DMA_InitStruct;
  9. DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 循环模式
  10. DMA_InitStruct.DMA_BufferSize = 3;           // 缓冲区大小(与规则组通道数匹配)
  11. DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址固定
  12. DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;         // 内存地址递增
  13. DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16位数据
  14. DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  15. DMA_InitStruct.DMA_Priority = DMA_Priority_High;
  16. DMA_Init(DMA1_Channel1, &DMA_InitStruct);
  17. // 设置外设地址(ADC数据寄存器)
  18. DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
  19. // 设置内存地址(自定义缓冲区)
  20. extern uint16_t adc_buffer[3];
  21. DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)adc_buffer;
  22. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
  23. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  24. ADC_Cmd(ADC1, ENABLE);
  25. ADC_ResetCalibration(ADC1);
  26. while(ADC_GetResetCalibrationStatus(ADC1));
  27. ADC_StartCalibration(ADC1);
  28. while(ADC_GetCalibrationStatus(ADC1));
  29. ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动转换
  30. DMA_Cmd(DMA1_Channel1, ENABLE);
  31. 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优先级配置 → 中断服务函数 → 换向逻辑
  1. GPIO_InitTypeDef GPIO_InitStruct;
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIO时钟
  3. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // 霍尔传感器连接的PA0/PA1/PA2
  4. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入
  5. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 输入模式下速度可忽略,但需设置
  6. GPIO_Init(GPIOA, &GPIO_InitStruct);
  7. EXTI_InitTypeDef EXTI_InitStruct;
  8. NVIC_InitTypeDef NVIC_InitStruct;
  9. // 将GPIO引脚映射到EXTI中断线(以PA0为例)
  10. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
  11. EXTI_InitStruct.EXTI_Line = EXTI_Line0; // 对应PA0
  12. EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
  13. EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 双沿触发
  14. EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  15. EXTI_Init(&EXTI_InitStruct);
  16. // 配置NVIC中断优先级
  17. NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
  18. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
  19. NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;
  20. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  21. NVIC_Init(&NVIC_InitStruct);
复制代码

  1. void EXTI0_IRQHandler(void) {
  2.     if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
  3.         uint8_t hall_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 读取霍尔信号
  4.         // 执行换向逻辑(例如BLDC电机驱动)
  5.         EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
  6.     }
  7. }
复制代码

速度环定时器



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

换相逻辑实现



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

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

主控制循环



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


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

盛世宏图

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表