久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 15913|回復(fù): 8
收起左側(cè)

STM32兩輪智能避障小車制作 含keil工程源碼、連線圖

  [復(fù)制鏈接]
ID:495511 發(fā)表于 2019-3-21 17:08 | 顯示全部樓層 |閱讀模式
這個(gè)項(xiàng)目最主要研究了基于STM32F103微處理器的智能小車控制系統(tǒng)的設(shè)計(jì)。整個(gè)系統(tǒng)主要包括STM32F103控制器、電機(jī)驅(qū)動(dòng)電路、紅外檢測(cè)電路、超聲波避障電路。我們采用STM32F103芯片,采用脈沖寬度調(diào)制信號(hào)(PWM)來完成對(duì)電機(jī)的控制,循跡模塊采用紅外探測(cè)法進(jìn)行黑白探測(cè),避障模塊進(jìn)行障礙物檢測(cè)并躲避,超聲波模塊用來檢測(cè)小車與障礙物之間的距離,其他外圍電路可用于其他功能的拓展。小車在運(yùn)行過程中,避障程序優(yōu)先于循跡程序。

1.介紹
1.1項(xiàng)目介紹
1.2研究目的
1.3設(shè)想
1.4研究方法及思路
1.5成果
2.軟硬件設(shè)計(jì)
2.1智能小車介紹
2.2智能小車的組成部分
2.2.1微處理器
2.2.2傳感器檢測(cè)部分
2.2.3超聲波檢測(cè)部分
2.2.4機(jī)器人的腳
2.3循跡原理
2.3.1紅外探測(cè)法
2.3.2循跡方法
2.3.3道路現(xiàn)象分析
2.3.4循跡代碼
2.4避障原理
2.4.1HC-SR04工作原理
2.4.2自由避障策略
2.4.3自由避障代碼
2.5自動(dòng)駕駛系統(tǒng)總體結(jié)構(gòu)
3.軟硬件調(diào)試
3.1軟件調(diào)試
3.2硬件調(diào)試
4.結(jié)論

1.介紹1.1項(xiàng)目介紹

本項(xiàng)目是一個(gè)自動(dòng)駕駛系統(tǒng)的項(xiàng)目,該項(xiàng)目能夠通過提供自動(dòng)駕駛、對(duì)路況智能處理以及其他為行駛系統(tǒng)設(shè)計(jì)的新功能,根據(jù)場(chǎng)景設(shè)定完成自動(dòng)駕駛。該自動(dòng)駕駛的設(shè)備可以是私家汽車, 貨車,也可以是卡車等。

1.2研究目的

設(shè)計(jì)一個(gè)自動(dòng)駕駛系統(tǒng),可以在特定地方尋找軌跡,并沿著軌跡行走;可以檢測(cè)到障礙物的距離并進(jìn)行躲避。

1.3設(shè)想

假設(shè)在校方提供提供的樣機(jī)、紅外探測(cè)器、超聲波檢測(cè)模塊功能正常,電池電量充足,源程序思路代碼均正確,場(chǎng)地軌跡明顯的情況下,我們的小車可以沿著黑色軌跡線持續(xù)行走,遇到障礙物時(shí)小車停止,移開障礙物后,小車可繼續(xù)沿著特定的軌跡行走,直至我們要求其結(jié)束。

1.4研究方法及思路

本次實(shí)驗(yàn)我們采取模擬法,使用HL-1 智能小車模擬真實(shí)的汽車,進(jìn)行實(shí)驗(yàn)。實(shí)驗(yàn)過程中,我們模擬不同的路況,例如“T型路”、“十字路”、“斷頭路”等路況,將小車放在相應(yīng)的位置,觀察其紅外探測(cè)的指示燈的亮滅狀況,并記錄下來,分析其對(duì)應(yīng)情況時(shí)IO口的輸入情況,得出循跡偽代碼;避障時(shí),我們通過設(shè)置障礙物,分析小車遇到障礙物時(shí)應(yīng)做出的回應(yīng),得到相應(yīng)的偽代碼。最終進(jìn)行整體代碼的分析撰寫。


1.5成果

循跡:小車在特定場(chǎng)景模式下,按照黑色的軌跡行駛;

避障:循跡模式下,小車遇障礙物停止;自由模式下,小車到障礙物的距離大于20cm時(shí)直行,小車到障礙物的距離大于10cm小于20cm時(shí)右轉(zhuǎn);小車到障礙物的距離小于10cm時(shí)后退;

文檔:提交技術(shù)報(bào)告、會(huì)議紀(jì)要、進(jìn)度計(jì)劃表、任務(wù)書組、項(xiàng)目組成員表等文檔

