硬件設備函數
42步進電機,步進電機驅動器,正點原子F429開發板spa
開發軟件code
keil5,Cubeblog
綜述事件
通常要精準的控制電機,就要控制單片機的引腳輸出指定個數的PWM波,有多種可實現的方法,其中最好用的方法是用定時器級聯輸出固定個數PWM脈衝,雖然多用了一個定時器,但大大減小了CPU的處理資源。STM32的每一個定時器能夠經過另一個定時器的某一個條件被觸發而啓動.這裏所謂某一個條件能夠是定時到時、定時器超時、比較成功等許多條件.這種經過一個定時器觸發另外一個定時器的工做方式稱爲定時器的同步,發出觸發信號的定時器工做於主模式,接受觸發信號而啓動的定時器工做於從模式。資源
Cube配置定時器,主定時器爲PWM輸出,從定時器爲門控模式開發
1.主定時器爲TIM3,其中通道1配置爲PWM輸出,主模式的更新事件選爲觸發輸入同步
Cube的配置爲參考,一切以代碼爲準it
void MX_TIM3_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim3.Instance = TIM3; //設置主定時器爲TIM3 htim3.Init.Prescaler = 4-1; //設置PWM頻率 htim3.Init.CounterMode = TIM_COUNTERMODE_UP; //設置計數模式爲向上計數 htim3.Init.Period = 100-1; //設置佔空比 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //設置爲無分頻 if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; //更新事件被選爲觸發輸入 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; //開啓主從模式 if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; //設置PWM模式爲PWM1 sConfigOC.Pulse = 50; //設置PWM佔空比爲50%(50/100) sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; //設置PWM空閒狀態引腳拉低 if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } HAL_TIM_MspPostInit(&htim3); //設置PA6複用爲PWM輸出引腳 HAL_TIM_Base_Stop(&htim3); }
2.從定時器爲TIM4,選爲門控模式——觸發輸入io
從爲TIM4,主爲TIM3,根據下圖,因此從模式的觸發時鐘爲ITR2
void MX_TIM4_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_SlaveConfigTypeDef sSlaveConfig = {0}; htim4.Instance = TIM4; //設置從定時器爲TIM4 htim4.Init.Prescaler =0; //設置從定時器頻率爲0 htim4.Init.CounterMode = TIM_COUNTERMODE_UP; //設置計數模式爲向上計數 htim4.Init.Period =0xffff; //這個大於0就行 htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //設置爲無分頻 if (HAL_TIM_Base_Init(&htim4) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; //設置爲內部時鐘觸發,即爲TIM3 if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED; //設置爲門觸發 sSlaveConfig.InputTrigger = TIM_TS_ITR2; //設置ITR2(tim3)爲輸入源 sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING; //設置觸發模式爲上升沿 sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1; //設置無預分頻 sSlaveConfig.TriggerFilter = 0x0; //設置無濾波 if (HAL_TIM_SlaveConfigSynchronization(&htim4, &sSlaveConfig) != HAL_OK) { Error_Handler(); } HAL_TIM_Base_Stop_IT(&htim4); }
從定時器的頻率必定要設爲0,否則輸出的PWM會加倍
中斷處理函數
HAL裏的中斷處理函數要選HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim),當TIM4->CNT的值達到TIM4->ARR的值時觸發中斷,關閉主從定時器,清零中斷標誌位SR
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { FLAG1_OK = 0; if(htim==(&htim4)) { //****************************************************// if(__HAL_TIM_GET_FLAG(&htim4, TIM_FLAG_CC1) != RESET) //判斷是否觸發中斷 { __HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC1); //清除中斷標誌位 HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); //關閉主定時器的PWM輸出 HAL_TIM_Base_Stop_IT(&htim4); //關閉從定時器的計數 //****************************************************// } delay_ms(1); FLAG1_OK = 1; } }
脈衝輸出主函數
中斷函數關閉的,於此要從新開啓,善始善終
while(1) { if(FLAG1_OK == 1 ) //標誌判斷 { she10 __HAL_TIM_SET_AUTORELOAD(&htim4,10-1); //ARR裝載要輸出的PWM脈衝數 HAL_TIM_Base_Start_IT(&htim4); //從定時器計數開啓 HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1); //主定時器PWM脈衝輸出
} }
分析儀實測波形
很漂亮整潔的10個PWM波,在1MHz如下挺準的,但上去了就多了一兩個波,還須要細調。
這個是單定時器的單通道的程序,已經寫好單定時器多通道的了,有時間再發。
有不足之處還請各位不吝賜教。