# 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 可以自動排版,酷。