用過stm32定時器的朋友都知道,定時器的CCR寄存器,可以用來配置PWM的輸出,但同樣也可以用來配置spwm。廢話不多說,直接上代碼。
首先,你得考慮一下幾個因素:
1.同步調制還是異步調制。
2.載波比N設置為多少
3.spwm計算法
4.prescaler和period的值
5.改變CCR還是改變ARR
下面是程序的大致情況:
1.使用同步
2.載波比設置為N = 360
3.采用對稱規則采樣法
4.通過中斷時實改變CCR的值
5.使用stm32f429,它的高級定時器時鍾頻率為180M(不分頻的情況下)
6.計數器采用遞增遞減的方式技術
——————————————————————————————————————————
1.GPIO的復用
使用了TIM8_CH1和TIM8_CH1N,兩個引腳。
這兩個腳是復用功能,所以在配置GPIO口的時候,要調用
這段代碼在GPIO配置之前,還是GPIO_Init()之后都沒有太大的影響。
2.ARR值與CCR
定義計數頻率,TIM_CLk,和濾波后正弦波的頻率,Sin_F那么
prescaler = 定時器計數頻率 / TIM_CLK - 1;
period = TIM_CLK / (2*Sin_F *N) - 1;
3.定時器計數方式的設定
不要死記什么TIM_CountMode_CenterAligned1,等,每款板子可能不一樣。
在這塊stm32f4的板子上面,CMS = 01 ,對應定時器遞減計數的時候,當計數的值等於CCR的值時,就觸發中斷,查看對應的寄存器
4.中斷函數的處理
首先進行中斷向量表的配置,這大家都會吧
根據對稱規則采樣的公式 D = 載波的周期 / 4 *(1 - 調制比 * sin(x)).
這里將sin(x)離散化處理,因為sin函數的值是小於1的,所以Sin_Tab[]應該是float或者double型
如果正弦波的周期定了,那么載波的定時器的周期也定了,參考下面的函數,
float n1_RET(float Sin_F)
{
static float temp;
temp = TIM_CLK;
temp = temp/Sin_F;
temp = temp/N;
temp = temp/4;
return temp;
}
這個函數就是計算載波周期的四分之一,當它的返回值乘以占空比就得到公式的第二個參數,
float n2_RET(float M,float AN_RET)
{
static float temp;
temp = AN_RET;
temp *= M;
return temp;
}
最后在中斷處理函數里面更新CCR的值,記住一次只更新一個值,並不是讓你更新N個,
所以在中斷處理函數中不需要對 i 進行 1 ~ 360 的遍歷 , 只需要 每次遞增就行了。
當 i 超過 N 時,進行復位就可以了。
TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);
NewChannelValue = (int)(n1_Temp - n2_Temp*Sin_Tab[i++]);
if ( i == 360)
{
i = 0;
}
TIM_SetCompare1(ADVANCE_TIM,NewChannelValue);