2.軟硬件設(shè)計(jì)2.1智能小車介紹
  • 智能小車是輪式機(jī)器人。
  • 它是一個(gè)集環(huán)境感知、規(guī)劃決策、自動(dòng)駕駛等功能于一體的綜合系統(tǒng)                           
  • 它是集中運(yùn)用了計(jì)算機(jī)、傳感、信息、通信、導(dǎo)航、人工智能及自動(dòng)控制等技術(shù)的綜合體。
圖 1 智能小車整體圖
2.2智能小車的組成部分2.2.1微處理器
圖 2 STM32F103C8主芯片整體圖

STM32F103C8主芯片

  •    內(nèi)核:ARM 32位的Cortex-M3 CPU 工作頻率72MHz                           
  •    存儲(chǔ)器:64KB閃存程序存儲(chǔ)器、20KB的SRAM
  •    電源電壓:2.0V~3.6V
  •    數(shù)據(jù)轉(zhuǎn)換器:2個(gè)12位AD轉(zhuǎn)換器(10個(gè)輸入通道)
  •    調(diào)試模式:串行單線調(diào)試(SWD)和JTAG接口
2.2.2傳感器檢測(cè)部分
圖 3 紅外反射傳感器整體圖

紅外反射傳感器

  •    檢測(cè)距離:1mm~8mm
  •    比較器輸出數(shù)字開關(guān)量(0和1)
  •    配多圈可調(diào)精密電位器調(diào)節(jié)靈敏度
  •    工作電壓:3.3V~5V

傳感器的紅外發(fā)射二極管不斷發(fā)射紅外線,當(dāng)發(fā)射出的紅外線沒有被反射回來或被反射回來強(qiáng)度不大時(shí),比較器的輸出端為高電平,指示燈熄滅;當(dāng)紅外線被反射回來且強(qiáng)度足夠大時(shí),比較器的輸出端為低電平,指示燈被點(diǎn)亮。

2.2.3超聲波檢測(cè)部分
圖 4 HC-SR04整體圖

HC-SR04引腳

  • VCC供5V電源
  • GND為地線
  • TRIG觸發(fā)控制信號(hào)輸入
  • ECHO回響信號(hào)輸出
表 1  HC-SR04電器參數(shù)

電氣參數(shù)

HC-SR04聲波模塊

工作電壓

DC  5V

工作電流

15mA

輸入觸發(fā)信號(hào)

10us的TTL脈沖

輸出回響

輸出TTL電平信號(hào)信號(hào),與射程成比例



2.2.4機(jī)器人的腳
圖 5 LN98N集成電機(jī)驅(qū)動(dòng)整體圖
  •    機(jī)械部分

車輪為三個(gè),前輪是兩個(gè)主動(dòng)輪,后輪是一個(gè)從動(dòng)輪

  •    電機(jī)部分
  •   兩個(gè)直流電機(jī)
  •   L298N集成電機(jī)驅(qū)動(dòng)芯片
  •   工作電壓:5V

微控制器產(chǎn)生PWM信號(hào)給L298N,通過調(diào)節(jié)方波的占空比來控制電機(jī)的轉(zhuǎn)速。兩個(gè)電機(jī)轉(zhuǎn)速相同時(shí)小車前進(jìn)或后退;轉(zhuǎn)速不同時(shí)小車轉(zhuǎn)彎;兩個(gè)電機(jī)反向等速運(yùn)轉(zhuǎn)時(shí),小車原地轉(zhuǎn)圈。

2.3循跡原理

小車循跡指的是小車在白色地板上循黑線行走,通常采取的方法是紅外探測(cè)法。

2.3.1紅外探測(cè)法

利用紅外線在不同顏色的物體表面具有不同的反射強(qiáng)度的特點(diǎn),在小車行駛過程中不斷地向地面發(fā)射紅外光,當(dāng)紅外光遇到白色紙質(zhì)地板時(shí)發(fā)生漫反射,反射光被裝在小車上的接收管接收;如果遇到黑線則紅外光被吸收,小車上的接收管接收不到紅外光。單片機(jī)就是否收到反射回來的紅外光為依據(jù)來確定黑線的位置和小車的行走路線。

2.3.2循跡方法

采用與路面顏色有較大差別的線條(白色路面上有條黑色曲線)作引導(dǎo)線,當(dāng)循跡傳感器照到黑線時(shí)輸出高電平1,照到白色時(shí)輸出低電平0。

圖 6 循跡示意圖
2.3.3道路現(xiàn)象分析
路徑名稱
路徑圖示
小車操作



