# STM32h723 NOTE ###### tags: `DIT` 宗旨: 避免以後的自己忘記stm32怎麼用,因此將分散在教學PPT各處的函式和用法記在一起,就不用找得很久了! [toc] ## 0. 總整理 ### GPIO Writes HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); ### Starts HAL_ADC_Start(&hadc1); HAL_TIM_Base_Start(&htim3); HAL_TIM_Base_Start_IT(&htim3); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_2); HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL); ### Get Values x = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_13); x = HAL_ADC_GetValue(&hadc1); x = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1); x = __HAL_TIM_GET_COUNTER(&htim3); ### Sets __HAL_TIM_SetCounter(&htim4, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 300); __HAL_TIM_SET_AUTORELOAD(&htim3, 999); ### EXTI void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(GPIO_Pin == GPIO_PIN_13){} } ### Other Callbacks void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){} void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){} void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){} if(htim->Instance == TIM3){} if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){} ### Others HAL_Delay(500); HAL_PollForConversion(&hadc1, 1); ## 1. Output and Input :star: 記得設定腳位 :star: (再忘記啊) ### Output ioc. GPIO_Output HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, SET); //B0輸出high HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, RESET); //B0輸出low HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); //B0輸出與上一個狀態相反的狀態 ### Input #### digital input ioc. GPIO_Input x = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_13); //讀取F13的數位訊號 #### analog input ioc. Analog, ADC, IN V (V是打勾的意思) HAL_ADC_Start(&hadc1); //開啟adc1 HAL_ADC_PollForConversion(&hadc1, 1); //等待adc1轉換,最多1毫秒 x = HAL_ADC_GetValue(&hadc1); //讀取adc1的類比訊號值 ### delay HAL_Delay(500); //delay, ms, 不可以放中斷內 ## 2. 外部中斷 EXTI ioc. GPIO_EXTI ioc. System Core, GPIO, NVIC V void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ //外部中斷會進去的函式 if(GPIO_Pin == GPIO_PIN_13){ //辨識觸發中斷的是13腳位,只能辨識數字 //要做的事 } } ## 3. timer ### base ioc. Timers, TIM, Clock Source, Internal Clock, set PSC and ARR HAL_TIM_BASE_Start(&htim3); //讓timer3開始計數,反正就是開啟timer x = __HAL_TIM_GET_COUNTER(&htim3); //得到timer3的CNT值 __HAL_TIM_SetCounter(&htim4, 0); //設定timer4的CNT為0 ### timer中斷 ioc. Timers, TIM, Clock Source, Internal Clock, NVIC V, set PSC and ARR HAL_TIM_BASE_Start_IT(&htim3); //讓timer3開始中斷模式 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ //觸發timer中斷後會進去的函式 if(htim->Instance == TIM3){ //辨識是timer3觸發中斷 //要做的事情 } } ## 4. PWM ### PWM output ioc. Timers, TIM, Channel, PWM Generation, set PSC and ARR and Pulse HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); //開啟timer3的channel1的PWM輸出 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 300); //把timer3的channel1的pulse改成300 __HAL_TIM_SET_AUTORELOAD(&htim3, 999); //聽說可以把timer3的arr的值改成999但我沒試過哈哈 ### PWM input ioc. Timers, TIM, combined chnnels, PWM input on CH1, set PSC and larger ARR HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); //timer3的channel1開啟輸入捕獲中斷模式 HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_2); //timer3的channel2開啟輸入捕獲一般模式 int t1, t2; double Frequency, duty; //宣告變數 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){ if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){ //當channel1偵測到上升緣的時候會進中斷 t1 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1) + 1; //讀取channel1抓到上升緣時CNT的值 if(t1 > 0){ //避免剛開始第一個波的時候算出奇怪的東西 t2 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2) + 1; //讀取channel2抓到下降緣時CNT的值 duty = (double)t2 * 100 / t1; //得到duty cycle的百分比 Frequency = (double)1000000 / t1; //得到頻率 } } } //在抓到t1的CNT值後,它會自己幫你把CNT歸零 ### PWM中斷 ioc. Timers, TIM, Channel, PWM Generation, set PSC and ARR and Pulse, NVIC V HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1); //開啟timer3的channel1的PWM輸出及中斷模式 HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); //關閉timer3的channel1的PWM輸出及中斷模式 void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){ //一個方波結束時會進去的中斷函式 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){ //辨識是channel1觸發中斷 //要做的事 } } ### 控servo 50 Hz PWM ioc. PSC 63, ARR 19999 Pulse = 600 + 10 * angle(deg) 數字可能會不一樣,要看servo的型號 ## 5. Encoder ioc. Timers, TIM, Combined Channels, Encoder Mode, set PSC 0, set larger ARR, Encoder Mode T1 and T2 HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL); //開啟timer4的encoder模式 ### 計算馬達轉速 int16_t countNow; //這樣子宣告的話反轉的時候就可以得到負數,原理跟記憶體有關 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { //另外設定一個timer3,每毫秒進中斷計算一次數據 countNow = __HAL_TIM_GetCounter(&htim4); rpsNow = (double) countNow / 4 / resolusion / ratio / 0.001; __HAL_TIM_SetCounter(&htim4, 0); } } ### 計算馬達角度 int16_t countNow; countNow = 0; //初始角度是0 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { //另外設定一個timer3,每毫秒進中斷計算一次數據 countNow = __HAL_TIM_GetCounter(&htim4); angleNow = (double) countNow / resolusion / 4 / ratio * 360; } } ## 6. PID P: 比例控制。主要控制從一開始到目標附近的時間,影響穩態誤差的大小。 I: 積分項。用來消除穩態誤差,太大會造成振盪。 D: 微分項。用來減緩振盪輻度,一點點就夠了。 errorBefore = error; error = goal - now; integral += error * time; differencial = (error - errorBefore) / time; output = P * error + I * integral + D * differencial ## 7. 冷知識 ctrl + shift + f 可以自動排版,酷。