我們可以在STM32單片機引脚產生頻率與占空比可調的PWM波。

時鐘配置

Clock Configuration -> HCLK = 80MHz
Clock Configuration -> PLL Source = HSE
Clock Configuration -> Input Source = 晶振頻率
RCC -> HSE = Crystal/Ceramic Resonator
TIM16 -> Clock Source = Internal Clock
Channel1 -> PWM Generation CH1
Prescaler = 8000 - 1
Counter Period = 100 - 1
Pulse = 20 (初始占空比)

計算得80,000,000/8000/100 = 100,程序可以生成100Hz的PWM波,頻率後續可以在程序中透過修改PrescalerCounter Period(即ARR)來改變。

配置好后初始化,使用函數HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1)打開PWM輸出,否則無波形。不同電路的配置方法有差異。

占空比切換

可以通過函數
__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, Duty)的Duty參數改變輸出占空比,Duty應當在0-100之間。

頻率切換

輸出PWM波的頻率可以透過修改Prescaler或Counter Period(即ARR)來改變。修改前建議先關閉PWM輸出,修改後再重啓輸出。

注意:設置值不應過高
1
2
3
4
HAL_TIM_PWM_Stop(&htim16, TIM_CHANNEL_1);
__HAL_TIM_SET_PRESCALER(&htim16, 2000 - 1);
//__HAL_TIM_SET_AUTORELOAD(&htimx, new_arr);
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);

PWM捕獲

PWM捕獲需要在上述基礎上進行如下配置:

TIM Channel1 -> Input Capture direct mode
Prescaler -> 80 - 1
Counter Period -> 默認
NVIC -> Global Interrupt
在主函數中調用函數HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1)啓動頻率測量捕獲計時器

1
2
3
4
5
6
7
8
9
10
11
uint8_t ccr_val = 0;
uint frq = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
if(htim -> Instance == TIM2) {
ccr_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
__HAL_TIM_SetCounter(htim, 0);
frq = (8000000 / 80) / ccr_val;
//80是分頻係數
HAL_TIM_IC_Start(htim, TIM_CHANNEL_1);
}
}

同樣地,我們可以使用Polarity Selection

ADC_IN11 -> IN11 = single_ended

1
2
3
4
5
6
7
8
9
10
11
12
13
double getADC(ADC_HandleTypeDef *pin) {
uint adc;
HAL_ADC_Start(pin);
adc = HAL_ADC_GetValue(pin);
double rtnVal = adc * 3.3 / 4096;
/*
注意此處4096為2的12次方,
代表12位分辨率的ADC
分辨率可以透過CubeMx的ADC配置界面修改
Parameter Settings -> Resolution -> ADC 12-bit resolution
*/
return rtnVal;
}

調用

1
2
char text[30];
sprintf(text, "V = %.2f", getADC(&hadc1));