首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

STM32 進階實戰:TIM1 六路互補 PWM + CCR4 觸發 ADC 注入採樣,實現無感 BLDC 驅動核心邏輯

     編輯:關於C語言

項目背景:無感 BLDC 電機驅動的核心難點

在無感無刷直流電機(Sensorless BLDC)驅動中,核心挑戰在於:

  • **六路互補 PWM 生成**:驅動三相全橋逆變器,需精確的死區控制防止直通
  • **過零檢測時機**:必須在 PWM 導通窗口(PWM-ON)內採樣相電流/反電動勢,避開開關噪聲
  • **電流保護響應速度**:過流/限流需在微秒級內完成採樣、判斷、關斷

STM32 高級定時器 TIM1 完美契合此需求:通道 1/2/3 輸出六路互補 PWM,通道 4 (CCR4) 可精確觸發 ADC 注入組採樣,並產生中斷處理保護邏輯。

TIM1 關鍵配置詳解

1. 基礎時基與重複計數器

TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD - 1;        // PWM 週期
TIM_TimeBaseStructure.TIM_Prescaler = 0;                    // 0 分頻,最大分辨率
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1; // 中心對齊模式 1
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;            // 每次更新都觸發

中心對齊模式 使計數器上下計數,更新事件發生在頂部/底部,配合 CCR4 在上升/下降沿精確觸發 ADC,實現「採樣點正好落在 PWM 導通平坦區」。

2. 斷路與死區配置 (BDTR)

TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = DEAD_TIME_VALUE;       // 死區時間(納秒級換算)
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;         // 硬件刹車輸入
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

死區設置直接關係 MOS 管開關安全,**必須根據驅動芯片數據手冊(如 IR2101/IR2136)計算**,不可估算。

3. 三相互補 PWM 輸出配置

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互補輸出使能
TIM_OCInitStructure.TIM_Pulse = 0;                            // 初始佔空比 0
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

TIM_OC1Init(TIM1, &TIM_OCInitStructure); // U 相
TIM_OC2Init(TIM1, &TIM_OCInitStructure); // V 相
TIM_OC3Init(TIM1, &TIM_OCInitStructure); // W 相

4. CCR4 配置:ADC 注入觸發源


// CCR4 不輸出 PWM,僅作內部比較觸發
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = ADC_TRIGGER_POINT;          // 採樣觸發點(計數器值)
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);

TIM_CtrlPWMOutputs(TIM1, ENABLE); // 主輸出使能(MOE 位)

關鍵發現: 若 CCR4 = 0,ADC 注入採樣**不會觸發**,也就無中斷產生。必須設置有效比較值(如導通區中點),才能正常工作。

ADC1 雙模式配置:規則組 + 注入組


// 規則組:DMA 連續採樣母線電流/電壓,軟件觸發
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 軟件觸發
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 4;

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);  // 母線電流
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);  // 母線電壓
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5);  // 溫度
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 4, ADC_SampleTime_239Cycles5); // 內部參考

// 注入組:CCR4 硬件觸發,採樣相電流/反電動勢
ADC_InjectedSequencerLengthConfig(ADC1, 3); // 3 個注入通道
ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_7Cycles5);   // U 相電流
ADC_InjectedChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_7Cycles5);   // V 相電流
ADC_InjectedChannelConfig(ADC1, ADC_Channel_TempSensor, 3, ADC_SampleTime_7Cycles5); // 內部溫度

ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4); // TIM1_CC4 觸發
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);

ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE); // 注入組轉換結束中斷
ADC_Cmd(ADC1, ENABLE);

中斷服務程序(ISR)設計要點

void ADC1_2_IRQHandler(void) {
    if (ADC_GetITStatus(ADC1, ADC_IT_JEOC) != RESET) {
        ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);

        // 1. 讀取注入組數據寄存器 (JDR1~JDR3)
        uint16_t i_u = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
        uint16_t i_v = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
        // uint16_t temp = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3);

        // 2. 克拉克/帕克變換、觀測器估算轉子位置
        // 3. 過零判斷、換相邏輯
        // 4. 限流/過流保護:若電流超閾值,直接置 TIM1->CCR1/2/3 = 0 或拉低 MOE 位

        // 注意:ISR 必須極短(< 5μs),複雜運算放主循環或低優先級任務
    }
}

實戰避坑指南

現象原因對策
CCR4 設置非 0 但 ADC 不觸發 TIM1 未使能主輸出 (MOE),或 CCR4 比較模式錯誤 檢查 TIM_CtrlPWMOutputs(ENABLE)、TIM_OC4Init 模式為 PWM1
採樣數據抖動大 採樣點落在 PWM 開關沿 調整 CCR4 值至導通區中心;增加採樣時間 ADC_SampleTime_239Cycles5
死區設置後波形異常 死區時間過長/過短 示波器測量上下管駕驭波形,參考驅動芯片手冊精確計算
注入中斷進不去 NVIC 優先級配置缺失,或 ADC_IT_JEOC 未使能 檢查 NVIC_Init、ADC_ITConfig(ADC_IT_JEOC, ENABLE)

總結

TIM1 + ADC1 注入組是 STM32 控制類應用的「黃金組合」。掌握中心對齊 PWM、死區配置、CCR4 精確觸發、注入組硬件觸發、DMA 雙緩衝 等核心技巧,即可構建高性能、高可靠性的電機驅動、電源控制、光伏 MPPT 等系統。建議配合示波器、邏輯分析儀逐步調試,從單相 PWM 開始,逐步疊加功能模塊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved