<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      STM32學習筆記【大學生電子設計競賽】【嵌入式】【標準庫學習】【HAL庫學習】

      前言

      此篇隨筆是博主在打電賽(全國大學生電子設計競賽)中寫下的筆記匯總,備賽歷程可見:視頻

      希望對小白有所幫助。

      STM32入門

      必備知識

      概述

      什么是 STM32:什么是STM32

      STM32 能做什么:STM32能做什么

      ST 官方官方網址:ST官網 (st.com)

      ST 官方中文網站:STMCU中文官網

      型號

      STM32 怎么選型:STM32怎么選型

      STM32 F1與F4的區別:【經驗分享】ST公司STM32F4與STM32F1的區別

      學習資源

      1、STM32 學習

      STM32 標準庫開發:STM32入門教程-2023持續更新中

      STM32 HAL庫開發:【野火】STM32 HAL庫開發實戰指南 教學視頻 手把手教學STM32全系列

      2、Kicad

      KiCad 是一款 PCB 設計軟件,優點是開源、有許多插件可用、有許多快捷鍵方便操作

      學習路徑:KiCad | 6.0 | 簡體中文 | Documentation | KiCad

      PCB(Printed Circuit Board),中文名稱為印制電路板,又稱印刷線路板,是重要的電子部件,是電子元器件的支撐體,是電子元器件電氣相互連接的載體。由于它是采用電子印刷術制作的,故被稱為“印刷”電路板。

      PCB 可以粗淺的理解為焊接死的面包板,目的是為了防止連線在搬運的過程中松動導致問題

      3、部分項目學習

      可以通過學習他人的部分項目,深入對開發過程的理解

      智能小車入門:STM32智能小車教程-循跡-避障-藍牙遙控-跟隨-stm32f103c8t6-stm32最小系統-手把手入門教程

      智能送藥小車標準庫:電賽培訓-基于21年賽題-智能送藥小車

      智能送藥小車HAL庫:電賽“智能送藥小車”【干貨教程】STM32HAL庫CubeMX+pid串級控制+OpenMV數字識別

      智能送藥小車:2021年電賽F題智能送藥小車(國二)開源分享

      其他智能送藥小車:2021全國電賽真題(F)—— 智能送藥小車

      小車跟隨行駛系統:2022電賽省一-小車跟隨行駛系統(C題)

      電磁炮:2019電賽----模擬電磁曲射炮

      滾球:電賽入坑----2017年電賽國賽真題滾球控制系統

      4、電機

      電機快速初步了解:有刷電機與無刷電機的原理

      電機學習:一個視頻學完生活中的所有電機

      電機驅動:一個視頻了解生活中電機的驅動控制及調速方法

      以上均為快速了解,作為科普簡單留下感性印象,下面的視頻能更完善的學習電機

      視頻地址:【野火】電機系列教學視頻,基于STM32硬件(步進電機,直流有刷電機,直流無刷電機,舵機,永磁同步電機PMSM)PID閉環算法

      在線文檔:【野火】電機應用開發實戰指南—基于STM32

      5、PID算法

      電機中的 野火視頻 有講解,此外還有一些資源

      PID理論學習:從不懂到會用!PID從理論到實踐~

      6、相關模塊學習

      灰度傳感器:一種雙灰度傳感器巡黑線方案

      相關資料

      總體

      STM32F10xxx參考手冊(中文)STM32F103C8T6/STM32F10xxx參考手冊(中文)

      數據手冊:STM32F103C8T6/STM32F103x8B數據手冊(中文)

      Cortex-M3權威指南:STM32F103C8T6/Cortex-M3權威指南

      野火F103 標準庫開發指南:野火STM32庫開發實戰指南——基于野火MINI開發板

      野火F103 HAL庫開發指南:野火F103 HAL庫開發指南

      HC-05模塊

      概述:【常用模塊】HC-05藍牙串口通信模塊使用詳解(實例:手機藍牙控制STM32單片機)

      雙機通信:兩個HC-05藍牙互相連接方法

      所有AT指令:HC-05 嵌入式藍牙串口通訊模塊 AT 指令集

      如果接收亂碼,注意看波特率是否正確,默認值為9600!

      STM32 接受藍牙信息代碼如下:

      #include "stm32f10x.h"
      
      void My_USART1_Init(void)
      {
          GPIO_InitTypeDef GPIO_InitStrue;
          USART_InitTypeDef USART_InitStrue;
          NVIC_InitTypeDef NVIC_InitStrue;
      
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //GPIO端口使能  
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  //串口端口使能  
      
          GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;  // 模式: 復用輸出
          GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;  // 引腳: A9
          GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;  // 速度: 10MHz
          GPIO_Init(GPIOA,&GPIO_InitStrue);
      
          GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;  // 模式: 浮空輸入
          GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;  // 引腳: A10
          GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;  // 速度: 10MHz
          GPIO_Init(GPIOA,&GPIO_InitStrue);
      
          USART_InitStrue.USART_BaudRate=9600;  // 波特率: 9600
          USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  // 硬件流控制: 無
          USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;  // 串口模式: 接受與發送
          USART_InitStrue.USART_Parity=USART_Parity_No;  // 極性: 無
          USART_InitStrue.USART_StopBits=USART_StopBits_1;  // 停止位: 1位
          USART_InitStrue.USART_WordLength=USART_WordLength_8b;  // 數據位長度: 8位
      
          USART_Init(USART1,&USART_InitStrue);
      
          USART_Cmd(USART1,ENABLE);  //使能串口1
      
          USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  //開啟接收中斷
      
          NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
          NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
          NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;  // 優先中斷級別: 1
          NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;  // 普通中斷級別: 1
          NVIC_Init(&NVIC_InitStrue);
      }
      
      void USART1_IRQHandler(void)
      {
          u8 res;
          if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
          {
              res= USART_ReceiveData(USART1);
              USART_SendData(USART1,res);
          }
      }
      
      int main(void)
      {
          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
          My_USART1_Init();
          while(1);
      }
      

      電機控制

      電機驅動與編碼器:TB6612與電機編碼器

      超聲波跟隨

      HC-SR04模塊:超聲波原理及測距

      超聲波跟隨小車:超聲波跟隨小車

      調試

      串口調試:USART-FlyMcu下載程序

      配合藍牙模塊可實現無線燒錄功能

      紅外遙控

      介紹:STM32 紅外遙控器詳解

      STM32標準庫學習

      stm32 固件庫函數介紹

      1、RCC

      void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
      void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
      void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
      

      2、GPIO 相關函數

      void GPIO_AFIODeInit(void);							// 復位AFIO外設
      void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);		// 鎖定 GPIO 配置
      void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);	// 配置AFIO事件輸出功能
      void GPIO_EventOutputCmd(FunctionalState NewState);				// 配置AFIO事件輸出功能
      void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);	// 進行引腳重映射
      void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);	// 配置AFIO的數據選擇器
      void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);		// 與以太網有關
      

      3、EXTI 相關函數

      void EXTI_DeInit(void);					// 清除 EXTI 配置
      void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);	// 初始化 EXTI
      void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);// 給EXTI結構體賦默認值
      void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);	// 軟件觸發EXTI外部中斷
      FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);	// 獲取標志位
      void EXTI_ClearFlag(uint32_t EXTI_Line);		// 清空標志位
      ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);		// 獲取中斷標志位
      void EXTI_ClearITPendingBit(uint32_t EXTI_Line);	// 清空中斷標志位
      

      4、中斷向量表

      中斷向量表位于啟動文件(start/startup_stm32f10x.md.s)

      __Vectors       DCD     __initial_sp               ; Top of Stack
                      DCD     Reset_Handler              ; Reset Handler
                      DCD     NMI_Handler                ; NMI Handler
                      DCD     HardFault_Handler          ; Hard Fault Handler
                      DCD     MemManage_Handler          ; MPU Fault Handler
                      DCD     BusFault_Handler           ; Bus Fault Handler
                      DCD     UsageFault_Handler         ; Usage Fault Handler
                      DCD     0                          ; Reserved
                      DCD     0                          ; Reserved
                      DCD     0                          ; Reserved
                      DCD     0                          ; Reserved
                      DCD     SVC_Handler                ; SVCall Handler
                      DCD     DebugMon_Handler           ; Debug Monitor Handler
                      DCD     0                          ; Reserved
                      DCD     PendSV_Handler             ; PendSV Handler
                      DCD     SysTick_Handler            ; SysTick Handler
      
                      ; External Interrupts
                      DCD     WWDG_IRQHandler            ; Window Watchdog
                      DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                      DCD     TAMPER_IRQHandler          ; Tamper
                      DCD     RTC_IRQHandler             ; RTC
                      DCD     FLASH_IRQHandler           ; Flash
                      DCD     RCC_IRQHandler             ; RCC
                      DCD     EXTI0_IRQHandler           ; EXTI Line 0
                      DCD     EXTI1_IRQHandler           ; EXTI Line 1
                      DCD     EXTI2_IRQHandler           ; EXTI Line 2
                      DCD     EXTI3_IRQHandler           ; EXTI Line 3
                      DCD     EXTI4_IRQHandler           ; EXTI Line 4
                      DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                      DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                      DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                      DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                      DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                      DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                      DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                      DCD     ADC1_2_IRQHandler          ; ADC1_2
                      DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                      DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                      DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                      DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                      DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                      DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                      DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                      DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                      DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                      DCD     TIM2_IRQHandler            ; TIM2
                      DCD     TIM3_IRQHandler            ; TIM3
                      DCD     TIM4_IRQHandler            ; TIM4
                      DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                      DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                      DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                      DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                      DCD     SPI1_IRQHandler            ; SPI1
                      DCD     SPI2_IRQHandler            ; SPI2
                      DCD     USART1_IRQHandler          ; USART1
                      DCD     USART2_IRQHandler          ; USART2
                      DCD     USART3_IRQHandler          ; USART3
                      DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                      DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                      DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
      __Vectors_End
      

      5、NVIC 相關函數

      /* 注意:中斷分支整個項目只能進行一次 */
      void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);				// 中斷分組
      
      void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);					// 初始化 NVIC
      void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);			// 設置中斷向量表
      void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);		// 系統低功耗配置
      

      6、TIM 相關函數

      基本函數:

      /* 初始化配置 */
      void TIM_DeInit(TIM_TypeDef* TIMx);								// 恢復缺省配置
      void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);	// 時基單元初始化
      
      void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);			// 時基單元結構體變量賦默認值
      
      void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);					// 使能計數器
      
      void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);		// 使能中斷輸出信號
      
      void TIM_InternalClockConfig(TIM_TypeDef* TIMx);						// 選擇內部時鐘
      void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);		// 選擇其他定時器的時鐘
      void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                      uint16_t TIM_ICPolarity, uint16_t ICFilter);			// 選擇TIx捕獲通道的時鐘
      void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                                   uint16_t ExtTRGFilter);						// 選擇 ETR 通過外部時鐘模式1輸入的時鐘
      void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                                   uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);		// 選擇 ETR 通過外部時鐘模式2輸入的時鐘
      void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                         uint16_t ExtTRGFilter);							// 配置 ETR 預分頻器、極性、濾波器等參數
      
      /* 更改參數 */
      void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);	// 更改預分頻值
      void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);			// 改變計數模式
      void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);				// 改變計數器的預裝功能設置
      void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);					// 給計數器寫入值
      void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);					// 給自動重裝器寫入值
      uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);							// 獲取當前計數器的值
      uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);							// 獲取當前預分頻的值
      
      /* 獲取與清除標志位 */
      FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);	// 獲取標志位
      void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);		// 清空標志位
      ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);		// 獲取中斷標志位
      void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);		// 清空中斷標志位
      

      輸出比較函數:

      void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	// 配置輸出比較模塊
      void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	// 配置輸出比較模塊
      void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	// 配置輸出比較模塊
      void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	// 配置輸出比較模塊
      void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);			// 輸出結構體賦默認值
      void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);		// 配置強制輸出模式,強制輸出高電平或低電平
      void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);		// 配置強制輸出模式,強制輸出高電平或低電平
      void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);		// 配置強制輸出模式,強制輸出高電平或低電平
      void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);		// 配置強制輸出模式,強制輸出高電平或低電平
      void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);		// 配置 CCR 預裝值功能
      void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);		// 配置 CCR 預裝值功能
      void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);		// 配置 CCR 預裝值功能
      void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);		// 配置 CCR 預裝值功能
      void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);			// 配置快速使能
      void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);			// 配置快速使能
      void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);			// 配置快速使能
      void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);			// 配置快速使能
      void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);			// 外部事件時清除 REF 信號
      void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);			// 外部事件時清除 REF 信號
      void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);			// 外部事件時清除 REF 信號
      void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);			// 外部事件時清除 REF 信號
      void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);		// 設置輸出比較的極性
      void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);	// 設置輸出比較的極性(互補通道
      void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);		// 設置輸出比較的極性
      void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);	// 設置輸出比較的極性(互補通道
      void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);		// 設置輸出比較的極性
      void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);	// 設置輸出比較的極性(互補通道
      void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);		// 設置輸出比較的極性
      void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);	// 修改輸出使能
      void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);	// 修改輸出使能
      void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);// 修改輸出比較模式
      void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);			// 更改 CCR 寄存器的值
      void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);			// 更改 CCR 寄存器的值
      void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);			// 更改 CCR 寄存器的值
      void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);			// 更改 CCR 寄存器的值
      

      輸入捕獲函數:

      void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);	// 輸入捕獲單元初始化
      void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);	// 初始化輸入捕獲單元,快速配置兩個通道,配置為PWMI模式
      void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);// 輸入捕獲結構體賦默認值
      void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);	// 選擇輸入觸發源(從模式的觸發源)
      void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);	// 選擇輸出觸發源TRGO(主模式輸出)
      void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);	// 選擇從模式
      void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);	// 配置1通道的分頻器
      void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);	// 配置2通道的分頻器
      void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);	// 配置3通道的分頻器
      void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);	// 配置4通道的分頻器
      void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);
      uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);	// 讀取1通道的CCR
      uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);	// 讀取2通道的CCR
      uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);	// 讀取3通道的CCR
      uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);	// 讀取4通道的CCR
      

      編碼器接口函數:

      void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                      uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);	// 編碼器接口配置
      

      7、ADC相關函數

      void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);	// 配置 ADC_CLK 分頻器
      
      void ADC_DeInit(ADC_TypeDef* ADCx);							// 恢復缺省配置
      void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);			// 初始化 ADC
      void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);					// ADC結構體初始化
      void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);				// 開啟 ADC
      void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);				// 開啟 DMA 輸出信號
      void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);	// 中斷輸出控制
      void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);		// 軟件觸發 ADC
      FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);				// 獲取軟件開始轉換狀態(軟件觸發后立刻從1清零)(一般不用)
      void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);			// 配置每隔幾個通道間斷一次
      void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);			// 啟用間斷模式
      void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);	// ADC規則組通道配置
      void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);		// ADC 外部觸發轉換控制
      uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);					// ADC 獲取轉換值
      uint32_t ADC_GetDualModeConversionValue(void);						// ADC 獲取雙模式轉換值
      
      /* 校準相關配置 */
      void ADC_ResetCalibration(ADC_TypeDef* ADCx);			// 復位校準
      FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);	// 獲取復位校準狀態
      void ADC_StartCalibration(ADC_TypeDef* ADCx);			// 開始校準
      FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);		// 獲取開始校準狀態
      
      /* 注入組相關配置 */
      void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
      void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
      void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
      void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
      void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
      FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
      void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
      void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
      void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
      uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
      
      /* 模擬看門狗相關配置 */
      void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);					// 是否啟動模擬看門狗
      void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);	// 配置高低閾值
      void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);				// 配置看門通道
      
      void ADC_TempSensorVrefintCmd(FunctionalState NewState);		// ADC 溫度傳感器,內部電壓控制
      
      FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);	// 獲取標志位狀態
      void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);		// 清空標志位
      ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);		// 獲取中斷狀態
      void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);		// 清空中斷掛起位
      

      8、DMA 相關函數

      void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);							// 恢復缺省配置
      void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);			// 初始化 DMA
      void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);							// DMA 結構體初始化
      void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);				// 使能 DMA
      void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);	// 中斷輸出使能
      
      void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);	// DMA 設置當前數據寄存器
      uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);			// DMA 獲取當前數據寄存器
      
      FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);	// 獲取標志位狀態
      void DMA_ClearFlag(uint32_t DMAy_FLAG);			// 清空標志位
      ITStatus DMA_GetITStatus(uint32_t DMAy_IT);		// 獲取中斷狀態
      void DMA_ClearITPendingBit(uint32_t DMAy_IT);		// 清空中斷掛起位
      

      9、USART

      void USART_DeInit(USART_TypeDef* USARTx);							// 恢復缺省配置
      void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);			// 初始化 USART
      void USART_StructInit(USART_InitTypeDef* USART_InitStruct);					// USART 結構體初始化
      void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);	// 配置同步時鐘輸出
      void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);			// 同步時鐘輸出結構體初始化
      void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);				// 開啟 USART
      void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);	// 開啟中斷
      void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);	// 開啟USART到DMA的觸發通道
      void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);		// 發送數據
      uint16_t USART_ReceiveData(USART_TypeDef* USARTx);			// 接收數據
      FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);	// 獲取標志位狀態
      void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);		// 清空標志位
      ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);		// 獲取中斷狀態
      void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);		// 清空中斷掛起位
      

      基礎模塊設計

      GPIO

      具體步驟

      • RCC 開啟時鐘
      • GPIO_Init() 初始化 GPIO
      • 使用輸出或輸入函數控制 GPIO
      GPIO_InitTypeDef GPIO_InitStructure;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
      

      EXTI 外部中斷

      EXTI基本結構

      具體步驟

      • RCC 開啟時鐘(GPIO、AFIO)
      • 配置 GPIO 為輸入模式
      • 配置 AFIO,選擇我們使用的一路GPIO
      • 配置 EXTI,選擇邊沿觸發方式、觸發響應方式(中斷響應、事件響應)
      • 配置 NVIC,選擇優先級
      void CountSensor_Init(void)
      {
      	/* RCC 開啟時鐘 */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
      
          /* 配置 GPIO  */
          GPIO_InitTypeDef GPIO_InitStructure;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
      
          /* 配置 AFIO */
          GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
      
          /* 配置 EXTI */
          EXTI_InitTypeDef EXTI_InitStructure;
          EXTI_InitStructure.EXTI_Line = EXTI_Line14;
          EXTI_InitStructure.EXTI_LineCmd = ENABLE;
          EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
          EXTI_Init(&EXTI_InitStructure);
      
          /* 配置 NVIC,中斷分組 */
          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      
          /* 配置 NVIC,設置優先級 */
          NVIC_InitTypeDef NVIC_InitStructure;
          NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
          NVIC_Init(&NVIC_InitStructure);
      }
      
      void EXTI15_10_IRQHandler(void)
      {
      	if (EXTI_GetITStatus(EXTI_Line14) == SET)
      	{
      
      		EXTI_ClearITPendingBit(EXTI_Line14);
      	}
      }
      

      EXTI 與 NVIC 的時鐘不需手動開啟

      Timer 定時中斷

      定時中斷基本結構

      • 具體步驟

        • RCC 開啟時鐘
        • 選擇時基單元的時鐘源(定時中斷選擇內部時鐘源)
        • 配置時基單元
        • 配置輸出中斷控制,允許更新中斷到 NVIC
        • 配置 NVIC,打開定時器中斷通道,分配優先級
        • 運行控制
      void Timer_Init(void)
      {
          
      	/* RCC 開啟時鐘 */
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
      	
      	/* 選擇時基單元的時鐘源,內部時鐘源 */
      	TIM_InternalClockConfig(TIM2);
      	
      	/* 配置時基單元 */
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
      	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
      	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
      	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
      	
      	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
      	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);		// 使能中斷
      	
      	/* 配置 NVIC,中斷分組 */
      	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      	
      	/* 配置 NVIC,配置優先級 */
      	NVIC_InitTypeDef NVIC_InitStructure;
      	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      	NVIC_Init(&NVIC_InitStructure);
      	
      	/* 啟動計時器 */
      	TIM_Cmd(TIM2, ENABLE);
      }
      
      void TIM2_IRQHandler(void)
      {
      	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
      	{
      		
      		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
      	}
      }
      

      PWM 輸出

      PWM基本結構

      • 具體步驟
        • RCC 開啟時鐘
        • 配置時基單元
        • 配置輸出比較單元
        • 配置 GPIO
        • 運行控制,啟動計數器
      #include "stm32f10x.h"                  // Device header
      
      void PWM_Init(void)
      {
      	/* RCC 開啟時鐘 */
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      
      	/* 配置 GPIO */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      
      	/* 選擇時基單元的時鐘源,內部時鐘源 */
      	TIM_InternalClockConfig(TIM2);
      
      	/* 配置時基單元 */
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
      	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
      	TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;		//PSC
      	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
      
      	/* 配置輸出比較單元 */
      	TIM_OCInitTypeDef TIM_OCInitStructure;
      	TIM_OCStructInit(&TIM_OCInitStructure);
      	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
      	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
      	TIM_OC3Init(TIM2, &TIM_OCInitStructure);
      
      	/* 運行控制,啟動計數器 */
      	TIM_Cmd(TIM2, ENABLE);
      }
      
      // 設置占空比
      void PWM_SetCompare3(uint16_t Compare)
      {
      	TIM_SetCompare3(TIM2, Compare);
      }
      
      // 設置預分頻值
      void PWM_SetPrescaler(uint16_t Prescaler)
      {
      	TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
      }
      
      

      IC 輸入捕獲

      輸入捕獲基本結構

      主從觸發模式

      • 具體步驟
        • RCC 開啟時鐘
        • GPIO 初始化為輸入模式(上拉或浮空)
        • 配置時基單元
        • 配置輸入捕獲單元,包括濾波器、極性、直連通道還是交叉通道、分頻器這些參數
        • 選擇從模式的觸發源(TI1FP1)
        • 選擇觸發后執行的操作(Reset操作)
        • 運行控制,啟動計時器
      #include "stm32f10x.h"                  // Device header
      
      void IC_Init(void)
      {
          /* RCC 開啟時鐘 */
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
          /* GPIO 初始化為輸入模式(上拉或浮空) */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
          /* 選擇時基單元的時鐘源,內部時鐘源 */
      	TIM_InternalClockConfig(TIM3);
      	
          /* 配置時基單元 */
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
      	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
      	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
      	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
      	
          /* 配置輸入捕獲單元 */
      	TIM_ICInitTypeDef TIM_ICInitStructure;
      	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
      	TIM_ICInitStructure.TIM_ICFilter = 0xF;
      	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
      	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
      	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
      	TIM_ICInit(TIM3, &TIM_ICInitStructure);
      	
          /* 選擇從模式的觸發源,選擇觸發后執行的操作 */
      	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
      	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
      	
          /* 運行控制,啟動計時器 */
      	TIM_Cmd(TIM3, ENABLE);
      }
      
      uint32_t IC_GetFreq(void)
      {
      	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
      }
      
      

      PWMI 模式

      PWMI基本結構

      • 具體步驟
        • RCC 開啟時鐘
        • GPIO 初始化為輸入模式(上拉或浮空)
        • 配置時基單元
        • 配置輸入捕獲單元
        • 選擇從模式的觸發源(TI1FP1)
        • 選擇觸發后執行的操作(Reset操作)
        • 運行控制,啟動計時器
      #include "stm32f10x.h"                  // Device header
      
      void IC_Init(void)
      {
      	/* RCC 開啟時鐘 */
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
          /* GPIO 初始化為輸入模式(上拉或浮空) */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
          /* 選擇時基單元的時鐘源,內部時鐘源 */
      	TIM_InternalClockConfig(TIM3);
      	
          /* 配置時基單元 */
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
      	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
      	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
      	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
      	
          /* 配置輸入捕獲單元 */
      	TIM_ICInitTypeDef TIM_ICInitStructure;
      	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
      	TIM_ICInitStructure.TIM_ICFilter = 0xF;
      	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
      	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
      	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
      	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
      
      	/* 選擇從模式的觸發源,選擇觸發后執行的操作 */
      	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
      	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
      	
          /* 運行控制,啟動計時器 */
      	TIM_Cmd(TIM3, ENABLE);
      }
      
      uint32_t IC_GetFreq(void)
      {
      	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
      }
      
      uint32_t IC_GetDuty(void)
      {
      	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
      }
      
      

      編碼器接口測速

      編碼器接口基本結構

      • 具體步驟
        • RCC 開啟時鐘
        • GPIO 初始化為輸入模式
        • 配置時基單元
        • 配置輸入捕獲單元,包括濾波器、極性參數
        • 配置編碼器接口模式
        • 運行控制,啟動計時器
      #include "stm32f10x.h"                  // Device header
      
      void Encoder_Init(void)
      {
      	/* RCC 開啟時鐘 */
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
          /* GPIO 初始化為輸入模式 */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
          /* 配置時基單元 */
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
      	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	// 沒用
      	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
      	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;		//PSC
      	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
      	
          /* 配置輸入捕獲單元,包括濾波器、極性參數 */
      	TIM_ICInitTypeDef TIM_ICInitStructure;
      	TIM_ICStructInit(&TIM_ICInitStructure);
      	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
      	TIM_ICInitStructure.TIM_ICFilter = 0xF;
      	TIM_ICInit(TIM3, &TIM_ICInitStructure);
      	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
      	TIM_ICInitStructure.TIM_ICFilter = 0xF;
      	TIM_ICInit(TIM3, &TIM_ICInitStructure);
      	
          /* 配置編碼器接口模式 */
      	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
      	
          /* 運行控制,啟動計時器 */
      	TIM_Cmd(TIM3, ENABLE);
      }
      
      int16_t Encoder_Get(void)
      {
      	int16_t Temp;
      	Temp = TIM_GetCounter(TIM3);
      	TIM_SetCounter(TIM3, 0);
      	return Temp;
      }
      
      

      ADC

      ADC基本結構

      • 具體步驟
        • RCC 開啟時鐘(ADC和GPIO),配置 ADC_CLK 分頻器
        • GPIO 配置為模擬輸入模式
        • 配置多路開關
        • 配置 ADC 轉換器
        • 配置看門狗(可選)
        • 開啟中斷,配置 NVIC(可選)
        • 開啟 ADC
        • 對 ADC 進行校準(建議)
      #include "stm32f10x.h"                  // Device header
      
      void AD_Init(void)
      {
          /* RCC 開啟時鐘 */
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
          /* 配置 ADC_CLK 分頻器 */
      	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
      	
          /* GPIO 配置為模擬輸入模式 */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
          /* 配置多路開關 */
      	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
      	
          /* 配置 ADC 轉換器 */
      	ADC_InitTypeDef ADC_InitStructure;
      	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
      	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
      	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
      	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
      	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
      	ADC_InitStructure.ADC_NbrOfChannel = 1;
      	ADC_Init(ADC1, &ADC_InitStructure);
      	
          /* 開啟 ADC */
      	ADC_Cmd(ADC1, ENABLE);
      	
          /* 對 ADC 進行校準 */
      	ADC_ResetCalibration(ADC1);		// 復位校準
      	while (ADC_GetResetCalibrationStatus(ADC1) == SET);	// 等待復位校準完成
      	ADC_StartCalibration(ADC1);		// 開始校準
      	while (ADC_GetCalibrationStatus(ADC1) == SET);		// 等待校準完成
      }
      
      uint16_t AD_GetValue(void)
      {
      	ADC_SoftwareStartConvCmd(ADC1, ENABLE);			// 軟件觸發轉換
      	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	// 等待轉換完成
      	return ADC_GetConversionValue(ADC1);			// 讀取 ADC 轉換結果
      }
      
      

      DMA

      DMA基本結構

      • 具體步驟
        • RCC 開啟時鐘
        • 初始化 DMA(包括外設和存儲器的各個數據、方向、傳輸計數器、是否需要自動重裝、選擇觸發源、通道優先級)
        • 若為硬件觸發,開啟對應 DMA 輸出(可選)
        • 開啟中斷輸出,配置 NVIC(可選)
        • 開啟 DMA

      改變傳輸寄存器時需先失能,寫入值后再使能

      #include "stm32f10x.h"                  // Device header
      
      uint16_t MyDMA_Size;
      
      void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
      {
          MyDMA_Size = Size;
      	
      	/* RCC 開啟時鐘 */
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
      	
      	/* 初始化 DMA */
          DMA_InitTypeDef DMA_InitStructure;
      	DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;			// 外設起始地址
      	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	// 外設數據寬度
      	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;		// 外設是否自增
      	DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;;				// 存儲器起始地址
      	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;;	// 存儲器數據寬度
      	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;;		// 存儲器是否自增
      	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	// 傳輸方向
      	DMA_InitStructure.DMA_BufferSize = Size;		// 緩沖區大小,即傳輸寄存器
      	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;		// 傳輸模式,即是否使用自動重裝
      	DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;		// 選擇是否存儲器到存儲器,即選擇硬件觸發或軟件觸發
      	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;	// 優先級
      	DMA_Init(DMA1_Channel1, &DMA_InitStructure);
      	
      	/* 開啟 DMA */
          DMA_Cmd(DMA1_Channel1, DISABLE);
      }
      
      void MyDMA_Transfer(void)
      {
      	/* DMA失能、設置當前數據寄存器、DMA使能 */
      	DMA_Cmd(DMA1_Channel1, DISABLE);
      	DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
      	DMA_Cmd(DMA1_Channel1, ENABLE);
      	
      	/* 等待轉運完成、清除轉運完成標志位 */
      	while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
      	DMA_ClearFlag(DMA1_FLAG_TC1);
      }
      
      

      USART 串口

      USART基本結構

      • 具體步驟
        • RCC 開啟時鐘(USART和GPIO)
        • GPIO設置(TX配置為復用輸出、RX配置為輸入)
        • 配置USART
        • 開啟中斷、配置NVIC(可選)
        • 開啟USART
      1. 發送數據

      初始化函數:

      #include "stm32f10x.h"                  // Device header
      #include <stdio.h>
      #include <stdarg.h>
      
      void Serial_Init(void)
      {
      	/* RCC 開啟時鐘 */
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
      	/* GPIO設置 */
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		// 復用推挽輸出
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
      	/* 配置USART */
      	USART_InitTypeDef USART_InitStructure;
      	USART_InitStructure.USART_BaudRate = 9600;						// 波特率
      	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		// 硬件流控制
      	USART_InitStructure.USART_Mode = USART_Mode_Tx;						// 串口模式
      	USART_InitStructure.USART_Parity = USART_Parity_No;					// 校驗位
      	USART_InitStructure.USART_StopBits = USART_StopBits_1;					// 停止位
      	USART_InitStructure.USART_WordLength = USART_WordLength_8b;				// 字長
      	USART_Init(USART1, &USART_InitStructure);
      	
      	/* 開啟USART */
      	USART_Cmd(USART1, ENABLE);
      }
      

      相關函數封裝:

      /**
        * @brief  發送一個字節
        * @param  Byte: 要發送的字節數據
        * @retval None
        */
      void Serial_SendByte(uint8_t Byte)
      {
      	USART_SendData(USART1, Byte);
      	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
      }
      
      /**
        * @brief  發送一個數組
        * @param  Array: 數組的首地址,必須為 uint8_t 類型的數組
        * @param  Length: 數組的長度
        *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
        * @retval None
        */
      void Serial_SendArray(uint8_t *Array, uint16_t Length)
      {
      	uint16_t i;
      	for (i = 0; i < Length; i ++)
      	{
      		Serial_SendByte(Array[i]);
      	}
      }
      
      /**
        * @brief  發送字符串
        * @param  String: 字符串的首地址
        * @retval None
        */
      void Serial_SendString(char *String)
      {
      	uint8_t i;
      	for (i = 0; String[i] != '\0'; i ++)
      	{
      		Serial_SendByte(String[i]);
      	}
      }
      
      /**
        * @brief  指數函數,即X的Y次方
        * @param  X:底數
        * @param  Y:指數
        * @retval None
        */
      uint32_t Serial_Pow(uint32_t X, uint32_t Y)
      {
      	uint32_t Result = 1;
      	while (Y --)
      	{
      		Result *= X;	// 1 乘以X Y次
      	}
      	return Result;
      }
      
      /**
        * @brief  發送數字
        * 	本質將數字手動轉為字符串然后發送
        * @param  Number
        * @param  Length
        * @retval None
        */
      void Serial_SendNumber(uint32_t Number, uint8_t Length)
      {
      	uint8_t i;
      	for (i = 0; i < Length; i ++)
      	{
      		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');	// 發送Number的每一位(高位先行)'0'->偏移
      	}
      }
      
      /**
        * @brief  fputc重定向
        * @param  
        * @retval 
        */
      int fputc(int ch, FILE *f)
      {
      	Serial_SendByte(ch);
      	return ch;
      }
      
      /**
        * @brief  模擬printf重寫打印字符串函數
        * @retval None
        */
      void Serial_Printf(char *format, ...)
      {
      	char String[100];
      	va_list arg;
      	va_start(arg, format);
      	vsprintf(String, format, arg);
      	va_end(arg);
      	Serial_SendString(String);
      }
      
      

      printf 重定向方法3:

      	char String[100];
      	sprintf(String, "\r\nNum3=%d", 333);
      	Serial_SendString(String);
      
      1. 接收數據
      #include "stm32f10x.h"                  // Device header
      #include <stdio.h>
      #include <stdarg.h>
      
      uint8_t Serial_RxData;
      uint8_t Serial_RxFlag;
      
      void Serial_Init(void)
      {
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      	
      	GPIO_InitTypeDef GPIO_InitStructure;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	// 上拉輸入
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
      	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_Init(GPIOA, &GPIO_InitStructure);
      	
      	USART_InitTypeDef USART_InitStructure;
      	USART_InitStructure.USART_BaudRate = 9600;
      	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      	USART_InitStructure.USART_Mode = USART_Mode_Rx;
      	USART_InitStructure.USART_Parity = USART_Parity_No;
      	USART_InitStructure.USART_StopBits = USART_StopBits_1;
      	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      	USART_Init(USART1, &USART_InitStructure);
      	
      	/* 開啟中斷 */
      	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
      	
      	/* NVIC 分組 */
      	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      	
      	/* NVIC 配置 */
      	NVIC_InitTypeDef NVIC_InitStructure;
      	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      	NVIC_Init(&NVIC_InitStructure);
      	
      	USART_Cmd(USART1, ENABLE);
      }
      
      /**
        * @brief  獲取標志位
        * @param  Nonw
        * @retval None
        */
      uint8_t Serial_GetRxFlag(void)
      {
      	if (Serial_RxFlag == 1)
      	{
      		Serial_RxFlag = 0;
      		return 1;
      	}
      	return 0;
      }
      
      /**
        * @brief  獲取串口數據
        * @param  None
        * @retval None
        */
      uint8_t Serial_GetRxData(void)
      {
      	return Serial_RxData;
      }
      
      /**
        * @brief  串口1中斷函數
        * @param  None
        * @retval None
        */
      void USART1_IRQHandler(void)
      {
      	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
      	{
      		Serial_RxData = USART_ReceiveData(USART1);	// 獲取數據
      		Serial_RxFlag = 1;				// 標志位置1
      		USART_ClearITPendingBit(USART1, USART_IT_RXNE);	// 清空終端掛起位
      	}
      }
      
      
      1. 收發 HEX 數據包
      /**
        * @brief  發送數據包
        * @param  None
        * @retval None
        */
      void Serial_SendPacket(void)
      {
      	Serial_SendByte(0xFF);
      	Serial_SendArray(Serial_TxPacket, 4);
      	Serial_SendByte(0xFE);
      }
      
      /**
        * @brief  中斷程序中接收數據包
        * @param  None
        * @retval None
        */
      void USART1_IRQHandler(void)
      {
      	static uint8_t RxState = 0;		// 當前狀態
      	static uint8_t pRxPacket = 0;		// 接收到第幾個數據
      	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
      	{
      		uint8_t RxData = USART_ReceiveData(USART1);
      		
      		if (RxState == 0)		// 狀態0:包頭
      		{
      			if (RxData == 0xFF)
      			{
      				RxState = 1;	// 進入狀態1
      				pRxPacket = 0;	// 接收數據指針置零
      			}
      		}
      		else if (RxState == 1)				// 狀態1:數據
      		{
      			Serial_RxPacket[pRxPacket] = RxData;	// 接收數據
      			pRxPacket ++;				// 指針后移
      			if (pRxPacket >= 4)
      			{
      				RxState = 2;		// 進入狀態3
      			}
      		}
      		else if (RxState == 2)			// 狀態2:包尾
      		{
      			if (RxData == 0xFE)
      			{
      				RxState = 0;		// 重新進入狀態0
      				Serial_RxFlag = 1;	// 置接收標志位為1
      			}
      		}
      		
      		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
      	}
      }
      
      

      STM32 CubeMX及HAL庫學習

      入門

      在擁有固件庫開發的基礎上,觀看 Z小旋的博客-CSDN博客,能夠快速上手 HAL 庫。

      下面對大佬的博客進行排序,方便查找。

      這里推薦: 【STM32】_Z小旋的博客-CSDN博客

      【STM32】HAL庫 STM32CubeMX教程一---安裝教程

      【STM32】HAL庫 STM32CubeMX教程二---基本使用(新建工程點亮LED燈)

      【STM32】HAL庫 STM32CubeMX教程三---外部中斷(HAL庫GPIO講解)_hal_gpio_exti_callback

      【STM32】HAL庫 STM32CubeMX教程四---UART串口通信詳解_hal_uart_transmit

      【STM32】HAL庫 STM32CubeMX教程五---看門狗(獨立看門狗,窗口看門狗)_stm32看門狗

      【STM32】HAL庫 STM32CubeMX教程六---定時器中斷_hal_tim_irqhandler

      【STM32】HAL庫 STM32CubeMX教程七---PWM輸出(呼吸燈)_stm32 hal pwm輸出

      【STM32】HAL庫 STM32CubeMX教程八---定時器輸入捕獲_hal_tim_readcapturedvalue

      【STM32】HAL庫 STM32CubeMX教程九---ADC_stm32cubemx adc

      【STM32】HAL庫 STM32CubeMX教程十---DAC

      【STM32】HAL庫 STM32CubeMX教程十一---DMA (串口DMA發送接收)_cubemx spi dma

      【STM32】HAL庫 STM32CubeMX教程十二---IIC(讀取AT24C02 )_cubemx iic

      【STM32】HAL庫 STM32CubeMX教程十三---RTC時鐘_stm32 hal庫的時鐘

      【STM32】HAL庫 STM32CubeMX教程十四---SPI_cubemx spi

      【STM32】HAL庫 STM32CubeMX教程十五---FMC-SDRAM(一)_stm32cubemx fmc

      【STM32】HAL庫 STM32CubeMX教程十五---FMC-SDRAM(二)

      提高

      1、串口

      初步寫自己的具體邏輯,主要是串口,可以觀看 STM32系列視頻(CubeMX+MDK5+HAL庫+庫函數一站式學習) 進行學習。

      這個視頻主要是標準庫和 HAL庫 函數都有,面向電源題類的。

      2、PID控制

      編碼器測速:【STM32】使用HAL庫進行電機測速,原理、代碼、濾波

      PID速度環:【STM32】使用HAL庫進行電機速度環PID控制,代碼+調參

      PID位置環:【STM32】使用HAL庫進行電機PID位置環控制,代碼+調參

      3、PID調參

      VOFA+調參:使用VOFA+上位機進行PID調參(附下位機代碼)

      VOFA+官網:VOFA+

      4、江科大OLED移植

      基于HAL庫的stm32的OLED顯示屏顯示:基于HAL庫的stm32的OLED顯示屏顯示(模擬I2C,四腳,0.96寸)

      其他

      大佬的筆記整理:【單片機學習筆記】上傳一整年的自學電子筆記,互相交流,共同進步

      電賽國一大佬的方案:2021年全國大學生電子設計大賽F題——智能送藥小車,全方位解決方案+程序代碼(詳細注釋)山東賽區國獎

      STM32中的預編譯

      #define

      1、不帶參宏定義

      #define,宏定義命令,它也是C語言預處理命令的一種。

      所謂宏定義,就是用一個標識符來表示一個字符串,如果在后面的代碼中出現了該標識符,那么就全部替換成指定的字符串。

      例如

      #define N 100
      

      在編譯過程中遇到 N 時,會直接替換為 100。

      2、帶參公定義

      宏定義可以攜帶參數。

      例如

      #define M(y) y*y+3*y  //宏定義
      
      int main()
      {
          // 以下命令解釋為 5*5+3*5
          int a = M(5);
      }
      

      3、防止頭文件重復包含

      如下所示

      #ifndef __HEADER_One_H__ // 意思是:宏開始行,如果還沒有定義 __HEADER_One_H__ 則 進入,否則退出
      #define __HEADER_One_H__ // 定義 __HEADER_One_H__
      
      // header1.h 頭文件內容
      
      #endif // 宏結束行
      

      模版:

      #ifndef __x_H__
      #define __x_H__
      
      #endif // 宏結束行
      

      #if 與 #if defined

      1、#if

      #if的意思是如果宏條件符合,編譯器就編譯這段代碼,否則,編譯器就忽略這段代碼而不編譯,如

      #define  A 0  // 把A定義為0
      
      #if (A > 1)
               printf("A > 1");  // 編譯器沒有編譯該語句,該語句不生成匯編代碼
      #elif (A == 1)
               printf("A == 1"); // 編譯器沒有編譯該語句,該語句不生成匯編代碼
      #else
               printf("A < 1");   // 編譯器編譯了這段代碼,且生成了匯編代碼,執行該語句
      #endif
      

      模版:

      #if x
      
      #else
      
      #endif
      
      #if x
      
      #elif x
      
      #else
      
      #endif
      

      2、#if defined

      #if defined (x)
          ...code...
      #endif
      

      這個#if defined它不管里面的 x 的邏輯是“真”還是“假”。它只管這個程序的前面的宏定義里面有沒有定義 x 這個宏,如果定義了 x 這個宏,那么,編譯器會編譯中間的 …code…,否則會直接忽視中間的 …code… 代碼。

      posted @ 2025-02-11 00:02  鵬展-penggeon  閱讀(694)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产成人精品一区二区秒拍1o| 在线观看免费人成视频色9| 国产精品免费AⅤ片在线观看 | 亚洲女人天堂| 99久久国产一区二区三区| 国产亚洲精品久久yy50| 国产三级精品三级在线区| 免费无码高H视频在线观看| 亚洲精品一区二区三区蜜臀| 天天做天天爱夜夜爽毛片| 午夜激情福利在线免费看| 华坪县| 国产av一区二区三区久久| 综合色一色综合久久网| 亚洲中文字幕久久精品码| 久久国产成人av蜜臀| 日本熟妇XXXX潮喷视频| 麻豆久久久9性大片| 婷婷色婷婷深深爱播五月| 色吊丝一区二区中文字幕| 99热这里只有精品免费播放| 日本久久精品一区二区三区| 一区二区三区激情都市| 公喝错春药让我高潮| 国产a在视频线精品视频下载| 亚洲中文字幕乱码电影| 日韩一区二区三区水蜜桃| 99精品偷自拍| 丝袜老师办公室里做好紧好爽| 亚洲肥熟女一区二区三区| 中文国产日韩欧美二视频| 日本一道一区二区视频| 无码AV无码免费一区二区| 国产精品偷乱一区二区三区 | 青青草无码免费一二三区| 亚洲国产成人综合自在线| 自拍偷在线精品自拍偷99| 国产午夜影视大全免费观看| 同江市| 精品国产女同疯狂摩擦2| 国产精品国产精品一区精品|