你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32智能小车设计

[复制链接]
STMCU小助手 发布时间:2022-9-3 15:17
历时两周,总算把小车弄好了,总体上来说做的太慢了。自己在32的学习中还不够仔细深入,只是浅面的学习,当真正做一个项目时,暴露的问题就太多了。这次在小车的制作的过程中,遇到了各种各样的问题,软件,硬件,各式各样的问题迎面而来,真的好几次心态崩了。不过还好小车这个项目不只是我一个人在搞,组里的其他成员也在一直在考虑问题,想办法,不断地解决解决,总归小车终于做好了,下面是小车完成图:
微信图片_20220903151642.jpg
) ?9 q# i' ]3 ]$ A# F9 k6 _2 C 微信图片_20220903151646.jpg
9 ^! J" R& f$ z9 U% w( o( H3 i* r
是有点灵魂接线(·<·)。
" a0 U3 C5 [4 J/ C" k7 b* Y
% }* N" s! {- B
' y; N2 l+ x: Q+ I% I. t& a7 Q

模块清单


' m7 B( ~' P7 x* Z$ Z3 @) _6 R
  • stm32f103C8T6开发板
    6 }/ G4 X: D$ W" I& b/ `, S: M
  • HC-SR04超声波测距模块X3
  • TB6612FNG 电机驱动模块X2
  • HC-05主从一体无线蓝牙模块X1
  • 智能小车底盘 4WD小车循迹/避障小车 底盘X1
  • LM2596S DC-DC降压电源模块X1
  • 电源模块3.3V 5V 12V多路输出 电压转换模块DC-DC 12V转3.3V 5V X1
  • 12V电池X1
  • 杜邦线 Xn
  • 转串口模块X1
  • ST-linkX1
  • 面包板X1
    # U2 F% y3 ?; H  }7 O

