,保證你收貨多多
話不多說先來看視頻
處理器電路設(shè)計
單片機(jī)是系統(tǒng)的CPU,是系統(tǒng)穩(wěn)定、正常運(yùn)行的重要前提,以下為單片機(jī)選型的兩種方案:
(1)傳統(tǒng)的8位單片機(jī),是通過超大規(guī)模集成電路對其進(jìn)行集成為一個獨(dú)立芯片的控制器。內(nèi)部組件包括CPU、隨機(jī)存儲器、只讀存儲器、I/O接口、中斷系統(tǒng)、計時器、串口通訊、數(shù)模轉(zhuǎn)換等。STC89C52單片機(jī)是最常見的51單片機(jī),但是資源較少,精確度低,處理速度相比STM32單片機(jī)差很多。
(2)使用目前市面上最常見的STM32單片機(jī),STM32系列單片機(jī)可分為ARMCortex-M3內(nèi)核體系結(jié)構(gòu)的不同應(yīng)用領(lǐng)域。它可分為STM32F1系列和STM32F4系列,STM32F1系列單片機(jī)時鐘頻率最高可達(dá)72米,在同一產(chǎn)品中性能最好。單片機(jī)的基本處理速度為36米,16位單片機(jī)的性能也很好。微晶片的內(nèi)建快閃記憶體相當(dāng)大,范圍從32kb到512kb,可視需要選擇。單個設(shè)備的功耗非常低,僅360mA,32位單片機(jī)產(chǎn)品的功耗最低,每兆赫只有0.5安培。特別值得一提的是,內(nèi)接單晶片匯流排是一種Harvard架構(gòu),可執(zhí)行速度高達(dá)1.25 DMIPS/MHz的指令。此芯片越來越多地被用作主要控制器。
通過對單片機(jī)的資源和處理時間的速度我們采用選擇STM32103C8T6為本系統(tǒng)主控芯片,程序下載是只需要一個JLINK就可以輕松完成。控制器模塊電路如下所示:

電源模塊設(shè)計
本設(shè)計采用鋰電池供電, 模塊的供電電壓一般都為5V,同時超聲波模塊需要較大的電流才能正常工作,所以在降壓的基礎(chǔ)上也要保證足夠大的輸出電流。本設(shè)計采用可調(diào)輸出版本,模塊的輸入電壓范圍廣,輸出電壓在1.25V-35V內(nèi)可調(diào),電壓轉(zhuǎn)換效率高,輸出紋波小。降壓電路如下所示:

電機(jī)驅(qū)動模塊設(shè)計
要完成轉(zhuǎn)向是能夠利用單片機(jī)實現(xiàn)的,然而單片機(jī)I0的帶負(fù)載能力弱,因此我們選擇了大功率放大器件TB6612FNG。TB6612FNG是采用MOSFET-H橋結(jié)構(gòu)的雙通道大電流電路輸出,可以控制2個電機(jī)的驅(qū)動。相比普通的電機(jī)驅(qū)動,外圍電路非常簡單,只需要一個芯片和一個鉭電容進(jìn)行PWM輸出濾波,系統(tǒng)尺寸小。PWM信號輸入頻率范圍廣,輕松滿足本設(shè)計的需求。

