stm32捕获占空比_基于STM32超声波避障小车
不管是對于初學者還是對于一個玩過單片機的電子愛好者來說,或多或少都接觸到過小車項目,今天給大家介紹的的一個項目基于STM32超聲波避障小車。這也是我曾經的一個課設,在此開源分享給大家,全文5000多字,干貨滿滿,加油讀完,保證你收貨多多。
基于STM32超聲波避障小車https://www.zhihu.com/video/1229107254572007424處理器電路設計
單片機是系統的CPU,是系統穩定、正常運行的重要前提,以下為單片機選型的兩種方案: (1)傳統的8位單片機,是通過超大規模集成電路對其進行集成為一個獨立芯片的控制器。內部組件包括CPU、隨機存儲器、只讀存儲器、I/O接口、中斷系統、計時器、串口通訊、數模轉換等。STC89C52單片機是最常見的51單片機,但是資源較少,精確度低,處理速度相比STM32單片機差很多。 (2)使用目前市面上最常見的STM32單片機,STM32系列單片機可分為ARMCortex-M3內核體系結構的不同應用領域。它可分為STM32F1系列和STM32F4系列,STM32F1系列單片機時鐘頻率最高可達72MHZ,在同一產品中性能最好。單片機的基本處理速度為36米,16位單片機的性能也很好。微晶片的內建快閃記憶體相當大,范圍從32kb到512kb,可視需要選擇。單個設備的功耗非常低,僅360mA,32位單片機產品的功耗最低,每兆赫只有0.5安培。特別值得一提的是,內接單晶片匯流排是一種Harvard架構,可執行速度高達1.25 DMIPS/MHz的指令。此芯片越來越多地被用作主要控制器。 通過對單片機的資源和處理時間的速度我們采用選擇STM32103C8T6為本系統主控芯片,程序下載是只需要一個JLINK就可以輕松完成。控制器模塊電路如下所示:
電源模塊設計
本設計采用鋰電池供電, 模塊的供電電壓一般都為5V,同時超聲波模塊需要較大的電流才能正常工作,所以在降壓的基礎上也要保證足夠大的輸出電流。本設計采用可調輸出版本,模塊的輸入電壓范圍廣,輸出電壓在1.25V-35V內可調,電壓轉換效率高,輸出紋波小。降壓電路如下所示:
電機驅動模塊設計
要完成轉向是能夠利用單片機實現的,然而單片機I0的帶負載能力弱,因此我們選擇了大功率放大器件TB6612FNG。TB6612FNG是采用MOSFET-H橋結構的雙通道大電流電路輸出,可以控制2個電機的驅動。相比普通的電機驅動,外圍電路非常簡單,只需要一個芯片和一個鉭電容進行PWM輸出濾波,系統尺寸小。PWM信號輸入頻率范圍廣,輕松滿足本設計的需求。
電源驅動引腳表
控制芯片:TB6612 控制芯片數量:21號TB6612引腳分配:VM PWMA--------->TIM1_CH1(PA8)VCC AIN2--------->GPIOB_12GND AIN1--------->GPIOB_13AO1 STBY--------->GPIOB_14AO2 BIN1--------->GPIOB_15BO2 BIN2--------->GPIOA_12BO1 PWMB--------->TIM1_CH2(PA9)GND GND2號TB6612引腳分配:VM PWMA--------->TIM1_CH3(PA10)VCC AIN2--------->GPIOB_5GND AIN1--------->GPIOB_6AO1 STBY--------->GPIOB_7AO2 BIN1--------->GPIOB_8BO2 BIN2--------->GPIOA_9BO1 PWMB--------->TIM1_CH4(PA11)GND GND 真值表AIN1 0 1 0 1AIN2 0 0 1 1BIN1 0 1 0 1BIN2 0 0 1 1停止 正轉 反轉 剎車電機所用到的定時器配置
//初始化TIMX,設置TIMx的ARR,PSC //arr:自動重裝載初值,psc為預分頻值,兩者配合控制定時器時鐘的周期 //定時器選擇TIM1 static void TB6612_ADVANCE_TIM1_Mode_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty){//-----------------時基結構體初始化-------------------------/TIM_TimeBaseInitTypeDef TIM_TimeStructure;/*開啟定時器1時鐘,即內部時鐘CK_INT=72M*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);TIM_DeInit(TIMx);/*內部時鐘作為計數器時鐘,72MHZ*/TIM_InternalClockConfig(TIMx);/*自動重裝載寄存器的值,累計TIM_Period+1個頻率后產生一個更新或者中斷*/TIM_TimeStructure.TIM_Period=arr;/*時鐘預分頻系數為71,則驅動計數器的時鐘CK_CNT=CK_INT/(71+1)=1MHZ*/TIM_TimeStructure.TIM_Prescaler=psc-1;/*設置時鐘分割,TIM_CKD_DIV1=0,PWM波不延時*/TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;/*向上計數模式*/TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;/*重復計數器*/TIM_TimeStructure.TIM_RepetitionCounter=0;/*初始化定時器*/TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);/*使能ARR預裝載寄存器(影子寄存器)*/TIM_ARRPreloadConfig(TIMx,ENABLE);//-----------------輸出比較結構體初始化-----------------------/TIM_OCInitTypeDef TIM_OCInitStructure;/*PWM模式設置,設置為PWM模式1*/TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;/*PWM輸出使能相應的IO口輸出信號*/TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;/*設置占空比大小,CCR1[15:0]: 捕獲/比較通道1的值,若CC1通道配置為輸出:CCR1包含了裝入當前捕獲/比較1寄存器的值(預裝載值)。*/TIM_OCInitStructure.TIM_Pulse=duty;/*輸出通道電平極性設置*/TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;/*初始化輸出比較參數*/TIM_OC1Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道1TIM_OC2Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道2TIM_OC3Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道3TIM_OC4Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道4/*自動重裝載*/TIM_OC1PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC3PreloadConfig(TIMx,TIM_OCPreload_Enable);TIM_OC4PreloadConfig(TIMx,TIM_OCPreload_Enable);/*使能計數器*/TIM_Cmd(TIMx,ENABLE);/*主輸出使能,如果設置了相應的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),則開啟OC和OCN輸出。*/TIM_CtrlPWMOutputs(TIMx,ENABLE); } //高級定時器輸出通道初始化函數 static void TB6612_ADVANCE_TIM_Gpio_Config() {GPIO_InitTypeDef GPIO_InitStruct;/*----------通道1配置--------------*//*定時器1輸出比較通道*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/*配置為復用推挽輸出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道二配置-------------*//*定時器1輸出比較通道*//*配置為復用推挽輸出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道三配置-------------*//*定時器1輸出比較通道*//*配置為復用推挽輸出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);/*-----------通道四配置-------------*//*定時器1輸出比較通道*//*配置為復用推挽輸出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct); }超聲波模塊
采用HC-SR04超聲波模塊,該芯片具有較高的集成度以及良好的穩定性,測度距離十分精確,十分穩定。供電電壓為DC5V供電電流小于10mA,探測距離為0.010m-3.5m一共有四個引腳VCC(DC5V)、Triger(發射端)、Echo(接收端)、GND(地)。HC-SR04實物圖如下:
該模塊是利用單片機的IO觸發電平測距,單片機內部利用普通定時器產生一個高電平信號之后,超聲波就可以自主發送頻率為40khz的方波,然后等待信號的返回;若有信號返回,單片機IO口就立刻輸出一高電平,利用高電平產生的時間可以計算小車與障礙物的距離。最終距離就是高電平持續時間乘以聲音在空氣中傳播的速度再除以2,可以反復測量距離。 在程序開始首先初始化超聲波,利用定時器并設置時基的自動重裝載初值1000,psc為預分頻值72,這樣的話我們產生一次中斷的時間是1ms,并設置搶占優先級0,子優先級3。HC_SR04_Echo引腳接收到高電平,打開定時器,且每1ms進入一次中斷。在測量時首先讓Trig發送一個大于10us的高電平,然后拉高HC_SR04_Trig,當Echo為0時打開定時器計時,當Echo為1時關閉定時器,通過公式計算距離。 模塊工作原理: (1)單片機觸發引腳,輸出高電平信號; (2)模塊發送端自動發送特定頻率的方波; (3)如果有信號返回,通過IO輸出一高電平,高電平持續的時間就是超聲波的發射時長; (4)測試距離=(高電平時間*聲速(340M/S))/2。 注意:在硬件操作上需要首先讓模塊地端先連接,否則會影響模塊工作。測距時,被測物體的擺放不能太過于雜亂,否則會影響測試結果。
超聲波重要代碼(可參考)
/* 獲取接收到的高電平的時間(us*/uint32_t Get_HC_SR04_Time(void){uint32_t t=0;t=Acoustic_Distance_Count*1000;//ust+=TIM_GetCounter(TIM2);//獲取usTIM2->CNT =0;Acoustic_Distance_Count=0;Systic_Delay_us(100);return t; } /*獲取距離*/ void Get_HC_SR04_Distance(void) {static uint16_t count=0;switch(count){case 1:{GPIO_SetBits(Acoustic_Port,HC_SR04_Trig);//Trig發送一個大于10us的高電平}break;case 15:{count=0;GPIO_ResetBits(Acoustic_Port,HC_SR04_Trig);while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==0);//當Echo為0時打開定時器 計時Open_Tim2();while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==1);//當Echo為0時打開定時器 計時Close_Tim2();HC_SR04_Distance=(float)(Get_HC_SR04_Time()/5.78);}break;default:break;}count++; }舵機模塊
本系統使用的是SG90型號的舵機,舵機是一種常見的角度驅動器,本系統需要判斷不同位置的障礙物可以且對轉向的力度小。舵機可以理解為方向盤稱,方向盤是一個常見的名字。它實際上是一個伺服馬達。舵機實物圖如下:
舵機模塊接口簡單,舵機模塊只有三個引腳。分別引引出了三根線左右兩邊是電源正負接口線,中間一根是PWM信號線直接連接單片機的控制引腳。通過控制單片機的引腳輸出的脈沖寬度進而控制舵機旋轉的角度。舵機每增加0.1ms 舵機對應增加9度。 0.5ms---------0 1.0ms---------45
1.5ms---------90 2.0ms---------135 2.5ms-----------180 20ms的時基脈沖,如果想讓舵機轉90度,就應該發生一個高電平持續時間為1.5ms,周期為20ms的方波,duty=1.5/20=7.5%。在這里設置定時器自動重裝載寄存器arr的值為1000,所以當占空比為百分之75是,在程序中就要設置占空比為75/1000=7.5%, 這就是具體的算法。
舵機重要代碼(可參考)
/**PWM引腳初始化*/static void SERVO_Gpio_Init(void){GPIO_InitTypeDef GPIO_InitStruct;/*----------通道2配置--------------*//*定時器3輸出比較通道*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/*配置為復用推挽輸出*/GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct); } //定時器3初始化,設置TIMx的ARR,PSC //arr:自動重裝載初值,psc為預分頻值,兩者配合控制定時器時鐘的周期 static void SERVO_TIM_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty) {//-----------------時基結構體初始化-------------------------/TIM_TimeBaseInitTypeDef TIM_TimeStructure;/*開啟定時器3時鐘,即內部時鐘CK_INT=72M*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);TIM_DeInit(TIMx);/*內部時鐘作為計數器時鐘,72MHZ*/TIM_InternalClockConfig(TIMx);/*自動重裝載寄存器的值,累計TIM_Period+1個頻率后產生一個更新或者中斷*/TIM_TimeStructure.TIM_Period=arr;//1000 當定時器從0計數到999,即1000次,為一個定時周期/*時鐘預分頻系數為71,則驅動計數器的時鐘CK_CNT=CK_INT/(1440-1+1)=0.05MHZ*/TIM_TimeStructure.TIM_Prescaler=psc-1;;//1400 //即定時器的頻率為5KHZ/*設置時鐘分割,TIM_CKD_DIV1=0,PWM波不延時*/TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;/*向上計數模式*/TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;/*重復計數器*/TIM_TimeStructure.TIM_RepetitionCounter=0;/*初始化定時器*/TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);/*使能ARR預裝載寄存器(影子寄存器)*/TIM_ARRPreloadConfig(TIMx,ENABLE);//-----------------輸出比較結構體初始化 開始-----------------------/TIM_OCInitTypeDef TIM_OCInitStructure;/*PWM模式設置,設置為PWM模式1*/TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;/*PWM輸出使能相應的IO口輸出信號*/TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;/*設置占空比大小,CCR1[15:0]: 捕獲/比較通道1的值,若CC1通道配置為輸出:CCR1包含了裝入當前捕獲/比較1寄存器的值(預裝載值)。*/TIM_OCInitStructure.TIM_Pulse=duty; //占空比大小/*輸出通道電平極性設置*/TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;/*初始化輸出比較參數*/TIM_OC2Init(TIMx,&TIM_OCInitStructure);//-----------------輸出比較結構體初始化 結束-----------------------//*自動重裝載*/TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);/*使能計數器*/TIM_Cmd(TIMx,ENABLE);/*主輸出使能,如果設置了相應的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),則開啟OC和OCN輸出。*/TIM_CtrlPWMOutputs(TIMx,ENABLE); } /*舵機PWM初始化每增加0.1ms 舵機對應增加9度 0.5ms---------0 1.0ms---------45 1.5ms---------90 2.0ms---------135 2.5ms-----------180 2.1ms turn_left=150 0.8ms turn_right=25 1.3ms turn_front=75 20ms的時基脈沖,如果想讓舵機轉90度,就應該發生一個高電平為1.5ms,周期為20ms的方波,duty=1.5/20=7.5% ,而定時器自動重裝載寄存器arr的值為 1000 ,所以duty=75,時占空比為75/1000=7.5%. */ void SERVO_Init(void) {SERVO_Gpio_Init();SERVO_TIM_Config(TIM3,1000,1440,turn_front); /** 我們把定時器設置自動重裝載寄存器 arr 的值為 1000,設置時鐘預分頻器為 1440,則 驅動計數器的時鐘:CK_CNT = CK_INT / (1440-1+1)=0.05M,則計數器計數一次的時間等于: 1/CK_CNT=20us,當計數器計數到 ARR 的值 1000 時,產生一次中斷,則中斷一次的時間 為:1/CK_CNT*ARR=20ms。 PWM 信號的頻率 f = TIM_CLK/{(ARR+1)*(PSC+1)} TIM_CLK=72MHZ= 72 000 000/(1000*1440)=5KHZ */ } /*舵機角度控制*/ void SERVO_Angle_Control(uint16_t Compare2) {TIM_SetCompare2(TIM3,Compare2); }編碼器模塊
調節小車前進的速度和避障快慢我們采用EC11旋轉式編碼器,可以用于光度、濕度、音量調節等參數的調節。EC11編碼器的形狀類似于電位器,中心有一個旋鈕可以調節PWM信號,光電碼盤利用光電轉換原理輸出三組方波脈沖。EC11編碼器的實物圖如下:
用來顯示小車轉速,以及左右編碼器數值和電池電壓等參數所用的是OLED顯示模塊,分辨率較高,而且功耗低,正常顯示時僅0.06W,供電電壓范圍在3.3V-5V,有IIC和SPI兩種通信協議可供選擇。顯示模塊的亮度和對比度可以通過程序設置。由于它使用壽命長以及其他的優點,OLED更加適合小系統,本系統由于單片機引腳有限,不適合利用簡單的LCD1602或者12864來顯示,在多方對比之下OLED效果更好。OLED顯示部分相對比較簡單,大家參考中景園的例程就可以實現。
總結
以上是生活随笔為你收集整理的stm32捕获占空比_基于STM32超声波避障小车的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不间断电源ups标准_什么是ups不间断
- 下一篇: mfc如何删除lineto画的_见到过的