---
# System prepended metadata

title: STM32h723 NOTE
tags: [DIT]

---

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