循跡直行


尋跡直行,沿著當(dāng)前黑色路徑指示直行

L彎左轉(zhuǎn)

循跡左轉(zhuǎn)90度,沿著當(dāng)前黑色路徑指示直行

L彎右轉(zhuǎn)

循跡右轉(zhuǎn)90度,沿著當(dāng)前黑色路徑指示直行

T型路口按命令轉(zhuǎn)彎

遇到T型路口,根據(jù)命令轉(zhuǎn)彎。命令左轉(zhuǎn),向左轉(zhuǎn)彎;命令右轉(zhuǎn),向右循跡轉(zhuǎn)彎。

            

              十字路口

遇到十字路口,根據(jù)命令行駛。左轉(zhuǎn),右轉(zhuǎn)直行

斷頭路

遇到斷頭路,左轉(zhuǎn)180度調(diào)頭

圖表 1   道路狀態(tài)模擬

我們采用三路循跡,共8中狀態(tài)指示,對(duì)應(yīng)狀況如下所示

表 2    紅外檢測(cè)狀態(tài)分析

指示燈A、C、E
代號(hào)
回應(yīng)
000
OUT
掉頭(‘u’)
001
R
右轉(zhuǎn)(‘r’)
010
M
執(zhí)行(‘f’)
011
MR
右轉(zhuǎn)(‘r’)
100
L
左轉(zhuǎn)(‘l’)
101
LR

110
LM
左轉(zhuǎn)(‘l’)
111
LMR
右轉(zhuǎn)(‘r’)

備注:我們?cè)O(shè)計(jì)的線路之間有一定的距離,LR狀態(tài)不會(huì)出現(xiàn)

2.3.4循跡代碼
圖 7   循跡代碼截圖
2.4避障原理2.4.1HC-SR04工作原理
  • 給超聲波模塊接入電源和地。
  • 給脈沖觸發(fā)引腳(trig)輸入一個(gè)長(zhǎng)為20us的高電平方波。
  • 輸入方波后,模塊會(huì)自動(dòng)發(fā)射8個(gè)40KHz的聲波,與此同時(shí)回波引腳(echo)端的電平會(huì)由0變?yōu)?;(此時(shí)應(yīng)該啟動(dòng)定時(shí)器計(jì)時(shí))
  • 當(dāng)超聲波返回被模塊接收到時(shí),回波引 腳端的電平會(huì)由1變?yōu)?;(此時(shí)應(yīng)該停止定時(shí)器計(jì)數(shù)),定時(shí)器記下的這個(gè)時(shí)間即為超聲波由發(fā)射到返回的總時(shí)長(zhǎng)。
  •   根據(jù)聲音在空氣中的速度為344米/秒,即可計(jì)算出所測(cè)的距離
2.4.2自由避障策略
表 3自由避障策略分析
當(dāng)前距離(curDis)/cm
應(yīng)答策略/代號(hào)
10<curDis <20
掉頭(‘u’)
curDis<10
后退(‘b’)
curDis >20
直行(‘f’)

2.4.3自由避障代碼
圖 8  自由避障程序截圖
2.5自動(dòng)駕駛系統(tǒng)總體結(jié)構(gòu)

圖 8  自動(dòng)駕駛系統(tǒng)總體結(jié)構(gòu)
3.軟硬件調(diào)試3.1軟件調(diào)試

系統(tǒng)開發(fā)條件:Keil 5.26.2.0

下載工具:J-Link 6.20

3.2硬件調(diào)試

小車連線:

·電源

              小車J2 –VCC 接stm32控制板JP2- +5V

              小車J2 –GND接stm32控制板JP2- GN

              小車J2 –VCC接紅外控制板VCC

小車J2 –GND接紅外控制板GND

·驅(qū)動(dòng)

              小車J3-IN1接stm32控制板JP3-PB10

              小車J3-IN2接stm32控制板JP3-PB11

              小車J3-IN3接stm32控制板JP3-PB12

              小車J3-IN4接stm32控制板JP3-PB13

              小車J3-EN1接stm32控制板JP3-3.3V

              小車J3-EN2接stm32控制板JP3-3.3V

·紅外信號(hào)輸出

              紅外控制板D01接stm32控制板J2-PB5

              紅外控制板D02接stm32控制板J2-PB6

              紅外控制板D03接stm32控制板J2-PB7

·超聲波輸入輸出

              超聲波模塊接小車J6

              小車J4-P2.0接stm32控制板PA0

              小車J4-P2.1接stm32控制板PA4

4.結(jié)論

