下面詳細說明程序的結構和功能的實現。
對于一個比較復雜的項目來說,程序框架的好壞決定了后續的可維護性,功能可擴展性。在這個項目中,筆者參考了MX的數字電源插件X-CUBE-DPower中的例程框架,將該框架移植到了本項目中。在本文的附件中,有st官方開發板B-G474-DPOW1的例子程序,本文中的代碼大部分來自于這些例程。
在這個程序框架中,框架本質上是一個狀態機,這個狀態機做為main()函數中的主循環的主體,實現了電源工作狀態的切換、LED狀態的指示、告警、開機軟啟動和恒壓恒流環路的計算等功能。
從上圖可以看到狀態機的一個工作流程,需要在本程序建立這個狀態機框架。
因為從下面開始的大部分的代碼編寫都不在MX生成的代碼中進行,為了以后不干擾用戶自己編寫的代碼,需要在程序的工程目錄中再創建一個新的目錄,專門保存和管理用戶自己編寫的代碼。
筆者創建了個“app”的目錄,里面有四個文件,如下圖:
LED.*為LED燈的相關代碼,Status_Machine.*為狀態機的相關代碼。
在進行狀態機框架建立之前,要先說一下LED燈的工作方式。
下圖是三個LED輸出引腳定義。
在本項目中,用到了三個LED燈,LED引腳分別是PB9——LED1、PE0——LED2、PE1——LED3。每個LED燈都有四種工作方式:1常亮、2常滅、3連續閃(閃動的時間可設置)、4連續閃n次間隔一段時間(m毫秒)后,再閃n次,其中閃動次數n,連續閃動間隔時間和下次閃動的間隔時間m都可以設定。
當定義好LED用到的數據類型后,將LED的功能函數移植過來,在stm32g4xx_it.c文件中的系統中斷——tick定時器中斷服務中將LED計數器遞減。當需要設置LED工作狀態機用下面函數:
LED_SetParams(&LED1_Status, LED_BLINK_N, LED_RUN_BLINK_NUM, LED_BLINK_PERIOD_MS, LED_BLINK_REPETITION_PERIOD_MS);
LED_SetParams(&LED2_Status, LED_BLINK_INF, 0, LED_BLINK_PERIOD_LONG_MS,0);
LED_SetParams(&LED3_Status, LED_BLINK_N, LED_STARTUP_BLINK_NUM, LED_BLINK_PERIOD_SHORT_MS, LED_BLINK_REPETITION_PERIOD_MS);
然后在main.c的主循環中運行
while (1)
{
LED_Task(&LED1_Status);
LED_Task(&LED2_Status);
LED_Task(&LED3_Status);
}
這樣,每個LED有四個狀態,通過三個LED燈不同狀態的組合,就能指示多種芯片內部運行狀態,在調試過程中非常有用。
在進入狀態機循環之前,應該先將需要的外設使能。
/* Init 2p2z using the FMAC */
if (__3p3zInitFmacInt16( &USER_APPL_FMAC, &cntrlFmac,
A1, A2, 0.0,
B0, B1, B2, 0.0,
post_shift, DUTY_TICKS_MIN, DUTY_TICKS_MAX ) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Init 2p2z using the CPU */
CNTRL_3p3zInit(&myDcdc.iLoop, iREF,
iA1, iA2, 0.0,
iB0, iB1, iB2, 0.0,
iK, (float_t)iDUTY_TICKS_MIN, (float_t)iDUTY_TICKS_MAX );
/* Start the FMAC and wait for DMA transfer */
if (__StartFmacInt16( &USER_APPL_FMAC, &cntrlFmac ) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Initialise soft start ramp */
CNTRL_RampFloatConfig( &myDcdc.vRamp, 0, (VOUT_SET*VOUT_ADC_COFF), STARTUP_DCDC_RAMP_DURATION, 1000 );
/* Perform an ADCx automatic self-calibration and enable ADC */
if(HAL_ADCEx_Calibration_Start(&USER_APPL_ADC3, ADC_SINGLE_ENDED) != HAL_OK)
{
/* ADC initialization Error */
Init_Error_Handler();
}
/* Start ADCx with DMA request */
if(HAL_ADC_Start_DMA(&USER_APPL_ADC3, (uint32_t *) &USER_APPL_FMAC.Instance->WDATA, 1) != HAL_OK)
{
/* ADC initiliazation Error */
Init_Error_Handler();
}
if(HAL_ADCEx_Calibration_Start(&USER_APPL_ADC1, ADC_SINGLE_ENDED) != HAL_OK)
{
/* ADC initialization Error */
Init_Error_Handler();
}
/* Start ADCx with DMA request */
if(HAL_ADC_Start_IT(&USER_APPL_ADC1) != HAL_OK)
{
/* ADC initiliazation Error */
Init_Error_Handler();
}
/* Disable the DMA interrupts */
__HAL_DMA_DISABLE_IT(&USER_APPL_DMA3, DMA_IT_HT | DMA_IT_TC );
/* Enables DAC1 and starts conversion of the channel 1 */
if (HAL_DAC_Start(&USER_APPL_DAC1, DAC_CHANNEL_1) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Enables DAC3 and starts conversion of the channel 1 */
if (HAL_DAC_Start(&USER_APPL_DAC3, DAC_CHANNEL_1) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Start the comparator1 to detect the peak current trip threshold */
if (HAL_COMP_Start(&USER_APPL_CURRENT_SENSE1) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Start the comparator3 to detect the peak current trip threshold */
if (HAL_COMP_Start(&USER_APPL_CURRENT_SENSE2) != HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
/* Start the UART2 */
if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&RX2_buff, 8)!= HAL_OK)
{
/* Configuration Error */
Init_Error_Handler();
}
將上述外設使能后,還要先將串口調試成功,在程序的調試過程中,通過串口可以將程序運行時的變量傳遞出來。
本例中,是通過串口中斷回調函數來完成的。
因為在前面已經通過函數
HAL_UART_Receive_IT(&huart2, (uint8_t *)&RX2_buff, 8)
打開了串口的接收端口,所以只要串口收到數據,就會進入上面的回調函數,進行數據的處理。如果向外界發送數據,用函數
HAL_UART_Transmit_IT(&huart2, (uint8_t *)&TX2_buff, 5)
至于接收和發送的內容,可以自己填寫。
然后將status_machine.c中的StM_Process()狀態機的本體移植進主循環中。至于狀態機如何運行的,可以詳細閱讀附件中的例程,這里就不再詳述。
下面著重介紹一下斜率補償是如何實現的。
因為峰值電流型控制,需要有斜率補償。在STM32G474VE這顆芯片中,是通過HRTIM和DAC相互配合來實現的,下圖為斜率補償的產生機制。
其中STRSTDATA[11:0]是由FMAC完成的環路補償計算的結果,用來更新DAC負向輸入端的參考值。STRSTTRIG是復位信號,表示DAC從何時開始產生斜率。STINCTRIG是步長時間間隔信號,表示每隔多長時間就將STRSTDATA[11:0]的值減去一個定值。STRSTTRIG與STINCTRIG是HRTIM的關聯信號。
DAC斜率補償的步長時間,只能通過TA(或TB...TF)的compare2來設定,下圖能清楚的說明DAC的斜率補償的工作原理。
然后在DAC1中進行設置。
因為ResetData和StepData這兩個寄存器的值要隨時根據環路計算值的變化而變化,這里可以先設為零,在程序中動態修改。
因為DAC1是控制TA1和TA2的占空比的,要與TA的時基同步,所以Trigger和Trigger2要選擇RST Out1 event和STEP Out1 event。
同理,設置TB和DAC3
斜率補償設置完成了。因為MOS管導通時會對電流互感器的采樣電流產生干擾,進而對comp比較器的輸出產生影響,使環路出現不穩定的狀態,所以有必要進行前沿消隱。
對于TA和TB的前沿消隱,分別用TA-compare3和TB-compare3做為消隱時間計數器。
TB的消隱也是如此設置。
從上面可以看到TA和TB的前沿消隱配置完成了。