電機(jī)驅(qū)動引腳表
1控制芯片:TB6612
2控制芯片數(shù)量:2
3 1號TB6612引腳分配:
4 VM PWMA--------->TIM1_CH1(PA8)
5 VCC AIN2--------->GPIOB_12
6 GND AIN1--------->GPIOB_13
7 AO1 STBY--------->GPIOB_14
8 AO2 BIN1--------->GPIOB_15
9 BO2 BIN2--------->GPIOA_12
10 BO1 PWMB--------->TIM1_CH2(PA9)
11 GND GND
12 2號TB6612引腳分配:
13 VM PWMA--------->TIM1_CH3(PA10)
14 VCC AIN2--------->GPIOB_5
15 GND AIN1--------->GPIOB_6
16 AO1 STBY--------->GPIOB_7
17 AO2 BIN1--------->GPIOB_8
18 BO2 BIN2--------->GPIOA_9
19 BO1 PWMB--------->TIM1_CH4(PA11)
20 GND GND
21真值表
22 AIN1 0 1 0 1
23 AIN2 0 0 1 1
24 BIN1 0 1 0 1
25 BIN2 0 0 1 1
26 停止 正轉(zhuǎn) 反轉(zhuǎn) 剎車
電機(jī)所用到的定時器配置
1//初始化TIMX,設(shè)置TIMx的ARR,PSC
2//arr:自動重裝載初值,psc為預(yù)分頻值,兩者配合控制定時器時鐘的周期
3//定時器選擇TIM1
4static void TB6612_ADVANCE_TIM1_Mode_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty)
5{
6 //-----------------時基結(jié)構(gòu)體初始化-------------------------/
7 TIM_TimeBaseInitTypeDef TIM_TimeStructure;
8 /*開啟定時器1時鐘,即內(nèi)部時鐘CK_INT=72M*/
9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
10 TIM_DeInit(TIMx);
11 /*內(nèi)部時鐘作為計數(shù)器時鐘,72MHZ*/
12 TIM_InternalClockConfig(TIMx);
13 /*自動重裝載寄存器的值,累計TIM_Period+1個頻率后產(chǎn)生一個更新或者中斷*/
14 TIM_TimeStructure.TIM_Period=arr;
15 /*時鐘預(yù)分頻系數(shù)為71,則驅(qū)動計數(shù)器的時鐘CK_CNT=CK_INT/(71+1)=1MHZ*/
16 TIM_TimeStructure.TIM_Prescaler=psc-1;
17 /*設(shè)置時鐘分割,TIM_CKD_DIV1=0,PWM波不延時*/
18 TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;
19 /*向上計數(shù)模式*/
20 TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;
21 /*重復(fù)計數(shù)器*/
22 TIM_TimeStructure.TIM_RepetitionCounter=0;
23 /*初始化定時器*/
24 TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);
25 /*使能ARR預(yù)裝載寄存器(影子寄存器)*/
26 TIM_ARRPreloadConfig(TIMx,ENABLE);
27 //-----------------輸出比較結(jié)構(gòu)體初始化-----------------------/
28 TIM_OCInitTypeDef TIM_OCInitStructure;
29 /*PWM模式設(shè)置,設(shè)置為PWM模式1*/
30 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
31 /*PWM輸出使能相應(yīng)的IO口輸出信號*/
32 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
33 /*設(shè)置占空比大小,CCR1[15:0]: 捕獲/比較通道1的值,若CC1通道配置為輸出:CCR1包含了裝入當(dāng)前捕獲/比較1寄存器的值(預(yù)裝載值)。*/
34 TIM_OCInitStructure.TIM_Pulse=duty;
35 /*輸出通道電平極性設(shè)置*/
36 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
37 /*初始化輸出比較參數(shù)*/
38 TIM_OC1Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道1
39 TIM_OC2Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道2
40 TIM_OC3Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道3
41 TIM_OC4Init(TIMx,&TIM_OCInitStructure);//初始化TIM1 通道4
42 /*自動重裝載*/
43 TIM_OC1PreloadConfig(TIMx,TIM_OCPreload_Enable);
44 TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);
45 TIM_OC3PreloadConfig(TIMx,TIM_OCPreload_Enable);
46 TIM_OC4PreloadConfig(TIMx,TIM_OCPreload_Enable);
47 /*使能計數(shù)器*/
48 TIM_Cmd(TIMx,ENABLE);
49 /*主輸出使能,如果設(shè)置了相應(yīng)的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),則開啟OC和OCN輸出。*/
50 TIM_CtrlPWMOutputs(TIMx,ENABLE);
51}
52//高級定時器輸出通道初始化函數(shù)
53static void TB6612_ADVANCE_TIM_Gpio_Config()
54{
55 GPIO_InitTypeDef GPIO_InitStruct;
56 /*----------通道1配置--------------*/
57 /*定時器1輸出比較通道*/
58 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
59 /*配置為復(fù)用推挽輸出*/
60 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
61 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
62 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
63 GPIO_Init(GPIOA,&GPIO_InitStruct);
64 /*-----------通道二配置-------------*/
65 /*定時器1輸出比較通道*/
66 /*配置為復(fù)用推挽輸出*/
67 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
68 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11;
69 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
70 GPIO_Init(GPIOA,&GPIO_InitStruct);
71 /*-----------通道三配置-------------*/
72 /*定時器1輸出比較通道*/
73 /*配置為復(fù)用推挽輸出*/
74 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
75 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
76 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
77 GPIO_Init(GPIOA,&GPIO_InitStruct);
78 /*-----------通道四配置-------------*/
79 /*定時器1輸出比較通道*/
80 /*配置為復(fù)用推挽輸出*/
81 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
82 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
83 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
84 GPIO_Init(GPIOA,&GPIO_InitStruct);
85}
超聲波模塊
采用HC-SR04超聲波模塊,該芯片具有較高的集成度以及良好的穩(wěn)定性,測度距離十分精確,十分穩(wěn)定。供電電壓為DC5V供電電流小于10mA,探測距離為0.010m-3.5m一共有四個引腳VCC(DC5V)、Triger(發(fā)射端)、Echo(接收端)、GND(地)。HC-SR04實物圖如下:

該模塊是利用單片機(jī)的IO觸發(fā)電平測距,單片機(jī)內(nèi)部利用普通定時器產(chǎn)生一個高電平信號之后,超聲波就可以自主發(fā)送頻率為40khz的方波,然后等待信號的返回;若有信號返回,單片機(jī)IO口就立刻輸出一高電平,利用高電平產(chǎn)生的時間可以計算小車與障礙物的距離。最終距離就是高電平持續(xù)時間乘以聲音在空氣中傳播的速度再除以2,可以反復(fù)測量距離。
在程序開始首先初始化超聲波,利用定時器并設(shè)置時基的自動重裝載初值1000,psc為預(yù)分頻值72,這樣的話我們產(chǎn)生一次中斷的時間是1ms,并設(shè)置搶占優(yōu)先級0,子優(yōu)先級3。HC_SR04_Echo引腳接收到高電平,打開定時器,且每1ms進(jìn)入一次中斷。在測量時首先讓Trig發(fā)送一個大于10us的高電平,然后拉高HC_SR04_Trig,當(dāng)Echo為0時打開定時器計時,當(dāng)Echo為1時關(guān)閉定時器,通過公式計算距離。
模塊工作原理:
(1)單片機(jī)觸發(fā)引腳,輸出高電平信號;
(2)模塊發(fā)送端自動發(fā)送特定頻率的方波;
(3)如果有信號返回,通過IO輸出一高電平,高電平持續(xù)的時間就是超聲波的發(fā)射時長;
(4)測試距離=(高電平時間*聲速(340M/S))/2。
注意:在硬件操作上需要首先讓模塊地端先連接,否則會影響模塊工作。測距時,被測物體的擺放不能太過于雜亂,否則會影響測試結(jié)果。

超聲波重要代碼(可參考)
1/* 獲取接收到的高電平的時間(us*/
2uint32_t Get_HC_SR04_Time(void)
3{
4 uint32_t t=0;
5 t=Acoustic_Distance_Count*1000;//us
6 t+=TIM_GetCounter(TIM2);//獲取us
7 TIM2->CNT =0;
8 Acoustic_Distance_Count=0;
9 Systic_Delay_us(100);
10 return t;
11}
12/*獲取距離*/
13void Get_HC_SR04_Distance(void)
14{
15 static uint16_t count=0;
16 switch(count)
17 {
18 case 1:
19 {
20 GPIO_SetBits(Acoustic_Port,HC_SR04_Trig);//Trig發(fā)送一個大于10us的高電平
21 }break;
22
23 case 15:
24 {
25 count=0;
26 GPIO_ResetBits(Acoustic_Port,HC_SR04_Trig);
27 while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==0);//當(dāng)Echo為0時打開定時器 計時
28 Open_Tim2();
29 while(GPIO_ReadInputDataBit(Acoustic_Port,HC_SR04_Echo)==1);//當(dāng)Echo為0時打開定時器 計時
30 Close_Tim2();
31 HC_SR04_Distance=(float)(Get_HC_SR04_Time()/5.78);
32
33 }break;
34 default:break;
35 }
36 count++;
37}
舵機(jī)模塊
本系統(tǒng)使用的是SG90型號的舵機(jī),舵機(jī)是一種常見的角度驅(qū)動器,本系統(tǒng)需要判斷不同位置的障礙物可以且對轉(zhuǎn)向的力度小。舵機(jī)可以理解為方向盤稱,方向盤是一個常見的名字。它實際上是一個伺服馬達(dá)。舵機(jī)實物圖如下:

舵機(jī)模塊接口簡單,舵機(jī)模塊只有三個引腳。分別引引出了三根線左右兩邊是電源正負(fù)接口線,中間一根是PWM信號線直接連接單片機(jī)的控制引腳。通過控制單片機(jī)的引腳輸出的脈沖寬度進(jìn)而控制舵機(jī)旋轉(zhuǎn)的角度。舵機(jī)每增加0.1ms 舵機(jī)對應(yīng)增加9度。
0.5ms---------0
1.0ms---------45
1.5ms---------90
2.0ms---------135
2.5ms-----------180
20ms的時基脈沖,如果想讓舵機(jī)轉(zhuǎn)90度,就應(yīng)該發(fā)生一個高電平持續(xù)時間為1.5ms,周期為20ms的方波,duty=1.5/20=7.5%。在這里設(shè)置定時器自動重裝載寄存器arr的值為1000,所以當(dāng)占空比為百分之75是,在程序中就要設(shè)置占空比為75/1000=7.5%, 這就是具體的算法。
舵機(jī)重要代碼(可參考)
1/**PWM引腳初始化*/
2static void SERVO_Gpio_Init(void)
3{
4 GPIO_InitTypeDef GPIO_InitStruct;
5 /*----------通道2配置--------------*/
6 /*定時器3輸出比較通道*/
7 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
8 /*配置為復(fù)用推挽輸出*/
9 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
10 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
11 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
12 GPIO_Init(GPIOA,&GPIO_InitStruct);
13}
14//定時器3初始化,設(shè)置TIMx的ARR,PSC
15//arr:自動重裝載初值,psc為預(yù)分頻值,兩者配合控制定時器時鐘的周期
16static void SERVO_TIM_Config(TIM_TypeDef* TIMx,uint16_t arr,uint16_t psc,uint16_t duty)
17{
18 //-----------------時基結(jié)構(gòu)體初始化-------------------------/
19 TIM_TimeBaseInitTypeDef TIM_TimeStructure;
20 /*開啟定時器3時鐘,即內(nèi)部時鐘CK_INT=72M*/
21 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
22 TIM_DeInit(TIMx);
23 /*內(nèi)部時鐘作為計數(shù)器時鐘,72MHZ*/
24 TIM_InternalClockConfig(TIMx);
25 /*自動重裝載寄存器的值,累計TIM_Period+1個頻率后產(chǎn)生一個更新或者中斷*/
26 TIM_TimeStructure.TIM_Period=arr;//1000 當(dāng)定時器從0計數(shù)到999,即1000次,為一個定時周期
27 /*時鐘預(yù)分頻系數(shù)為71,則驅(qū)動計數(shù)器的時鐘CK_CNT=CK_INT/(1440-1+1)=0.05MHZ*/
28 TIM_TimeStructure.TIM_Prescaler=psc-1;;//1400 //即定時器的頻率為5KHZ
29 /*設(shè)置時鐘分割,TIM_CKD_DIV1=0,PWM波不延時*/
30 TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;
31 /*向上計數(shù)模式*/
32 TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;
33 /*重復(fù)計數(shù)器*/
34 TIM_TimeStructure.TIM_RepetitionCounter=0;
35 /*初始化定時器*/
36 TIM_TimeBaseInit(TIMx,&TIM_TimeStructure);
37 /*使能ARR預(yù)裝載寄存器(影子寄存器)*/
38 TIM_ARRPreloadConfig(TIMx,ENABLE);
39 //-----------------輸出比較結(jié)構(gòu)體初始化 開始-----------------------/
40 TIM_OCInitTypeDef TIM_OCInitStructure;
41 /*PWM模式設(shè)置,設(shè)置為PWM模式1*/
42 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
43 /*PWM輸出使能相應(yīng)的IO口輸出信號*/
44 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
45 /*設(shè)置占空比大小,CCR1[15:0]: 捕獲/比較通道1的值,若CC1通道配置為輸出:CCR1包含了裝入當(dāng)前捕獲/比較1寄存器的值(預(yù)裝載值)。*/
46 TIM_OCInitStructure.TIM_Pulse=duty; //占空比大小
47 /*輸出通道電平極性設(shè)置*/
48 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
49 /*初始化輸出比較參數(shù)*/
50 TIM_OC2Init(TIMx,&TIM_OCInitStructure);
51 //-----------------輸出比較結(jié)構(gòu)體初始化 結(jié)束-----------------------/
52 /*自動重裝載*/
53 TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Enable);
54 /*使能計數(shù)器*/
55 TIM_Cmd(TIMx,ENABLE);
56 /*主輸出使能,如果設(shè)置了相應(yīng)的使能位(TIMx_CCER寄存器的CCxE、CCxNE位),則開啟OC和OCN輸出。*/
57 TIM_CtrlPWMOutputs(TIMx,ENABLE);
58}
59/*舵機(jī)PWM初始化
60 每增加0.1ms 舵機(jī)對應(yīng)增加9度
610.5ms---------0
621.0ms---------45
631.5ms---------90
642.0ms---------135
652.5ms-----------180
662.1ms turn_left=150
670.8ms turn_right=25
681.3ms turn_front=75
6920ms的時基脈沖,如果想讓舵機(jī)轉(zhuǎn)90度,就應(yīng)該發(fā)生一個高電平為1.5ms,周期為20ms的方波,duty=1.5/20=7.5% ,而定時器自動重裝載寄存器arr的值為 1000 ,所以duty=75,時占空比為75/1000=7.5%.
70*/
71void SERVO_Init(void)
72{
73 SERVO_Gpio_Init();
74 SERVO_TIM_Config(TIM3,1000,1440,turn_front);
75/** 我們把定時器設(shè)置自動重裝載寄存器 arr 的值為 1000,設(shè)置時鐘預(yù)分頻器為 1440,則
76驅(qū)動計數(shù)器的時鐘:CK_CNT = CK_INT / (1440-1+1)=0.05M,則計數(shù)器計數(shù)一次的時間等于:
771/CK_CNT=20us,當(dāng)計數(shù)器計數(shù)到 ARR 的值 1000 時,產(chǎn)生一次中斷,則中斷一次的時間
78為:1/CK_CNT*ARR=20ms。
79PWM 信號的頻率 f = TIM_CLK/{(ARR+1)*(PSC+1)} TIM_CLK=72MHZ
80 = 72 000 000/(1000*1440)=5KHZ
81*/
82}
83/*舵機(jī)角度控制*/
84void SERVO_Angle_Control(uint16_t Compare2)
85{
86 TIM_SetCompare2(TIM3,Compare2);
87}
編碼器模塊
調(diào)節(jié)小車前進(jìn)的速度和避障快慢我們采用EC11旋轉(zhuǎn)式編碼器,可以用于光度、濕度、音量調(diào)節(jié)等參數(shù)的調(diào)節(jié)。EC11編碼器的形狀類似于電位器,中心有一個旋鈕可以調(diào)節(jié)PWM信號,光電碼盤利用光電轉(zhuǎn)換原理輸出三組方波脈沖。EC11編碼器的實物圖如下:

OLED顯示模塊
用來顯示小車轉(zhuǎn)速,以及左右編碼器數(shù)值和電池電壓等參數(shù)所用的是OLED顯示模塊,分辨率較高,而且功耗低,正常顯示時僅0.06W,供電電壓范圍在3.3V-5V,有IIC和SPI兩種通信協(xié)議可供選擇。顯示模塊的亮度和對比度可以通過程序設(shè)置。由于它使用壽命長以及其他的優(yōu)點,OLED更加適合小系統(tǒng),本系統(tǒng)由于單片機(jī)引腳有限,不適合利用簡單的LCD1602或者12864來顯示,在多方對比之下OLED效果更好。OLED顯示部分相對比較簡單,大家參考中景園的例程就可以實現(xiàn)。
END
微信公眾號:果果小師弟
關(guān)注可了解獲取更多的免費(fèi)資料;
如果你覺得文章對你有幫助,轉(zhuǎn)發(fā)分享,歡迎贊賞最后
10T資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、單片機(jī)、等等!在公眾號內(nèi)回復(fù)「更多資源」,即可免費(fèi)獲取,期待你的關(guān)注!!!
下面的是我的公眾號二維碼圖片,歡迎關(guān)注。