本次項(xiàng)目設(shè)計(jì)了中央處理模塊、電機(jī)驅(qū)動(dòng)模塊、避障模塊和循跡模塊。其中中央處理模塊的芯片是stm32f103,電機(jī)驅(qū)動(dòng)模塊的主要芯片是LM293D,避障模塊的主要器件是HC-SR04,循跡模塊的主要器件是五個(gè)紅外探測(cè)器(IR)。通過各模塊之間的配合以及軟件和硬件設(shè)計(jì)的結(jié)合,使得最終設(shè)計(jì)出的小車具有循跡功能和避障功能,即能沿軌跡黑線前進(jìn),不會(huì)偏出軌跡,并且當(dāng)探測(cè)到障礙物時(shí)可停止前進(jìn),且探測(cè)距離大于10cm。最終完成了該項(xiàng)目的設(shè)想預(yù)期。



  1. #include <stdio.h>

  2. extern void CarInit(void);
  3. extern void DebugInit(void);
  4. extern void TimerInit(void);
  5. extern void CheckTimer(void);

  6. int main()
  7. {
  8.   TimerInit();    // 系統(tǒng)任務(wù)定時(shí)器初始化
  9.   CarInit();      // 小車各模塊初始化
  10.   DebugInit();

  11.   while(1)
  12.   {
  13.     CheckTimer(); // 開始執(zhí)行定時(shí)任務(wù)
  14.   }
  15. }
  16. timer.c
  17. #include "stm32f10x.h"

  18. void TimerInit()
  19. {
  20.               RCC->APB2ENR |= 1 << 11;

  21.               TIM1->PSC = 36000 - 1;
  22.               TIM1->ARR = 65535;
  23.               TIM1->CR1 = 0x81;
  24. }

  25. static unsigned short TimeGet()
  26. {
  27.   return TIM1->CNT;
  28. }


  29. struct timer
  30. {
  31.   void (*proc)(void);
  32.   int reload;
  33.   unsigned short begin;
  34.   unsigned short duration;
  35. };

  36. #define TIMER_CNT_MAX 8
  37. static struct timer tmr[TIMER_CNT_MAX];
  38. static int tmr_cnt=0;

  39. int SetTimer(unsigned short duration, void (*proc)(void) , int reload)
  40. {
  41.   if (tmr_cnt >= TIMER_CNT_MAX)
  42.   {
  43.     return 0;
  44.   }
  45.   tmr[tmr_cnt].begin = TimeGet();
  46.   tmr[tmr_cnt].duration = duration;
  47.   tmr[tmr_cnt].proc = proc;
  48.   tmr[tmr_cnt].reload = reload;
  49.   tmr_cnt++;
  50.   return 1;
  51. }

  52. // CheckTimer為主程序循環(huán)調(diào)用函數(shù),執(zhí)行定時(shí)事務(wù)
  53. void CheckTimer()
  54. {
  55.   int tmr_idx=0;
  56.   int i=0;
  57.   unsigned short now = TimeGet();

  58.   while (tmr_idx < tmr_cnt)
  59.   {
  60.     if ((unsigned short)(now - tmr[tmr_idx].begin) >= tmr[tmr_idx].duration)
  61.     {
  62.       if (tmr[tmr_idx].proc)
  63.         (*tmr[tmr_idx].proc)();
  64.       if (tmr[tmr_idx].reload)
  65.       {
  66.         tmr[tmr_idx].begin = now;
  67.         tmr_idx++;
  68.       }
  69.       else
  70.       {
  71.         for (i=tmr_idx; i<tmr_cnt-1; i++)
  72.           tmr[i] = tmr[i+1];
  73.         tmr_cnt--;
  74.       }
  75.     }
  76.     else
  77.       tmr_idx++;
  78.   }
  79. }

  80. 3.motor.c

  81. #include "stm32f10x.h"

  82. struct motor
  83. {
  84.   enum {STOP, FORWARD, BACKWARD} state;
  85.   int forward_opcode;
  86.   int backward_opcode;
  87. };

  88. static struct motor left_motor, right_motor;

  89. void MotorInit()
  90. {
  91.   RCC->APB2ENR |= 1 << 3;
  92.   GPIOB->CRH &= 0xff0000ff;
  93.   GPIOB->CRH |= 0x00333300; //PB10              左后退 , PB11              左前進(jìn), PB12              右前進(jìn), PB13  右后退
  94.   GPIOB->BSRR = ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13)) << 16;
  95.             
  96.   left_motor.state = STOP;
  97.   left_motor.forward_opcode = 1 << 11;
  98.   left_motor.backward_opcode = 1 << 10;

  99.   right_motor.state = STOP;
  100.   right_motor.forward_opcode = 1 << 12;
  101.   right_motor.backward_opcode = 1 << 13;            
  102. }

  103. //對(duì)某電機(jī)施加前轉(zhuǎn)驅(qū)動(dòng)電平
  104. static void MotorRotateForward(struct motor *pmotor)
  105. {
  106.               if (pmotor->state != FORWARD)
  107.               {
  108.                 GPIOB->BSRR = (pmotor->backward_opcode << 16) | pmotor->forward_opcode;
  109.                 pmotor->state = FORWARD;
  110.               }
  111. }

  112. //對(duì)某電機(jī)施加后轉(zhuǎn)驅(qū)動(dòng)電平
  113. static void MotorRotateBackward(struct motor *pmotor)
  114. {
  115.               if(pmotor->state != BACKWARD)
  116.               {
  117.                 GPIOB->BSRR = (pmotor->forward_opcode << 16) | pmotor->backward_opcode;
  118.                 pmotor->state = BACKWARD;
  119.               }
  120. }

  121. //對(duì)某電機(jī)停止驅(qū)動(dòng)電平
  122. static void MotorStop(struct motor *pmotor)
  123. {
  124.               if (pmotor->state != STOP)
  125.               {
  126.                 GPIOB->BSRR = (pmotor->forward_opcode | pmotor->backward_opcode) << 16;
  127.                 pmotor->state = STOP;
  128.               }
  129. }

  130. //電機(jī)控制函數(shù)
  131. //輸入?yún)?shù):電機(jī)標(biāo)識(shí)字符'r'或’l'(右或左)   操作代碼字符'f'、'b'或's'(正轉(zhuǎn)、反轉(zhuǎn)或靜止)
  132. void MotorControl(char motor, char op_cmd)
  133. {
  134.   struct motor *pmotor;

  135.   if (motor == 'r')
  136.     pmotor = &right_motor;
  137.   else if (motor == 'l')
  138.     pmotor = &left_motor;
  139.   else
  140.     return;
  141.   if (op_cmd == 'f')
  142.     MotorRotateForward(pmotor);
  143.   if (op_cmd == 'b')
  144.     MotorRotateBackward(pmotor);
  145.   if (op_cmd == 's')
  146.     MotorStop(pmotor);
  147. }
  148. wheel.c
  149. #include "stm32f10x.h"

  150. extern void MotorInit(void);
  151. static void WheelDrive(void);
  152. extern void MotorControl(char motor, char op_cmd);
  153. extern int SetTimer(unsigned short duration, void (*proc)(void) , int reload);

  154. struct wheel
  155. {
  156.   unsigned short period;
  157.   unsigned short duty;
  158.   unsigned short current;
  159.   unsigned char motor;
  160.   unsigned char dir;
  161. };

  162. static struct wheel wheel_left, wheel_right;
  163. static enum{STOP, FORWARD, BACKWARD, LEFT, RIGHT, U_TURN} state;

  164. // WheelInit是對(duì)小車的車輪要的外部接口進(jìn)行初始化。
  165. void WheelInit()
  166. {
  167.               MotorInit();

  168.               wheel_left.period = 50;
  169.               wheel_left.duty = 15;
  170.               wheel_left.current = wheel_left.period;
  171.               wheel_left.dir = 's';
  172.               wheel_left.motor = 'l';
  173.             
  174.               wheel_right.period = 50;
  175.               wheel_right.duty = 15;
  176.               wheel_right.current = wheel_right.period;
  177.               wheel_right.dir = 's';
  178.               wheel_right.motor = 'r';

  179.               state = STOP;
  180.             
  181.               SetTimer(2, WheelDrive, 1); // 每1ms執(zhí)行一次
  182. }

  183. static void WheelRun(struct wheel *pwheel, char dir)
  184. {
  185.               if((dir != 'f') && (dir != 'b'))
  186.     return;
  187.               pwheel->dir = dir;
  188.               pwheel->current++;
  189.               if (pwheel->current >= pwheel->period)
  190.     pwheel->current = 0;
  191.               if (pwheel->current < pwheel->duty)
  192.     MotorControl(pwheel->motor, pwheel->dir);
  193.               if(pwheel->current >= pwheel->duty)
  194.     MotorControl(pwheel->motor, 's');
  195. }

  196. static void WheelStop (struct wheel *pwheel)
  197. {
  198.               if(pwheel->dir == 's')
  199.   return;
  200.               pwheel->dir = 's';
  201.               pwheel->current = pwheel->period;
  202.               MotorControl(pwheel->motor, 's');
  203. }

  204. // WheelDrive是根據(jù)工作狀態(tài)來設(shè)定小車的前進(jìn)、后退、左轉(zhuǎn)、右轉(zhuǎn)及停止,
  205. // 主要是操控WheelRun和WheelStop兩個(gè)函數(shù)實(shí)現(xiàn)所需要的功能。
  206. static void WheelDrive()
  207. {
  208.   switch(state)
  209.   {
  210.                 case FORWARD:
  211.       WheelRun(&wheel_right, 'f');
  212.       WheelRun(&wheel_left, 'f');
  213.     break;
  214.                
  215.     case BACKWARD:
  216.       WheelRun(&wheel_right, 'b');
  217.       WheelRun(&wheel_left, 'b');
  218.     break;

  219.                 case LEFT:
  220.                   WheelRun(&wheel_right, 'f');
  221.       WheelStop(&wheel_left);
  222.     break;

  223.                 case RIGHT:
  224.       WheelStop(&wheel_right);
  225.       WheelRun(&wheel_left, 'f');
  226.     break;

  227.                 case STOP:
  228.       WheelStop(&wheel_right);
  229.       WheelStop(&wheel_left);
  230.     break;

  231.     case U_TURN:
  232.       WheelRun(&wheel_right, 'b');
  233.       WheelRun(&wheel_left, 'f');
  234.     break;
  235.   }
  236. }
  237. // WheelControl外部采用命令方式改變車的工作狀態(tài)
  238. void WheelControl(char cmd)
  239. {
  240.   switch(cmd)
  241.   {
  242.                 case 'f':
  243.       state = FORWARD;
  244.     break;

  245.                 case 'b':
  246.       state = BACKWARD;
  247.     break;

  248.                 case 'l':
  249.       state = LEFT;
  250.     break;

  251.                 case 'r':
  252.       state = RIGHT;
  253.     break;

  254.                 case 's':
  255.       state = STOP;
  256.     break;

  257.     case 'u':
  258.       state = U_TURN;
  259.     break;
  260.   }            
  261. }

  262. void SpeedChange(unsigned char mode)
  263. {
  264.   if (mode)
  265.   {
  266.     wheel_left.duty = 35;
  267.     wheel_right.duty = 35;
  268.   }
  269.   else
  270.   {
  271.     wheel_left.duty = 15;
  272.     wheel_right.duty = 15;
  273.   }
  274. }
  275. detection.c

  276. #include "stm32f10x.h"
  277. #include <stdio.h>

  278. static void UpdateDistance(void);
  279. extern void SpeedChange(unsigned char mode);
  280. extern int  SetTimer(unsigned short duration, void (*proc)(void) ,int reload);

  281. static unsigned char TIM2CaptureFlag; // 輸入捕獲狀態(tài)
  282. unsigned int curDis = 0xffff;         // 當(dāng)前距離
  283. unsigned char SYSTEM_MODE = 0;        // 模式選擇 0--循跡避障,1--自由避障
  284. char InfraredState;

  285. void DetectionInit()
  286. {
  287.   GPIO_InitTypeDef        GPIO_InitStructure;
  288.   NVIC_InitTypeDef        NVIC_InitStructure;
  289.   TIM_ICInitTypeDef       TIM_ICInitStruct;
  290.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  291.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
  292.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  293.   // HC-SR04 Echo PA0 (TIM2_CH1的IC1)
  294.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  295.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  296.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  297.   GPIO_ResetBits(GPIOA, GPIO_Pin_0);

  298.   // HC-SR04 Trig PA4
  299.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  300.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  301.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  302.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  303.   GPIO_ResetBits(GPIOA, GPIO_Pin_4);

  304.   // LED
  305.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  306.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  307.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  308.   GPIO_Init(GPIOC, &GPIO_InitStructure);
  309.   GPIO_ResetBits(GPIOC, GPIO_Pin_13);

  310.   // 左紅外 PB5,中紅外 PB6,右紅外 PB7
  311.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  312.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  313.   GPIO_Init(GPIOB, &GPIO_InitStructure);

  314.   // 功能選擇 PB8
  315.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  316.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  317.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  318.   GPIO_ResetBits(GPIOB, GPIO_Pin_8);

  319.   // TIM2
  320.   TIM_TimeBaseStructure.TIM_Period = 0xffff;                  // 重載計(jì)數(shù)值最大
  321.   TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;               // 計(jì)數(shù)周期1us
  322.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     // 不分頻
  323.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上計(jì)數(shù)
  324.   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  325.   //TIM2_CH1輸入捕獲初始化
  326.   TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;               // 使用通道1
  327.   TIM_ICInitStruct.TIM_ICFilter = 0x02;                       // 不濾波
  328.   TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;          // 不分頻
  329.   TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;// 直接映射到IC1
  330.   TIM_ICInit(TIM2, &TIM_ICInitStruct);

  331.   // TIM2 NVIC配置
  332.   NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  333.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  334.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  335.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  336.   NVIC_Init(&NVIC_InitStructure);

  337.   TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
  338.   TIM_Cmd(TIM2, ENABLE);

  339.   // 100ms更新一次距離
  340.   SetTimer(200, UpdateDistance, 1);
  341. }

  342. char DetectionGet()
  343. {
  344.   InfraredState = (GPIOB->IDR >> 5) & 0x7; // 低三位分別為PB5、PB6、PB7的值
  345.   return InfraredState;
  346. }

  347. void TIM2_IRQHandler(void)
  348. {
  349.   if((TIM2CaptureFlag & 0x10) == 0)                       // 是否是新的一次捕獲
  350.   {
  351.     TIM2CaptureFlag |= 0x10;                              // 捕獲到一次上升沿
  352.     TIM_SetCounter(TIM2, 0);
  353.     TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling);  // 設(shè)置為下降沿捕獲
  354.   }
  355.   else
  356.     curDis = 0.017 * TIM_GetCapture1(TIM2);
  357.   TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);                // 清除中斷標(biāo)志位
  358. }

  359. static void Delay20Us()
  360. {
  361.   int i = 0;
  362.   for (; i <= 231; i++);
  363. }

  364. static void UpdateDistance()
  365. {
  366.   TIM2CaptureFlag = 0;
  367.   TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising);

  368.   // Trig
  369.   GPIO_SetBits(GPIOA, GPIO_Pin_4);
  370.   Delay20Us();
  371.   GPIO_ResetBits(GPIOA, GPIO_Pin_4);

  372.   // 系統(tǒng)模式選擇
  373.   if (GPIOB->IDR & 0x100)
  374.     SYSTEM_MODE = 1;
  375.   else
  376.     SYSTEM_MODE = 0;
  377.   SpeedChange(SYSTEM_MODE);
  378. }
  379. track.c
  380. #include "stm32f10x.h"
  381. #include <stdio.h>

  382. extern void WheelControl(char cmd);

  383. enum {OUT, R, M, MR, L, LR, LM, LMR};
  384. extern unsigned int curDis; // 當(dāng)前測(cè)距結(jié)果
  385. static char lastDetect = M; // 上一次的紅外探測(cè)結(jié)果
  386. static char uTurnFLag = 0;  // 大轉(zhuǎn)彎標(biāo)記

  387. void TrackRun(char detection)
  388. {
  389.   if (curDis <= 15)
  390.     GPIO_SetBits(GPIOC, GPIO_Pin_13);
  391.   else
  392.     GPIO_ResetBits(GPIOC, GPIO_Pin_13);

  393.   // 當(dāng)前距離小于15cm,停車
  394.   if (curDis <= 15)
  395.   {
  396.     WheelControl('s');
  397.     return;
  398.   }

  399.   if (detection != OUT)
  400.     uTurnFLag = 0;

  401.   // 直行的case
  402.   if (detection == M)
  403.     WheelControl('f');

  404.   // 右轉(zhuǎn)的case
  405.   if (detection == R || detection == MR || detection == LMR)
  406.     WheelControl('r');

  407.   // 左轉(zhuǎn)的case
  408.   if (detection == L)
  409.     WheelControl('l');

  410.   // 大轉(zhuǎn)彎
  411.   if (uTurnFLag)
  412.     WheelControl('u');

  413.   // other cases
  414.   if (detection == OUT)
  415.     switch (lastDetect)
  416.     {
  417.       case R:
  418.         WheelControl('r');
  419.       break;

  420.       case M:
  421.         uTurnFLag = 1;
  422.       break;

  423.       case MR:
  424.         WheelControl('r');
  425.       break;

  426.       case L:
  427.         WheelControl('l');
  428.       break;

  429.       case LM:
  430.         WheelControl('l');
  431.       break;
  432.     }

  433.   if (detection != OUT)
  434.     lastDetect = detection;
  435. }
  436. avoid.c
  437. #include "stm32f10x.h"

  438. extern void WheelControl(char cmd);

  439. extern unsigned int curDis;

  440. void ObstacleAvoid()
  441. {
  442.   if (curDis <= 20)
  443.     GPIO_SetBits(GPIOC, GPIO_Pin_13);
  444.   else
  445.     GPIO_ResetBits(GPIOC, GPIO_Pin_13);

  446.   if (curDis >= 10 && curDis <= 20) // 滿足 10cm <= dist <= 20cm
  447.     WheelControl('u');              // 則右轉(zhuǎn)

  448.   if (curDis < 10)                  // 滿足 dist < 10cm
  449.     WheelControl('b');              // 則后退

  450.   if (curDis > 20)
  451.     WheelControl('f');              // 其他case則直行
  452. }
  453. car.c
  454. #include "stm32f10x.h"
  455. #include <stdio.h>

  456. static void CarRun (void);
  457. extern void WheelInit(void);
  458. extern char DetectionGet(void);
  459. extern void DetectionInit(void);
  460. extern void ObstacleAvoid(void);
  461. extern void TrackRun(char detection);
  462. extern int  SetTimer(unsigned short duration, void (*proc)(void) , int reload);

  463. extern unsigned char SYSTEM_MODE;

  464. void CarInit()
  465. {
  466.   WheelInit();               // 車輪初始化
  467.   DetectionInit();           // 傳感器初始化(紅外和超聲波)
  468.   SetTimer(2, CarRun, 1);    // 每1ms執(zhí)行一次CarRun
  469. }

  470. static void CarRun()
  471. {
  472.   char det = DetectionGet();
  473.   if (SYSTEM_MODE)
  474.     ObstacleAvoid();
  475.   else
  476.     TrackRun(det);
  477. }