4 [% b0 p9 [% j# a* o
5 H9 `: P* N8 @' b$ G9 }0 f# s3 o% d- w. f  s8 H. D

完成功能

9 N4 _! d% D) \. K% o
  • 超声波避障
    # V4 j) f; D9 Z' O3 l+ _
  • 蓝牙控制
  • 走矩形

    + v& b  l9 T$ M

* g" p! k9 Y# |9 E+ q; {  T) l! v2 b
各个模块就不再介绍了,具体介绍大家可以自行百度或者看一下我的前几篇Arduino智能小车博客,里面有简单的介绍。

' h! |% Z$ P+ J; S9 m' @
! {. H  r6 |) c" z, c
那么,开始吧。
: w( F2 y4 l8 [* _+ l2 W& J3 Y# `
8 B$ M6 ^% t. J& v! s

准备工作

' {. ]' i0 k, d& R$ h2 A
1.首先配置好keil5 c8t6模板(温馨提示:多看看模板的核心驱动,包括sys.h delay.h usart.h等,这些核心文件一定要保证准确无误!)
: B* q3 W1 u  h/ n. v; F; L. U
2.了解开发板和确保开发板无误% `7 W) r7 s& X7 y, o
3.熟悉怎么用转串口模块和st-link将驱动下载到开发板上。
: V# }1 W/ H# k$ P3 Z) K
下图示为c8t6开发板的引脚图

6 j# ~* Z' ]( d' u, B5 x" z 微信图片_20220903151652.jpg
7 v2 L5 z4 b6 L* T9 o6 p2 _, ^" l0 k
1.超声波避障功能
: G1 h2 v, ?3 t( \3 s1 v% E
我们设计的思路如下,用三个超声波来避障。为什么用三个超声波呢?我们想的是如果用舵机的话,小车在行进过程中并不好判断,只能将车停下,舵机转动来检测哪个方向无障碍物,而用3个超声波不仅可以在行进中判断,也可以让小车没有停下的动作,显得整个过程比较流畅。这就是我们使用三个超声波的原因了。

' V6 M/ a5 K; z& q# P$ Q( X6 l$ \8 p; W
我们使用的是定时器二的通道一,通道二,通道三来进行输入捕获的,那么,第一个问题就来了。
( {2 w9 ^$ e* I% X: d5 V
我们在写超声波代码时,用一个超声波先测试,发现超声波测试的并没有问题 ,串口显示的数据也并没有问题。但是,但是,在用三个超声波同时测试是,却发现数据显示的总有问题,输出的数据总是毫无规律,且数字都非常大,我们就在想是什么问题。
7 X+ r. e4 F/ f" C8 y5 M# c
下面是三个超声波控制的代码:

6 x! C4 p8 ~! v) e8 }( W% E0 p' X
  1. //main.c3 [& C2 M% {. m/ U+ Z8 R6 a
  2. #include "sys.h"
    ( k( X3 B* _, i2 H4 X- i8 }
  3. #include "usart.h"   
    6 ]1 }$ o- m% |4 s& F  k) k* V5 l
  4. #include "delay.h"  
    ( g4 M% F) X4 [  R
  5. #include "led.h"  ! Z) r5 }( Y/ T+ W' N7 n
  6. #include "dianji.h"
    " v& V( w6 f' V) A, }5 _) \
  7. #include "hcsr.h") j% ^. E# |9 ?4 q6 R
  8. u32 DIS_Init(u8 STA,u16 VAL)
    5 M; j, \% D/ I9 L
  9. {
    : P! `/ X& W7 d, i
  10.     u32 temp;0 R2 I( T/ h( p+ W% k( p7 _3 E
  11.     u32 lenth;) |% K, \# s' [; z' b1 K) [
  12.     if((*STA)&0X80)//成功捕获到了一次高电平, U0 {8 `  b  R. {3 f( l9 l
  13.     {
    8 \" e  W% _: e
  14.         temp=STA&0X3F;
    , r$ Z1 {9 g. e; r0 J
  15.         temp*=65536;               //溢出时间总和& k0 [% J! o. z6 d
  16.         temp+=VAL; //得到总的高电平时间
    ) U7 U* N  @( e. m6 m+ C9 z; j5 G
  17.         lenth=temp*0.017;           //计算长度) x' H! q" E2 z4 ~
  18.         STA=0;     //开启下一次捕获7 B0 O; \$ g; a$ G" h' M
  19.     }+ T. r. w' V/ U" @3 j
  20.     return lenth;
    ( u* H5 j  X$ O! W4 e2 }
  21. }
    # Z7 i7 J. j; s1 A9 z7 W
  22. 0 U( {/ s* Y7 ?- P9 v
  23. extern u8 TIM2CH2_CAPTURE_STA; //输入捕获状态& P9 n- F1 v% y% \& }
  24. extern u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值- ?8 j/ m- q- M0 d+ Z  r. |. J, Y
  25. 6 d) Q( O7 ?3 S/ d
  26. extern u8 TIM2CH3_CAPTURE_STA; //输入捕获状态8 F; z: @  ?4 A2 Q' O
  27. extern u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值5 p) _4 I+ \3 |

  28. : S0 u( \; Z# R
  29. extern u8 TIM2CH4_CAPTURE_STA; //输入捕获状态5 H. a+ Y" p% n" @1 Y8 B* B
  30. extern u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    6 j0 }' n% y2 \  ]+ y

  31. % M1 ~* |. L1 M* N. {# Z
  32. int main(void)$ F8 P! T! p- A
  33. {    0 R: }1 q; F# U2 f
  34.   u32 temp=0;
    ! f# j1 M' K& u0 P- E: m
  35.   u32 length1;1 J( A9 N  ^2 g* Z( W
  36.   u32 length2;
    ; \- C0 n9 Y4 ~/ m' l
  37.   u32 length3;   
    9 G0 W1 N. S  Y; B) R7 }2 c
  38.   Stm32_Clock_Init(9); //系统时钟设置
    - U* s, |: \% Y4 ~" o* ]1 |% F
  39.   delay_init(72);       //延时初始化2 M1 z7 {  i1 F, c' I8 \6 R
  40.   uart_init(72,9600);  //串口初始化        //初始化与LED连接的硬件接口5 p8 n3 s# j9 V) \- q
  41.   TIM_PWM1_Init();//10000-1,36-1);//不分频。PWM频率=72M/(0.036M)=2Khz
    4 j& N% E9 c9 p4 ?$ |
  42.   Echo1=0;) b; p* m4 O  A% z$ h; Q& r  {* `' o0 Q
  43.   Echo2=0;
    ! G1 R0 ]" T# ~
  44.   Echo3=0;- ]5 p8 P8 N# c
  45.   HCSR04_Init(0XFFFF,72-1);//以1Mhz的频率计数2 x$ E$ c; o( ^8 @, T6 t) `
  46.   /*while(1)0 O9 J1 n+ D" X
  47.   {
    . L! I6 b4 @1 q* @/ I! S3 P) }
  48.     8 u# u$ P+ |; Y( k+ H1 d
  49.   }*/
    & D4 J  h& w' Y
  50.   while(1)! j# g0 {  _: ?6 u
  51.   {
    , |; V% Y* O, Y6 `$ D6 S
  52.     Echo3=1;
    3 L2 F0 E$ c( {+ m
  53.     delay_us(20);0 k4 o6 ^6 e) J- S* T
  54.     Echo3=0;: r, K% E4 D, ^& J0 m- ^: p3 B4 A
  55.     length1=DIS_Init(&TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL);; [0 m* W% X1 t- {" ]
  56.     delay_ms(1000);2 V$ w$ K0 z' E+ ~/ P8 T
  57.     Echo1=1;4 }2 q5 c1 U$ q# t
  58.     delay_us(20);
    5 D2 N* D9 k2 }0 v7 u* f! ]8 \
  59.     Echo1=0;0 a7 t& Y: s- X% g
  60.     length2=DIS_Init(&TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL);/ b- ]" K& a7 N$ p; Y. O
  61.     delay_ms(1000);/ L' \: b  i( m7 P; t5 F
  62.     Echo2=1;% F" V1 C! k0 \+ M/ K& Z1 C
  63.     delay_us(20);* H; [( w3 N4 G$ z
  64.     Echo2=0;
    ' g9 h1 t) B. I4 d
  65.     length3=DIS_Init(&TIM2CH3_CAPTURE_STA,TIM2CH3_CAPTURE_VAL);9 l3 L$ V. g/ v9 S0 @7 u9 W* d
  66.     printf("%d %d %d\r\n",length1,length2,length3);
    / U  d* n1 m% i  s" e
  67.   //  GO();( [7 G& }) R$ k6 {/ C* @
  68.     delay_ms(500);
    , u4 d: @( ~' S4 D+ ]# T
  69.   }- g) u; ?0 Q! B& O
  70. }
    % F# L% i- C0 M8 D) h

  71. # L3 }$ i% f& F
  72. hcsr.c5 Z: I* }$ u! k& f" W- D
  73. #include "sys.h"2 s" ]. v1 z; J/ a$ D  I' t
  74. #include "delay.h"; V' G- x( i: r
  75. #include "usart.h"# T! k1 S) ~2 W5 r- x* [
  76. #include "hcsr.h"4 h" i& T$ j4 m# z' Y
  77. void HCSR04_Init(u16 arr,u16 psc)! F% x( Z! x  t5 C6 a' g; G( }2 D
  78. {6 Q* ]! z4 r( V: s1 E  J5 A
  79.     RCC->APB1ENR|=1<<0;    //TIM2时钟使能$ `/ s( _! Q- q+ o
  80.     RCC->APB2ENR|=1<<2;    //使能PORTA时钟  V; U6 U# M" Y; c6 D+ ]  R
  81.     RCC->APB2ENR|=1<<3;     //使能PORTB时钟
    4 b2 L9 {9 U5 Z% U9 R3 H6 I/ W
  82.     GPIOA->CRL&=0XFFFF000F;//PA1 清除之前设置
    6 Y' ]  M% D+ n& g3 v, t1 {
  83.     GPIOA->CRL|=0X00008880;//PA1输入8 e1 B! s! H1 D* c. x
  84. //    GPIOA->ODR|=0<<0;
    1 V  c/ b- [1 N/ J* r
  85.     GPIOA->ODR|=0<<1;      //PA1下拉+ V2 P5 u" l4 v" r: \
  86.     GPIOA->ODR|=0<<2;6 g: d" g. S3 h4 _6 v2 l3 f) E
  87.     GPIOA->ODR|=0<<3;6 R+ j% g, ]2 G
  88.   ) ]% I& ]6 v# P% S3 M2 S
  89.     GPIOB->CRL&=0X000FFFFF;//PB7清除之前设置& r6 A5 Z; \& _" t- n: [8 e$ \
  90.     GPIOB->CRL|=0X33300000;//PB7推挽输出
    3 L# \5 W' F# S$ h) [
  91.     GPIOB->ODR|=1<<7;      //PB7 输出高6 s2 U3 G, i3 m+ k, A% F
  92.     GPIOB->ODR|=1<<6;& }9 v, U5 v7 P. h* e' Z' B
  93.     GPIOB->ODR|=1<<5;
    $ f. u! P7 B& s; O7 y0 R( b# P
  94.   
    1 z5 {: O' [4 D! ?
  95.     TIM2->ARR=arr;         //设定计数器自动重装值. u/ t0 e% W0 p3 O. |* W' g- i
  96.     TIM2->PSC=psc;         //预分频器$ K  B. |( L, Y2 h3 y) Q$ y
  97.   
    3 k& [. Q( I- }" \' q& }
  98.     TIM2->CCMR1|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
    0 K- g+ z, d0 ]" p. E2 I
  99.     TIM2->CCMR1|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效6 p! U) K) H' B) f( o& ~
  100.     TIM2->CCMR1|=0<<10;    //IC2PS=00 配置输入分频,不分频
    * ~  A  ?  c- N- b/ U# ^7 k
  101.   
    " w3 v6 y5 J$ g
  102.     TIM2->CCER|=0<<5;      //CC2P=0 上升沿捕获7 j: P3 X, d& i8 B" @' z
  103.     TIM2->CCER|=1<<4;      //CC2E=1 允许捕获计数器的值到捕获寄存器中. X* T  T& Q( _8 g$ Y4 B0 S* j
  104.     7 h$ W, B8 j' f7 h( s, F  M$ H5 a
  105.     TIM2->CCMR2|=1<<0;     //CC2S=01 选择输入端IC1映射到TI1, V' [8 `* `6 S( z- k( q
  106.     TIM2->CCMR2|=1<<4;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
    2 l# I  g& }' |7 |' R% K8 t& f1 ?
  107.     TIM2->CCMR2|=0<<2;    //IC2PS=00 配置输入分频,不分频9 P# J+ w. n/ P6 d4 @, z2 J  [: k9 J
  108.   
    ) O( \* d3 U0 ^" d+ e
  109.     TIM2->CCER|=0<<9;      //CC2P=0 上升沿捕获4 V) \, f: o6 T
  110.     TIM2->CCER|=1<<8;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    5 @; D1 V. b0 c5 S( w2 ]7 ]
  111.    
    % U5 s( e+ A8 M' l8 E
  112.     TIM2->CCMR2|=1<<8;     //CC2S=01 选择输入端IC1映射到TI18 P8 R/ F( I; a; X* M
  113.     TIM2->CCMR2|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效* m. v3 }) e" O
  114.     TIM2->CCMR2|=0<<10;    //IC2PS=00 配置输入分频,不分频
    : k' n8 E1 J8 g: x
  115.   % r  w/ e! T9 ^; x
  116.     TIM2->CCER|=0<<13;      //CC2P=0 上升沿捕获
    0 c8 o! m9 K9 p; C, S" @1 c
  117.     TIM2->CCER|=1<<12;      //CC2E=1 允许捕获计数器的值到捕获寄存器中( f" ~! i2 a) ]7 E1 F
  118.     6 s3 @2 u% Y# h2 E9 [8 p
  119.     TIM2->DIER|=1<<2;      //允许捕获中断, a+ c# E9 C% o& Y+ l  s* s
  120.     TIM2->DIER|=1<<3;      //允许捕获中断
    5 M& [0 }0 N' l1 F) Z
  121.     TIM2->DIER|=1<<4;      //允许捕获中断
    , K" a) S/ i6 B& H* j3 Z
  122.     TIM2->DIER|=1<<0;      //允许更新中断
    9 ]6 {8 q. w5 {/ F
  123.     //TIM2->CR1|=0X01;       //使能定时器27 j; o) t- d2 t% [4 }
  124.     MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
    % N2 s8 ?* ~6 n2 C" e0 @
  125. }
    - r9 v' ]2 C' d% m. E( X  K/ F

  126. 2 Y# U3 m1 }% w5 t7 c$ M- c
  127. u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
    1 I) H6 N8 w" w7 Q
  128. u16 TIM2CH1_CAPTURE_VAL;  //输入捕获值
    ; J2 r" V9 n  F

  129. , o) Y+ K6 H, t7 d# j7 h  m, k1 w+ Y
  130. u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态" _( f* Z* G5 B: a- t' a
  131. u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值3 X# E1 f. G! g9 F0 W7 Z: `. }5 `

  132. - Q- W, @$ E) ?& a" J
  133. u8 TIM2CH3_CAPTURE_STA=0; //输入捕获状态' O8 s% c' k/ b( {. [, [8 D& }
  134. u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值0 a" D6 h8 ^3 w' P" T1 o, I% J. ?1 R
  135. & F) a+ Q+ S' r: D2 M3 g7 R
  136. u8 TIM2CH4_CAPTURE_STA=0; //输入捕获状态
    ( j0 E0 x" ?( M' V
  137. u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    : e0 Y& p2 Y! g# {7 V1 b  _
  138. # e# U4 a% l; e$ K9 l+ N
  139. //定时器2中断服务程序
    ' A. R  {! x* J4 p
  140. void TIM2_IRQHandler(void)3 S0 [, d( H- b: e
  141. {
    8 O2 x$ P' h/ ]% ~4 h( i5 W0 z6 x
  142.     u16 tsr;8 k' Z& V; h- w, W3 c# c  X+ v, z
  143.     tsr=TIM2->SR;% p( r; f. ^' }" E
  144.   
    % H% H# R, C; B; R0 f  G* ]7 j
  145.     if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
    - j. u  E" r1 E1 g2 q
  146.     {
    " X/ b+ y9 w7 ~+ O* o
  147.         if(tsr&0X01)//溢出
    / ]4 \8 u% [+ n6 O! b: ]8 v$ a' g
  148.         {; v' U1 ^& d/ R2 o* C3 u/ y* Z1 ^
  149.             if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了8 m0 i9 v; \) W' W) r9 }7 Q% j
  150.             {* k4 Q5 x  ^) N; A
  151.                 if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了% q* U& y: ^! I6 g# X
  152.                 {
    0 t( [9 G3 J+ U& v4 E
  153.                     TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
    , |! W1 a$ D3 n( _, X- X
  154.                     TIM2CH4_CAPTURE_VAL=0XFFFF;
    3 Z  x) z& J% v5 x: e7 [0 H
  155.                 }else TIM2CH4_CAPTURE_STA++;9 k- d" t- y& F$ u* o% m* ~
  156.             }
    ! ?% r) R, a, M$ @" b" L. S
  157.         }1 E( G! w+ e! @) A; q4 ^
  158.         if(tsr&0x10)//捕获1发生捕获事件- U0 e+ l% H3 J* F
  159.         {
    1 z" h4 a5 v2 [7 \# t: \
  160.             if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿( @1 n1 F# A$ D  I. ~3 T
  161.             {* A9 d3 Y9 c* J$ P+ q1 |
  162.                 TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
    2 c' G7 v# f: q$ e
  163.                 TIM2CH4_CAPTURE_VAL=TIM2->CCR4;//获取当前的捕获值# G, b; e7 b% _( F0 m
  164.                 TIM2->CCER&=~(1<<13);    //CC1P=0 设置为上升沿捕获7 h0 c. V0 a5 _
  165.             }else                       //还未开始,第一次捕获上升沿
    1 n  T$ N" y0 ?
  166.             {
    * b( b: Q( f% F5 N. C6 U2 v- A
  167.                 TIM2CH4_CAPTURE_VAL=0;; L2 \9 h/ k8 x
  168.                 TIM2CH4_CAPTURE_STA=0X40; //标记捕获到了上升沿
    + L1 |# G' X+ o) C- B. B
  169.                 TIM2->CNT=0;             //计数器清空
    $ a8 H4 m/ E* E3 n
  170.           //    TIM2CH4_CAPTURE_VAL=TIM2->CCR4;4 y  z0 Z9 W: X6 @4 {. p, E% i- @
  171.                 TIM2->CCER|=1<<13;        //CC1P=1 设置为下降沿捕获
    3 o, g/ T, n. f6 U
  172.               TIM2->CR1|=0x01;
    8 [8 k1 n8 b* ^/ f- ^
  173.             }
    / I, y% t- }+ ]9 L. H: c7 N4 x5 q
  174.         }
    1 P: ]8 V. i% J$ g  J
  175.     }: C# Y; s! i! u3 l; g8 u' y) x: N
  176.     if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获
    $ G8 u9 |9 Y2 J' q7 Q
  177.     {9 O* @: ~) H4 J, o% U2 U1 ~6 q
  178.         if(tsr&0X01)//溢出' v5 ~; g* K9 n& Q, l
  179.         {) T: b: e* W6 \0 x
  180.             if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
    ) }6 H* ^8 p' |, u' b
  181.             {" H! J. h6 L8 y3 r8 _
  182.                 if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    ; m6 I) o% g8 m0 M9 e
  183.                 {
    ( z1 L: j+ |; Q$ q1 Q  ~( V
  184.                     TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
    ' I3 Y; d% c; _4 ~
  185.                     TIM2CH2_CAPTURE_VAL=0XFFFF;
    6 c  e' o6 M& o+ P$ s: z4 X
  186.                 }else TIM2CH2_CAPTURE_STA++;
    1 Y" ~3 M4 x/ ?4 ~
  187.             }& R  p, b. ~. Q8 L$ M
  188.         }
    4 |  S' o% N* y) x9 N* D
  189.         if(tsr&0x04)//捕获1发生捕获事件( O1 l' {2 {+ _/ ^2 i
  190.         {
    * T& F; D- z: ?. R4 d7 ]3 D7 g
  191.             if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿+ {( M) |5 A8 M6 U" g) u
  192.             {4 l& z+ ?' y6 S  `: V
  193.                 TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
    7 [5 o7 A8 [! Z8 ]. z3 w4 G2 C
  194.                 TIM2CH2_CAPTURE_VAL=TIM2->CCR2;//获取当前的捕获值
    " R) Q5 V0 S. @. ]/ P4 z0 S$ M
  195.                 TIM2->CCER&=~(1<<5);    //CC1P=0 设置为上升沿捕获; m# f  T! M0 s+ u5 L
  196.             }else                       //还未开始,第一次捕获上升沿
    * o: z% a7 F7 `4 @6 `& Q7 d
  197.             {3 C7 d: A0 Y$ e
  198.                 TIM2CH2_CAPTURE_VAL=0;
    6 p& t& ]5 f* k$ T
  199.                 TIM2CH2_CAPTURE_STA=0X40; //标记捕获到了上升沿
    . k# T$ `& l& m+ p; f
  200.                 TIM2->CNT=0;             //计数器清空( t4 [( E# w/ c6 h) V. T
  201.                 TIM2->CCER|=1<<5;        //CC1P=1 设置为下降沿捕获
    ! A  H% N* n, n7 n1 |8 Z: v& |
  202.               TIM2->CR1|=0x01;4 ~) M. H% @+ W, f3 x
  203.             }
    1 v$ j2 f) G/ k# Q& D
  204.         }9 ~1 d  `# P# ^, S) f* L6 v
  205.     }/ L2 y& W1 o9 I& a+ e& n6 A  ~" f: h
  206.     + R+ [! `: }. U" `9 a
  207.     if((TIM2CH3_CAPTURE_STA&0X80)==0)//还未成功捕获
      }0 S8 K! T$ B7 ^1 |7 Y; m, @
  208.     {
    : f, T4 m. L( ^' X
  209.         if(tsr&0X01)//溢出8 \& X- [. b; ^5 H) A
  210.         {
    $ v- j" N' b3 s$ `* B9 I4 d1 C
  211.             if(TIM2CH3_CAPTURE_STA&0X40)//已经捕获到高电平了
    0 A& x; V7 S" C, e2 D/ y
  212.             {
    % P  x) M; X8 h9 d9 B# Z& z
  213.                 if((TIM2CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了% e3 J: i" t: H9 j& \% `" a
  214.                 {
    ( C7 N! }1 c1 C3 q% g+ n. f( H
  215.                     TIM2CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
    " P8 Z. v5 j  m' E  o6 n) E( z
  216.                     TIM2CH3_CAPTURE_VAL=0XFFFF;# M4 v, x, A  j
  217.                 }else TIM2CH3_CAPTURE_STA++;2 L" b2 Q+ O" k' Z  e
  218.             }7 M3 t0 F  {% K+ o( S3 Q; }) O
  219.         }
    1 w0 ]3 ^  T6 ^6 _
  220.         if(tsr&0x08)//捕获1发生捕获事件6 \8 G4 L9 W3 [6 X" p* B
  221.         {8 K" i9 f3 @0 l* D3 o, l2 Z
  222.             if(TIM2CH3_CAPTURE_STA&0X40) //捕获到一个下降沿
    2 x, }. [- l* B1 L, i, i; t3 |
  223.             {
    ' d( ]6 t) \( k$ O, o
  224.                 TIM2CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽" M6 |1 c$ h% I) G/ M; l2 |
  225.                 TIM2CH3_CAPTURE_VAL=TIM2->CCR3;//获取当前的捕获值, N, j- D$ f3 F
  226.                 TIM2->CCER&=~(1<<9);    //CC1P=0 设置为上升沿捕获8 d$ x  L  }# e/ u6 U
  227.             }else                       //还未开始,第一次捕获上升沿) F( T! l& m+ y% O/ N) N
  228.             {3 m) J3 c( w* H- M
  229.                 TIM2CH3_CAPTURE_VAL=0;- c! |% [6 a5 U& ?& z6 ^- @
  230.                 TIM2CH3_CAPTURE_STA=0X40; //标记捕获到了上升沿
    8 n8 Y* g9 p( k! o7 K! W$ P4 D
  231.                 TIM2->CNT=0;  
    4 ?. A5 H* D3 j: t: E( l5 \$ r
  232.             //    TIM2CH3_CAPTURE_VAL=TIM2->CCR3;              //计数器清空
    5 [* \2 k! A1 V4 O
  233.                 TIM2->CCER|=1<<9;        //CC1P=1 设置为下降沿捕获
    3 j9 P2 i$ g9 v, Z. D  V: M0 d
  234.               TIM2->CR1|=0x01;) y, C% |0 P, ]: @
  235.             }3 m+ N/ T8 @6 {, h
  236.         }, l7 ?% F' I4 n. Z, e
  237.   }& W% R+ W* |1 L& l
  238.    
    9 X; Q0 l+ z: |2 E; F: [
  239.         . `4 \: G3 g* n& V) h# R9 z6 P
  240.     TIM2->SR=0;//清除中断标志位
    / Y1 A" B% q! C/ U) N' C
  241.    
    / M7 {, `5 k- g# M7 S2 j; k' V2 W7 F
  242. }
    6 U# G: p; M7 s- s

  243.   s8 d1 e, b9 d, D" n. M; e' m
  244. hcsr.h
    , N: S. Y/ Q7 {% ]! }7 p# c
  245. #ifndef __HSCR04_H$ n+ }) p1 ?& A$ j7 p  T
  246. #define __HSCR04_H0 z/ y/ X; L8 t! g
  247. #include "sys.h"
    # I8 ~7 Q9 L& S0 i+ @; y  |
  248. : w# c1 [9 K* b1 P( a
  249. #define Echo1 PBout(7) // PB7  @' T2 l" F) m; V& Z. k" A
  250. #define Echo2 PBout(6) // PB7- H/ D9 l& ^& \2 F1 c3 E' s
  251. #define Echo3 PBout(5) // PB7! q# ?/ F  a+ X- W% q. \; T' H
  252. & Y; T6 f. b$ p% J% Z
  253. void HCSR04_Init(u16 arr,u16 psc);
    * A7 M  S: C% ?, h; j: n

  254. 0 T+ A  }* T4 v7 W
  255. #endif
复制代码

& k/ |9 k! R# a9 ]6 k
最后发现,输入捕获代码中,中断服务函数中,TIM2->CNT不能清零,因为初始化中,用的是同一个定时器的通道2,3,4。如果每一次中断函数的某个通道函数将TIM2->CNT清0,那么其他通道的记录的TIM2->CNT的值就发生变化,从而导致了各种各样的情况。

/ P' j$ \, k+ ^  }
问题二就是从串口读取数据,当时挺崩溃的。首先是keil5模板问题,当时串口怎么都显示不出来数据,我们当时都很疑惑。一直反复的看代码,考虑各种情况,但还是显示不出来数据。一开始我们以为是超声波接受的反馈的数据不满足某个条件,所以没有显示。到后面查来查去,又在想是开发板并没有给电压?超声波集体歇B?最终发现,usart.c文件写的串口不是我们接线串口所对应的。当时心态挺炸的,改了之后终于可以测试数据了。
4 v# g5 w1 v) F+ e& e0 E' K
问题三是我们在没接电机驱动之前,超声波接收的数据无论准不准确,最起码能接收到,可是接了电机驱动却发现每次返回的值都是0。我们当时并没有找到原因,又在猜想是不是电机用到的定时器对超声波的定时器有影响?又在想是不是外部电子设备把信号影响了?又在想各种各样的问题?

! V2 z' C' O: R- z; S
最终解决的方法是,串口模块给的电压不够。(我也不知道这样形容的对不对,但感觉就是),为什么这样说呢?

* k6 X2 j/ }2 ^8 I
当时一开始我想的是,超声波的模块在用转串口模块给其供电时,是不是超声波模块的VCC和GND引脚并没有电压,从而导致信号发射不出去。于是我用万用表测试两侧电压,发现是5V没错。又在想是不是发出信号并没有发去,于是我让TRIG引脚一直为1,测试TRIG电压发现为2.6v左右。在此之后,我又用12v的电池降压给开发板供电,发现TRIG电压为3.3V左右。我想验证,是不是电压问题而导致的接收数据为零。所以我想用电池给开发板供电,然后打开串口监视器看数据。但是要想启用串口监视器,必须要用串口给开发板供电。最后我们选用了蓝牙模块,从手机的接收器来观察数据。终于,果然是电压的问题,数据成功出现了!!!(哭了)

; [5 A8 ^; m: I: ?2.用PWM调控电机速度
这一过程能稍微简单一些,就是一开始还是电压的问题,四个轮子根本带不起来。反复查看代码后并没有太多问题,可是轮子还是不转,但是发现电机嗡嗡响,去掉一个电机后,将速度调大,发现两个轮子缓缓的动了。验证时,我们将轮子速度调小,发现轮子不转,证明了代码并无问题。

8 H; l# D8 _# B, a0 ?' I
pwm控制部分代码:
  1. #include "dianji.h"
    6 d) I6 i: m* a; {9 u. S
  2. #include "sys.h"
    4 h1 `8 Q; w. o! Q
  3. #include "delay.h"& F- X; h- z5 F; b
  4. . T1 m9 E+ C$ F$ k  x
  5. void TIM_PWM1_Init(u16 arr,u16 psc)% B3 `! d0 v% f- F/ i3 K, ^
  6. {                / ~5 Z' A) n! D+ Y( d) l( m# d1 K
  7.   //此部分需手动修改IO口设置
    . s# b; j- L2 K5 C$ T
  8.   RCC->APB1ENR|=1<<1;   //TIM3时钟使能   
    7 s& t1 ~5 d1 f; l" B# a6 y3 X
  9.   RCC->APB2ENR|=1<<2;    //GPIOA使能' P) N# O* b- R
  10.   RCC->APB2ENR|=1<<3;   //GPIOB使能
    / p# i& Y) C- a; b  \& k- O& c- Y
  11.   RCC->APB2ENR|=1<<4;
    + ^) J2 v. t6 ~7 ^1 C! }5 ^
  12.   GPIOA->CRL&=0X00FFFFFF;  //PA(7)PA(6)做复用,PA(3)是BIN1 PA(4)BIN2 PA(5)STBY
    , J/ Z5 K8 @, L  k
  13.   GPIOA->CRL|=0XBB000000;% v. G- p' s1 _3 o7 n3 Z
  14.   //GPIOA->ODR|=1<<7;9 q* o2 W! X4 P9 F2 J$ J
  15.   //GPIOA->ODR|=1<<6;
    : [- u: k0 t3 O* O; @3 [* Y+ }& K. O: G; N
  16.   GPIOC->CRH&=0X000FFFFF;
    * k7 \; }# W8 L$ a6 o! w
  17.   GPIOC->CRH|=0X33300000;& m" j, A4 W( Q; T# h9 T  A
  18.   GPIOB->CRL&=0XFFFFF000; //PB(0)是AIN1 PB(1)是AIN29 D& @; R5 @* x
  19.   GPIOB->CRL|=0X00000333;  E, f2 c8 h/ q2 f  A; e
  20.   TIM3->ARR=arr;      //设定计数器3自动重装值
    * d( g0 U7 ~! w9 d
  21.   TIM3->PSC=psc;      //预分频器设置
    # h1 Q( o, N$ t5 x7 p0 l
  22.   : ~( W" i, ^+ O3 {
  23.   TIM3->CCMR1|=6<<4;    //CH1 PWM2模式     
    9 A- D$ A- N; v
  24.   TIM3->CCMR1|=1<<3;     //CH1预装载使能   
    ; \5 R4 z2 r. k  f& N* c
  25.   TIM3->CCMR1|=6<<12;    //CH2 PWM2模式     % p* y4 z4 F3 r) n& \: Z( D
  26.   TIM3->CCMR1|=1<<11;     //CH2预装载使能  
    7 B' _. k5 u. `( {; d* q5 \( c
  27.   $ _( ~. g- M8 h4 I
  28.    TIM3->CCER|=1<<0;     //OC1 输出使能" X% y2 y+ K  e+ h! F
  29.   TIM3->CCER|=1<<4;     //OC1 输出使能  
    ( W' @) j; T& h- A, D' q
  30. //  TIM3->BDTR|=1<<15;     //MOE 主输出使能     
    1 z( e* C, Q" z3 S
  31. : b6 C- U2 |* ^+ N9 K2 h' @
  32.   TIM3->CR1=0x0080;     //ARPE使能
    5 }1 x- L  O5 p4 I
  33.   TIM3->CR1|=0x01;      //使能定时器3 4 j+ E9 C# F- O  s9 ~" q

  34. / i. y  q# y% R$ O
  35.   RCC->APB2ENR|=1<<11; //TIM1定时器使能. A3 e) M8 j6 z
  36.   GPIOA->CRH&=0XFFFF0FF0;
    ' z( a4 s* D, i0 I. i8 A* F
  37.   GPIOA->CRH|=0X0000B00B;
    4 X; p% T+ L. c4 o. ?; D6 r
  38.   //GPIOA->ODR|=1<<8;/ F2 t# I6 F8 u: B( h+ E3 _
  39.   //GPIOA->ODR|=1<<11;
    : \5 f4 A  z1 \9 ]+ o8 a0 M
  40.   
    8 q# i" ~; S; ^# D2 ?1 {  T
  41.   GPIOB->CRH&=0X0000FFFF;/ Z6 b' Z. \8 l0 w  k; A6 X
  42.   GPIOB->CRH|=0X33330000;
    0 W  s3 H6 T0 b9 `, p
  43.   ; [0 `* j: j: Q) ~' A
  44.   TIM1->ARR=arr;      //设定计数器自动重装值
    - g: {5 @& F" G0 M/ U1 u$ _
  45.   TIM1->PSC=psc;      //预分频器设置
    . y" y4 i7 k$ I* X3 O9 {
  46.   ! v; O5 m& t- r! \4 @
  47.   TIM1->CCMR1|=6<<4;    //CH1 PWM2模式     
    ' P1 {" {  i% F. V. y5 X; R
  48.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    # @6 t% g0 O  e1 z. F! b- `
  49.   TIM1->CCMR2|=6<<12;    //CH4 PWM2模式     5 }" B8 |0 d& R0 p7 [% z. e
  50.   TIM1->CCMR2|=1<<11;     //CH4预装载使能  
    % v- C( v1 ~- J! V& q. \) B
  51.     D+ D) t1 w) V' T1 W2 h' Q/ U
  52.   TIM1->CCER|=1<<0;     //OC1 输出使能3 T- H8 @7 @! K& L& f  A
  53.   TIM1->CCER|=1<<12;     //OC4 输出使能  
    ! J/ V2 U8 k4 o4 H
  54.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     
    6 l. P8 N' F+ t' G9 e

  55. 4 w1 U% m& L% [3 G
  56.   TIM1->CR1=0x0080;     //ARPE使能 6 x6 N) O+ d& t/ r" I9 A
  57.   TIM1->CR1|=0x01;      //使能定时器1
    0 m3 B4 `5 s& j$ D7 Z0 s4 x" F
  58.   
    & x# U: r3 s8 J. Z. R2 d
  59.   STBY=1;
    9 a7 Z; [  L' o" ?5 d2 k
  60.   STBY1=1;) A+ o9 k. ]1 d5 T% y3 O
  61. }( Y  ], s7 M" c8 {; Z* E9 ?8 @3 k8 q
  62. " s$ [9 c5 A: g* n$ q" T' t$ Z
  63. void GO(u16 a,u16 b)
    0 V6 [' }0 Q( v+ J8 W7 @: B9 i! R
  64. {
    - S# q5 h4 Y( }5 ~; b$ X% m+ u
  65.   AIN1=0;     //AIN1,BIN1,AIN2,BIN2控制轮子方向
    / v3 p4 g: Y5 S" l" [6 P' N
  66.   AIN2=1;
    ) F% F# l2 \4 E: {: p
  67.   BIN1=0;
    & O/ O* I6 p( ^/ C( |3 b
  68.   BIN2=1;0 [% M5 j' `/ l9 z3 K: ]8 y9 J  Z
  69.   AIN3=1;# L" _, `5 \! E5 p8 u$ Z0 Q0 n) t
  70.   AIN4=0;# s! ^3 q% s" o) x( O* T
  71.   BIN3=1;) i% F- G4 X7 Q0 K" F, K
  72.   BIN4=0;  
    # Y$ m0 X1 l! |3 V0 H
  73.   4 t& q& p9 J5 B# w
  74.   TIM3->CCR1=a;//右上,控制速度7 e/ Z. X" Y0 @  v& D; O+ }
  75.   TIM3->CCR2=b;//左上
    . U  m$ g& d; q6 l
  76.   TIM1->CCR1=a;//右下, @# s) J5 Z7 {' J$ N( k& ~. r, z
  77.   TIM1->CCR4=b;//左下5 Y: L5 S5 d, A7 }5 Z3 p
  78.   //delay_ms(2000);1 g  @, K7 |4 i& g9 v
  79. }* ?- e9 W, p8 G6 k5 V

  80. * d/ c, N' m, }3 g
  81. void STOP(void)
    $ h' ~/ e2 o$ }. I- _
  82. {
    3 l- G1 M; M3 L+ j' v  n
  83.   AIN1=0;( X% z. E& m6 j4 Z
  84.   AIN2=0;# j3 n7 r$ R+ z7 N
  85.   BIN1=0;) u7 H# N4 L& |1 q
  86.   BIN2=0;
    . U7 ~! u$ U. r5 A/ ?5 \3 U( [+ ^
  87.   AIN3=0;
    - y& f2 B9 x- H  L6 R
  88.   AIN4=0;/ O+ g+ E9 x% c, e
  89.   BIN3=0;) E+ h& k# o( t
  90.   BIN4=0;  
    & c5 V6 ^% @- H7 z" A3 F2 ?
  91. }
    2 y/ Q% o1 \* t; f/ X0 F$ u
  92. 2 l; q: u* w2 @6 }: v0 C
  93. void BACK(u16 a,u16 b)& B, K, q: l$ G- `- i
  94. {$ q$ m  J! T. I+ m" H
  95.   AIN1=1;
    - l% |' o. i- z
  96.   AIN2=0;: C- K" C1 G9 F2 Y  c" _" A
  97.   BIN1=1;
    / t. f! F9 N! Q+ M7 @1 e
  98.   BIN2=0;
    ' y# f: k  [) P7 }) g
  99.   AIN3=0;$ }" m) B7 m3 n3 l2 d/ ^8 @
  100.   AIN4=1;7 {) C* R0 x) P) @
  101.   BIN3=0;- u% @+ Z/ k: I+ w8 \+ G
  102.   BIN4=1;  , W: T( D) M8 b; h
  103.   1 x2 ^6 [9 h  V6 L
  104.   TIM3->CCR1=a;//右上
    $ c$ m# m* ~# K2 S) I
  105.   TIM3->CCR2=b;//左上
    8 I0 r, _+ S! Q2 z2 M9 h6 A' m
  106.   TIM1->CCR1=a;//右下
    . I( v, L6 u, @; K/ `2 L! Z
  107.   TIM1->CCR4=b;//左下1 ?" ?! h9 R& y# y5 k* M
  108. //  delay_ms(1000);1 j6 S' {& Z# N0 `: a9 S6 C
  109. }* d6 J* c- A+ b8 O! U3 D
  110. 8 i1 W* g. e3 Q% p; ^; x
  111. void RIGHT(u16 a,u16 b)
    7 C* X* C) K4 S" D, D3 |2 o
  112. {
      V8 N- |" Z5 s
  113.   AIN1=1;# ?$ ?# y; W1 O7 @3 u$ L
  114.   AIN2=0;; W- t/ U4 _) L. j  }7 w
  115.   BIN1=0;& ^- M$ L1 Q3 R
  116.   BIN2=1;
    3 l9 ?; w) M2 Q1 l+ o& |% l( h
  117.   AIN3=0;
    7 C1 S: I# p1 R4 ~2 ^. Y
  118.   AIN4=1;
    - V6 m1 b3 R, L7 x7 }4 a" X5 s
  119.   BIN3=1;+ G  a/ {. \6 ~7 Q% B, S
  120.   BIN4=0;  
      e$ G) h9 l( V
  121.   
    . V4 g0 i6 e) u* C& Z% ?
  122.   TIM3->CCR1=a;//右上! e; m' ]! K( V% M
  123.   TIM3->CCR2=b;//左上
    . L) U. U( ~- U0 M* C1 c- c
  124.   TIM1->CCR1=a;//右下
    7 p4 {" `4 n3 Q5 R
  125.   TIM1->CCR4=b;//左下$ q) E! |' M: B9 v" `# b
  126. //  delay_ms(1000);
    5 }6 [) r5 x) ]3 k6 ~, K
  127. }
    ( p: n5 ?7 C6 H

  128. % G: t- n& J$ X. K, Z" `! _
  129. void LEFT(u16 a,u16 b)
    & k  P6 m! b5 Y( |" E! H
  130. {
    " i8 j5 W: Z' F4 s' v! {9 t
  131.   AIN1=0;
    ) o: {5 G; q! O8 t( O$ a
  132.   AIN2=1;9 A3 K, ^) O$ |* r: z' N$ ?4 N
  133.   BIN1=1;  V7 y2 \% _7 S- W2 E& [  {$ G3 q
  134.   BIN2=0;; P) @: Z  ^& U+ i$ X2 m
  135.   AIN3=1;8 W% Q* ~$ [% ~! G* s, X( Q! X/ C7 N6 Z, n
  136.   AIN4=0;1 {1 G6 L' f2 Q4 w/ v9 R
  137.   BIN3=0;
    ' z* ^$ M; s' g* y. Q; {7 L
  138.   BIN4=1;  0 Y; @$ n1 L' k9 j! \( p, w
  139.   " |, z/ q. J/ [8 ?
  140.   TIM3->CCR1=a;//右上- T8 y: L( {1 G: \8 W, {8 C
  141.   TIM3->CCR2=b;//左上
    6 N, Z/ s9 ]+ K) o( C$ u
  142.   TIM1->CCR1=a;//右下& W% {/ N# z2 M: ]6 a
  143.   TIM1->CCR4=b;//左下) R) t/ o/ `2 ]1 d" B  N7 p; x
  144. //  delay_ms(1000);) [# S# u$ L( s! d8 s
  145. }
复制代码

4 y5 j; V7 y1 U6 o' j3.蓝牙控制
蓝牙控制这一内容是小伙伴写的,大概内容和串口一章内容相似,就是多做出了判断,即没通过蓝牙输入数据来改变小车此时的模式,在蓝牙控制模式下,也可以相对应用蓝牙控制小车的方向。我们用的仍是串口一来控制蓝牙,为什么这样做?一是方便,二是就如前面所说,电机和超声波的分压严重,在电脑上上的串口监视器得出的数据并不准确,所以还不如用蓝牙来看数据,于是我们直接用了串口一来和蓝牙连接。初始化问题并不需要要修改,直接调用uart()函数即可,在中断控制代码下加入接收数据而触发的各种就好了。
! [) D4 }' f8 o6 W: |; k
蓝牙控制部分代码:
  1. void USART1_IRQHandler(void)
    ) r" n" f0 ?! V* U) ?3 w' b
  2. {
    8 y) |0 k$ j- H
  3.   char res;  + Z9 c0 o0 j2 Y0 W
  4.   if(USART1->SR&(1<<5))
    7 [- k: W9 U2 J& [, U4 O
  5.   {    7 N6 p+ H& B& e5 F: A
  6.     res=USART1->DR;
    , u0 S% c% D, }! N+ U. `* e* h
  7.     printf("\r\n%d",res);   
    # p% X' h3 y% q5 a4 ~
  8.     if(res==50)                                              //输入2为前进7 D3 ^* J3 q8 i% ^/ d! P" c7 }1 {
  9.     {  : |; u/ v. R/ T+ r2 R$ N$ j+ J
  10.       GO(300,300);5 M& p1 \( E2 C+ H
  11.       printf("\r\nGo Stright");
    2 `5 B+ l5 r2 }
  12.     }
    " s% \: l4 f; J7 y! U* ]+ O
  13.     else if(res==56)                       //输入8为后退
    : G6 P0 L# N9 S$ \. H: f8 t
  14.     {
    $ ]7 r8 R: j: S+ F" B' V
  15.       BACK(300,300);
    % w6 V1 w+ ]4 J$ e; F3 P
  16.       printf("\r\nGo Back");9 h1 G/ @! s; d6 N/ h2 l
  17.     }
    4 C, v4 J3 U3 p. f
  18.     else if(res== 52)                //输入4为左转
    : S' G& j9 `8 g/ R) p6 Y* C
  19.     {
      _" Q8 ^( P6 H6 y/ W; F
  20.       LEFT(300,300);6 f8 v; q: d* a$ \$ I
  21.       printf("\r\nTurn Left");      7 v# q( D1 H: d
  22.     }
    ; U& ~, i% R8 R8 O  U0 b6 g
  23.     else if(res==54)                //输入6为右转
    1 p6 _- s/ V) j* W: T1 p
  24.     {1 c' \" }  H$ T: H, A
  25.       RIGHT(300,300);
    / _: C3 e9 G# k
  26.       printf("\r\nTurn Right");. o' s/ `% S' J% l3 [
  27.     }4 d; E- I5 R" Q
  28.     else if(res==53)                //输入5为停止: J* T' m- h& r; @3 y0 J; ~& f
  29.     {) S1 N+ p6 `* {( `
  30.       STOP();2 Y# s9 N7 @$ s: f( O* a
  31.       printf("\r\nStop");
    0 N( b7 \' `$ k9 m2 Y" F
  32.     }3 j6 P4 t& c3 A- i/ M; G: g' t
  33.     else if(res=='9')                //进入超声波避障模式
    ; k- B, n% a% W' E+ t
  34.     {
    3 G1 {" d0 Y1 e8 Z2 |
  35.       opq=0;
    ( |( u+ ?3 P& L+ Y. E
  36.     }: Q& W: O: E2 ^3 o! X2 c
  37.   }
    + `, l( f, g5 m) i' R
  38. }
复制代码

- B0 }+ G; W  O% C2 C! U! A5 Y5 ?) ]
总的来说蓝牙控制这块并没有踩多少坑(大概这不是我写的吧^ _ ^,感谢小伙伴)
( `* A3 @8 s% y8 Z8 N# J9 y
4.走矩形, z& b& ]$ q4 D  P2 |/ {' z3 ~

8 l/ N& z5 e/ _$ y  D& p8 v2 O  E+ U走矩形功能也是小伙伴写的,设计思路大致是通过蓝牙输入长和宽,小车通过接受的数据进行矩形运动。在这唯一遇到的问题就是小车的速度问题和转向时间。这个是他们弄得,自我感觉还是很不好调的,因为要考虑电池可供电压,小车行驶的惯性,不同地面的摩擦程度等等。考虑的方面比较多,根据不同的情况可能还要修改小车的速度和转向时间。我们就是在光滑地砖上测得,摩擦力应该是比较小的。
# o8 e! ~# j+ i
走矩形代码:
  1. void Juxing()//小车的矩形运动函数+ C1 J2 l  X$ `
  2. {- `4 {/ ?. Q; I/ n, R3 H0 P
  3.   u8 chang,kuan,x,y;//chang、kuan分别是小车要走矩形的长和宽的值( Z$ }+ D* S0 \/ w* E' n# x
  4.   delay_ms(200);4 A0 a3 N  ^; N
  5.   printf("Chang:\r\n");* w8 \3 b: r9 v. G/ Q
  6.   while(1)$ w) m5 N" E* _/ w; z! i
  7.   {
    8 r2 Z6 t$ e% b# |" ^% L0 b
  8.     printf("Input Chang:\r\n");
    4 S; N9 J0 V5 H/ G! t$ O# v
  9.     delay_ms(200);
    5 c3 f$ k8 P, d' @3 K! x
  10.     if(USART1->SR&(1<<5))//当串口接收到消息后跳出循环9 v  r2 h  G2 b" e- f4 K
  11.     {
    % W' B1 ?8 {6 U" R
  12.       chang=USART1->DR-'0';//将字符型的数据转换为整型数据0 r3 [" q( t+ [' W$ k# w3 l8 f  G
  13.       break;
    4 Y' q$ O  M7 ?3 d9 s3 X
  14.     }
    : ^, B& t- O" @: R  c
  15.   }! G8 k) }* o( r8 k7 _
  16.   printf("长:%d\r\n",chang);//打印串口接收到的数据
    7 v" ~$ F# Z4 C* V" @% p( E
  17.   USART1->SR=0;//串口的接收标志位清零,为下一次接收宽度数据做准备
    3 t+ d: g) f+ P0 d+ C
  18.   while(1)+ O8 J. C5 ?- ?% p  \5 n7 N8 K
  19.   {0 y1 H3 v. G7 D9 w' w+ F" Q
  20.     printf("Input Kuan:\r\n");
    3 v4 M. q5 N# O, Y& |( J
  21.     delay_ms(200);7 _" A6 P! [. V7 X$ e0 t
  22.     if(USART1->SR&(1<<5))' {) C% j0 M# @. i/ p
  23.     {
    6 |- w' j+ R. ?; Q
  24.       kuan=USART1->DR-'0';//当串口接收到数据后跳出循环
    & Y, m5 D7 z: z& }; D4 c. x
  25.       break;
    ; D# E- P* U* K; v( c
  26.     }. M2 \  \- M, ^1 b) x. [* _
  27.   }
    ; E) k7 e5 Q5 _# b& D- ^
  28.   printf("宽:%d\r\n",kuan);//打印宽度数据' D6 d% z- @9 [9 m5 O7 ~
  29.   //当前小车速度为0.25米每秒则小车每走1cm要用40ms所以以1cm为单位每走1cm耗时40ms用for函数驱动小车运动" `- v/ h1 x. |2 I2 v9 U4 ^
  30.   for(x=0;x<chang*10;x++)//直走长
    : P0 _9 u; C* i6 ^
  31.   {
    / o) p, z: V: j+ B$ C
  32.     GO(300,300);' g5 @1 [/ U% d# d
  33.     delay_ms(40);) v+ |/ E- l% Q6 E6 `9 m
  34.   }
    4 j) @5 j* u7 w, B: e
  35.   RIGHT(300,300);//右拐, K$ z/ ~9 P8 m, \
  36.   delay_ms(785);: ^4 j' M4 X5 m8 R
  37.   for(y=0;y<kuan*10;y++)//直走宽% ?8 Q; q; @+ C3 c7 q7 y! |+ p2 z
  38.   {
    # T: p" v) @% k
  39.     GO(300,300);( a  K7 T2 w. c) H. @" ?  q% O
  40.     delay_ms(40);4 y9 a2 K, a  L. M# ]( o# j
  41.   }; c6 F0 R1 J% T( k5 H  E
  42.   RIGHT(300,300);//右拐
    0 R5 }( n4 k$ x* e* [
  43.   delay_ms(785);
    : {+ V7 A0 r( g( ?
  44.   for(x=0;x<chang*10;x++)//直走长; J6 P' @3 ?/ M+ j) }0 ]2 z
  45.   {
    ' j2 Q; `% a0 w! M! u! Z
  46.     GO(300,300);" m" _: V+ T3 t7 z
  47.     delay_ms(40);
    . j" u1 k! b& q8 `' c/ [
  48.   }
    & y; e- u& I9 A6 \4 f8 E0 l, i
  49.   RIGHT(300,300);//右拐7 r9 W6 Q" B3 d" Q
  50.   delay_ms(785);- D9 u- n* L+ Z
  51.   for(y=0;y<kuan*10;y++)//直走宽
    ! K1 |" l+ E- p0 H% t/ D+ @0 Y& `
  52.   {
    7 f6 m  P# v+ n' r
  53.     GO(300,300);8 F" s) |+ N; T  u, `7 T/ T3 ^
  54.     delay_ms(40);
    , _8 x( G" {  i
  55.   }
    # a; F: f, K& e( X% X
  56.   RIGHT(300,300);//右拐
    2 `, c1 |$ Y$ C2 x' R2 a) u7 b
  57.   delay_ms(785);% V3 e7 O5 l: q
  58.   STOP();
    + }$ e7 }9 k( J$ F! f0 c
  59.   
复制代码
2 n' k0 p) \3 I  A4 m# S9 X

% q% n2 ]* \4 ~0 K8 ^8 A& g/ t转载自: 古月居
; G7 o! B1 |& n& X+ c* W
赞 收藏 评论0 发布时间:2022-9-3 15:17

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版