復(fù)制代碼

底板網(wǎng)上購(gòu)得,技術(shù)文檔、源碼在附件中
全部資料51hei下載地址:
Smart_Car_Lib_Ver.7z (191.29 KB, 下載次數(shù): 203)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:266092 發(fā)表于 2019-3-29 10:47 | 顯示全部樓層
程序質(zhì)量很好,學(xué)習(xí)學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

ID:505045 發(fā)表于 2019-5-18 18:20 | 顯示全部樓層
樓主可以發(fā)給我郵箱嗎?17382569964@163.COM
回復(fù)

使用道具 舉報(bào)

ID:591784 發(fā)表于 2019-7-28 22:08 | 顯示全部樓層
RocWang 發(fā)表于 2019-5-18 18:20
樓主可以發(fā)給我郵箱嗎?

你有嗎?能不能也發(fā)我一份。992163846@qq.com
回復(fù)

使用道具 舉報(bào)

ID:588361 發(fā)表于 2019-7-29 10:21 | 顯示全部樓層
謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

ID:657560 發(fā)表于 2019-12-6 14:45 | 顯示全部樓層
RocWang 發(fā)表于 2019-5-18 18:20
樓主可以發(fā)給我郵箱嗎?

你有嗎?能不能也發(fā)我一份。1610077438@qq.com    謝謝啦
回復(fù)

使用道具 舉報(bào)

ID:826937 發(fā)表于 2020-10-8 19:52 | 顯示全部樓層
包含proteus的仿真文件么
回復(fù)

使用道具 舉報(bào)

ID:818895 發(fā)表于 2020-10-21 20:48 | 顯示全部樓層
這么好的案例,要好好學(xué)習(xí)STM32.
回復(fù)

使用道具 舉報(bào)

ID:889199 發(fā)表于 2021-4-15 16:41 | 顯示全部樓層

不包含proteus文件。——來自已經(jīng)下載人的評(píng)論
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲综合二区 | 国产高清精品一区二区三区 | 1区2区视频 | 一区二区亚洲 | 久久久精品久久 | 日本精品一区二区三区四区 | 色婷婷综合网 | 日韩欧美亚洲综合 | 成人在线中文字幕 | 亚洲综合二区 | 亚洲精品视频在线观看免费 | 亚洲视频一区在线 | 日本精品久久 | 色免费视频 | 中文字幕在线观看视频网站 | 免费看一区二区三区 | 99视频在线看 | 天天综合网天天综合 | 国产高清视频一区 | 欧美精品成人一区二区三区四区 | 欧美亚洲免费 | 中文精品视频 | 国产精品久久久久久久久久久久冷 | 美女一区 | 四虎影院美女 | 日本精品一区二区三区在线观看视频 | 污视频免费在线观看 | 免费一级淫片aaa片毛片a级 | 别c我啊嗯国产av一毛片 | a在线视频 | 国产午夜精品视频 | 日本精品视频 | 精品一区二区视频 | 午夜精品久久久久久久久久久久久 | 久久国产精品一区二区三区 | 欧美精品综合 | 国产精品视频一区二区三区四蜜臂 | 91精品国产综合久久久久久 | 午夜视频一区二区 | 91精品一区二区三区久久久久久 | 五月免费视频 |