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

stm32智能小车设计

[复制链接]
STMCU小助手 发布时间:2022-9-3 15:17
历时两周,总算把小车弄好了,总体上来说做的太慢了。自己在32的学习中还不够仔细深入,只是浅面的学习,当真正做一个项目时,暴露的问题就太多了。这次在小车的制作的过程中,遇到了各种各样的问题,软件,硬件,各式各样的问题迎面而来,真的好几次心态崩了。不过还好小车这个项目不只是我一个人在搞,组里的其他成员也在一直在考虑问题,想办法,不断地解决解决,总归小车终于做好了,下面是小车完成图:
微信图片_20220903151642.jpg . l$ o) z' Z9 D, @9 I; G! g
微信图片_20220903151646.jpg
: }2 z8 B2 B2 C% @
: c# @8 `, q& @1 p6 h2 i
是有点灵魂接线(·<·)。
8 {( X2 i; ~/ `- w! C; E

( N6 [" u% y" a2 \7 u' n' l
/ t0 t, k5 \' H% K

模块清单


1 V7 Q5 }. W( k% h
  • stm32f103C8T6开发板% B) f+ g  A0 Q& Z  v
  • 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

    0 c* O5 T: s0 t3 ~: @
8 L. ^# \& G9 I8 }3 U; E+ e

. m, v* H  b! c
. M* B4 K2 `# q! S8 W8 B

完成功能

6 D% C: o* z  u7 T2 I
  • 超声波避障
    2 G" J* f4 W( e4 B* W+ D: Y# L
  • 蓝牙控制
  • 走矩形

    $ {! b/ |+ |/ K

9 ]; a1 Z) u% q# A2 Z. m7 G
& R. Z: }8 s" b- |$ w1 K
各个模块就不再介绍了,具体介绍大家可以自行百度或者看一下我的前几篇Arduino智能小车博客,里面有简单的介绍。

5 T& U5 M% u( z; l- A+ F& L! N. i- Z5 w& c( y% y# U* V
那么,开始吧。

- t; T- [; ]" a8 |9 D
$ S0 Z* J$ @6 D# U7 m* @" v3 ?/ R+ D

准备工作


, f  S% H! m- `; |
1.首先配置好keil5 c8t6模板(温馨提示:多看看模板的核心驱动,包括sys.h delay.h usart.h等,这些核心文件一定要保证准确无误!)9 c8 x4 e. _2 H" u0 s6 g) U
2.了解开发板和确保开发板无误
( o5 d- z0 C, w( T  P& U3.熟悉怎么用转串口模块和st-link将驱动下载到开发板上。

" Y6 ]) L% v5 O+ r下图示为c8t6开发板的引脚图

) k; d2 g, Z0 A; {0 k+ z; J 微信图片_20220903151652.jpg
  }8 Z! p, W! f; Z5 P
4 \( d7 x) ?& L% ?# i1.超声波避障功能( G% |$ B. }* H2 B
我们设计的思路如下,用三个超声波来避障。为什么用三个超声波呢?我们想的是如果用舵机的话,小车在行进过程中并不好判断,只能将车停下,舵机转动来检测哪个方向无障碍物,而用3个超声波不仅可以在行进中判断,也可以让小车没有停下的动作,显得整个过程比较流畅。这就是我们使用三个超声波的原因了。
# j' q7 I! j2 n% N) G* K
我们使用的是定时器二的通道一,通道二,通道三来进行输入捕获的,那么,第一个问题就来了。
0 |% t/ P( D  o0 k, H% Z) O
我们在写超声波代码时,用一个超声波先测试,发现超声波测试的并没有问题 ,串口显示的数据也并没有问题。但是,但是,在用三个超声波同时测试是,却发现数据显示的总有问题,输出的数据总是毫无规律,且数字都非常大,我们就在想是什么问题。

! t% t6 b) ^. r) V7 W3 d下面是三个超声波控制的代码:
# i* B) R- E- Y
  1. //main.c
    5 ]- @+ L$ M' a  {+ G7 i  B
  2. #include "sys.h"2 H: x0 N: i# |$ Z: M
  3. #include "usart.h"    8 n5 e2 V0 {0 {1 |9 u: ?
  4. #include "delay.h"  . j5 s; W5 r, {
  5. #include "led.h"  
    * q; }. L2 y. {% ~3 q8 \& D; Y
  6. #include "dianji.h"6 Q+ s5 a1 u! n
  7. #include "hcsr.h": _+ J) J( v/ {6 ]& r' a! G8 G
  8. u32 DIS_Init(u8 STA,u16 VAL)
    3 [% e; E) d+ Q1 r6 E  x
  9. {
    9 R( C9 N+ ]" Y1 R! y- O0 S
  10.     u32 temp;  r, k, V& K/ L
  11.     u32 lenth;
    1 S+ }7 M# W% {) X) V1 s' T
  12.     if((*STA)&0X80)//成功捕获到了一次高电平5 w0 @2 p4 b7 W
  13.     {6 h1 [- l5 @$ v: y# X9 y
  14.         temp=STA&0X3F;
    : Q8 s; j* m3 Q3 D" a2 e* b: `; e
  15.         temp*=65536;               //溢出时间总和
    - i* R8 g" L6 b" P
  16.         temp+=VAL; //得到总的高电平时间
    7 d  k9 H9 L9 k$ X4 e& ]$ N
  17.         lenth=temp*0.017;           //计算长度
    4 u3 x) l  R( c9 a+ J
  18.         STA=0;     //开启下一次捕获8 p- A! ]& a, u6 S/ i; @
  19.     }
    & j0 m' `+ P5 U3 n$ }
  20.     return lenth;
    & ~; ?, ?% D8 {* e) @$ ^- a
  21. }. y+ C8 L- T* }
  22. - N2 O6 W- s+ s- v4 q
  23. extern u8 TIM2CH2_CAPTURE_STA; //输入捕获状态
    ' L/ y/ m9 k' F5 B3 s, B4 X
  24. extern u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值, t9 \" P3 M) d4 |6 B- j
  25. / F* C3 A1 u' m2 T* v  F
  26. extern u8 TIM2CH3_CAPTURE_STA; //输入捕获状态+ j8 P8 o) V* M4 }" T& Z5 G
  27. extern u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    2 i$ N: P# C: w9 o+ b! a" M% r9 d) v

  28. $ [3 D  R% X7 M0 R
  29. extern u8 TIM2CH4_CAPTURE_STA; //输入捕获状态; Q. `  A) {* A  l4 y7 b
  30. extern u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值4 Y5 v: v- W, f- ~' W' y+ ~. H

  31. 5 t+ T( C# K* k5 H: Q9 o
  32. int main(void)
    & `# q- p( u6 ~* ^
  33. {   
    3 d- r" [! n$ l  K
  34.   u32 temp=0;- b$ }% D" ?) q8 S( R; r7 ?) U3 N
  35.   u32 length1;# Q. `! B  O0 \; h% v! \. f
  36.   u32 length2;
    . V- V' ^; T; Z0 G; i; r7 S$ i
  37.   u32 length3;   
    ; x5 c; Z) U% d# R! }5 V6 m7 r
  38.   Stm32_Clock_Init(9); //系统时钟设置$ G/ V( ?& ]  [% Q; {
  39.   delay_init(72);       //延时初始化# k' I1 e( C* ~) `
  40.   uart_init(72,9600);  //串口初始化        //初始化与LED连接的硬件接口9 j0 \+ ]" j8 ~7 R1 Y
  41.   TIM_PWM1_Init();//10000-1,36-1);//不分频。PWM频率=72M/(0.036M)=2Khz
    7 M; T. o$ Z5 W# `! H* C6 y+ ~
  42.   Echo1=0;, Z# x! A1 r! @5 ^
  43.   Echo2=0;
    & V" i  h4 V, ]+ P8 O: [' s
  44.   Echo3=0;
    7 u3 v/ U- M5 E1 M
  45.   HCSR04_Init(0XFFFF,72-1);//以1Mhz的频率计数. R+ |5 }3 l/ S
  46.   /*while(1)- p$ K1 i5 ~: f% }9 M' a, W7 l
  47.   {
    & V* l7 ~6 b- `% n3 [
  48.     9 v; q) f# _2 \2 W
  49.   }*/" c3 D7 F% s8 e% Q/ L2 |7 v
  50.   while(1)( l- `: D4 I- L# G
  51.   {
    ; N7 D- |3 G0 C' o
  52.     Echo3=1;
    4 ?3 o( c0 _% }! m: C2 s
  53.     delay_us(20);+ B! c0 w# `* O' v5 ^, m
  54.     Echo3=0;
    * V2 z9 ~! F& Z) _
  55.     length1=DIS_Init(&TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL);$ w( `  C7 l4 t  P( k( E
  56.     delay_ms(1000);  Z% e" ^8 W- a8 r
  57.     Echo1=1;* \! E( M; U' t0 I5 H+ L/ P& O  i; s: H; P
  58.     delay_us(20);
    4 D8 F. H! P9 D! t5 u* M
  59.     Echo1=0;
    ! e' ^+ i. Q, h
  60.     length2=DIS_Init(&TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL);6 Q2 w2 Q7 ?( m- v* E+ G
  61.     delay_ms(1000);* K0 \* }8 H. b5 n
  62.     Echo2=1;
    2 X5 }- b* L7 n! t8 F  k; L; M3 q
  63.     delay_us(20);
    9 R" r5 J, s! E* M
  64.     Echo2=0;
    - D, J, p% I$ X) H% w
  65.     length3=DIS_Init(&TIM2CH3_CAPTURE_STA,TIM2CH3_CAPTURE_VAL);
    * n* N3 L; y0 Y( |% {' X
  66.     printf("%d %d %d\r\n",length1,length2,length3);
    - }4 u- K, U7 C2 s
  67.   //  GO();4 T8 t0 [- J( M* X2 o' r
  68.     delay_ms(500);+ O7 G' S: Y+ S- B
  69.   }
    0 A3 ?/ K$ R( I& }  K1 K
  70. }/ P& x& k7 B7 _0 G- m- r( p
  71. 8 y" J' M/ f3 _0 F6 J: e
  72. hcsr.c) z8 t( R& D% }+ x8 n% F' E
  73. #include "sys.h"
    # p% x- ^$ m" G  s/ E7 J
  74. #include "delay.h"+ h& x" R  y- w1 Q; \) P
  75. #include "usart.h"* ]6 s% }, K4 n5 ]
  76. #include "hcsr.h". d# K. b$ J, g
  77. void HCSR04_Init(u16 arr,u16 psc)" N4 n1 L! c# I& w; {6 S2 C2 U
  78. {' M% V: K; T- Q
  79.     RCC->APB1ENR|=1<<0;    //TIM2时钟使能
    . L/ O' w" t2 F, H
  80.     RCC->APB2ENR|=1<<2;    //使能PORTA时钟1 W  c9 }2 R7 v% K
  81.     RCC->APB2ENR|=1<<3;     //使能PORTB时钟
    7 \7 J( B( `; t0 B% z, ^
  82.     GPIOA->CRL&=0XFFFF000F;//PA1 清除之前设置
    : ]9 Y0 |6 T  q$ b9 Y/ }
  83.     GPIOA->CRL|=0X00008880;//PA1输入. ~/ v. R- M  @) Z4 \
  84. //    GPIOA->ODR|=0<<0;
      w3 o$ \& K  T
  85.     GPIOA->ODR|=0<<1;      //PA1下拉) E. U* b, c' w- w5 S
  86.     GPIOA->ODR|=0<<2;
      Z7 Z- t, G) i+ }; K2 a% P4 o+ ^
  87.     GPIOA->ODR|=0<<3;  R/ U3 A% ~# M0 h/ a2 K
  88.   % `' h7 L" _- \' c4 N/ N
  89.     GPIOB->CRL&=0X000FFFFF;//PB7清除之前设置
    / o& ?  `* `2 K8 S$ c/ P
  90.     GPIOB->CRL|=0X33300000;//PB7推挽输出
    ; V+ G) e$ ^* s" z* r
  91.     GPIOB->ODR|=1<<7;      //PB7 输出高
    + g9 y- ]9 E: ~* |5 s$ j
  92.     GPIOB->ODR|=1<<6;& |* _( z4 w& i
  93.     GPIOB->ODR|=1<<5;% G" v1 X: A9 F$ d
  94.   
    " ?6 Z4 s' F' i1 i' ]2 s6 a
  95.     TIM2->ARR=arr;         //设定计数器自动重装值
    6 ]6 ~2 A/ a, }% y& e: S
  96.     TIM2->PSC=psc;         //预分频器' p/ ^3 `7 p! A
  97.   1 O9 }# w$ S& C+ Y2 b
  98.     TIM2->CCMR1|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
    8 P$ ?* l4 E: {" I2 \
  99.     TIM2->CCMR1|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
    / |8 ~& j1 o' [, |. j( T3 n' B
  100.     TIM2->CCMR1|=0<<10;    //IC2PS=00 配置输入分频,不分频
    $ l. t0 L- H; H8 M' A3 E
  101.   
    ' f8 G4 O' x4 M. ]+ X0 w
  102.     TIM2->CCER|=0<<5;      //CC2P=0 上升沿捕获2 p+ a& G% n4 K$ ], k* n
  103.     TIM2->CCER|=1<<4;      //CC2E=1 允许捕获计数器的值到捕获寄存器中$ |% D- u9 r+ s1 t
  104.     , w5 V$ H) u4 ~% {0 {' S1 h6 E
  105.     TIM2->CCMR2|=1<<0;     //CC2S=01 选择输入端IC1映射到TI1. f* E; y  i: {! E7 ]* @/ ?
  106.     TIM2->CCMR2|=1<<4;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
    6 I2 U4 b) E( I" R* J. S
  107.     TIM2->CCMR2|=0<<2;    //IC2PS=00 配置输入分频,不分频
    7 c$ A  _5 W  J" r0 }
  108.   ( C0 O. I; a, w. k2 y8 {& ]
  109.     TIM2->CCER|=0<<9;      //CC2P=0 上升沿捕获/ V! N, R" S. S/ v# v4 k2 j
  110.     TIM2->CCER|=1<<8;      //CC2E=1 允许捕获计数器的值到捕获寄存器中& t. l- A! {- H1 X0 E6 r! S; K
  111.     1 x+ n& e) S/ `
  112.     TIM2->CCMR2|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1' t8 N3 K& ], z- z* s' p) k
  113.     TIM2->CCMR2|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效) A0 k) k8 ^5 g! ?* M
  114.     TIM2->CCMR2|=0<<10;    //IC2PS=00 配置输入分频,不分频1 f$ N$ P/ f  X/ I- a2 s- y+ r3 T
  115.   
    ' J8 e# s  Q* }! k3 v2 e8 m& f7 \
  116.     TIM2->CCER|=0<<13;      //CC2P=0 上升沿捕获
    5 i/ w# l% `/ m, H, m. J
  117.     TIM2->CCER|=1<<12;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    0 ]5 y# J& _7 o* n
  118.    
    ( g5 s9 j' s! P% p7 Y
  119.     TIM2->DIER|=1<<2;      //允许捕获中断
    ' C' Y. g9 n: l: |: _8 [
  120.     TIM2->DIER|=1<<3;      //允许捕获中断
    $ J5 z! W. D' X7 c
  121.     TIM2->DIER|=1<<4;      //允许捕获中断
    + q, p: j! P3 I9 y) z; P
  122.     TIM2->DIER|=1<<0;      //允许更新中断; [' Z+ ^1 N. s) j2 g
  123.     //TIM2->CR1|=0X01;       //使能定时器2% L4 s3 I3 c5 W' b6 y- N
  124.     MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
    + Q! y; n! W$ r1 T4 z
  125. }7 {# |+ M9 h3 [5 `) g

  126. + i' H/ T. Q4 X4 l
  127. u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态9 b! u" [/ W+ N, A1 P
  128. u16 TIM2CH1_CAPTURE_VAL;  //输入捕获值
    6 t6 ?9 I: P3 A8 P  v

  129. ) t3 i3 P5 {0 S) l8 D' B4 q
  130. u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态1 d2 f% g* Y+ q+ b: N0 E6 t
  131. u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值
    0 \! ^/ s( Q, s( h! m9 }0 T6 d$ y
  132. 5 }5 Z/ a! p% r3 _  n1 J
  133. u8 TIM2CH3_CAPTURE_STA=0; //输入捕获状态
    6 S7 T, c* z: Y! c- g& u, J
  134. u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    ; d4 o4 J  S5 t3 I
  135. ) J, b1 O" H# y6 j8 E9 q
  136. u8 TIM2CH4_CAPTURE_STA=0; //输入捕获状态
    2 `1 j7 \1 {& R, C* o
  137. u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值) T& U+ T& M( {& Q' G8 S5 j

  138. # H  P% ]+ k3 l4 u
  139. //定时器2中断服务程序9 c2 I# d! a; N/ ~- I
  140. void TIM2_IRQHandler(void)# q( Q) n. {, t
  141. {
    , d; i, ?9 s6 i+ g" y/ I: z5 S
  142.     u16 tsr;" J4 p% e5 a; d- v% A8 @8 J$ c
  143.     tsr=TIM2->SR;1 M/ s2 o6 j) F
  144.   8 z0 p0 I0 J: `) p3 d/ |# v
  145.     if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
    . i- a' z1 S. o$ u
  146.     {# d$ l2 f$ R( y& [( ]( Q. R2 x& R
  147.         if(tsr&0X01)//溢出8 U1 F- m( [; w
  148.         {- w: \( Z  B# c! k2 M# Z. [
  149.             if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
    7 f- U' J! }6 \& w
  150.             {; Y4 J5 k. j0 n/ A! _( S
  151.                 if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    ; T3 {: P: Q, J+ ^
  152.                 {
    ( z, C! p, L+ P1 F4 T& k4 z6 |+ n
  153.                     TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次0 B9 b7 |$ C  T  Q  A8 N: ^
  154.                     TIM2CH4_CAPTURE_VAL=0XFFFF;
      Z) n& L7 E5 F) R( U
  155.                 }else TIM2CH4_CAPTURE_STA++;6 ^% i5 X; \! U5 h( _7 L
  156.             }
    8 u0 G- R5 X( _
  157.         }
    ) O& C. [' V) Q; c* ?
  158.         if(tsr&0x10)//捕获1发生捕获事件
    6 u% [% b) _/ d, D9 c+ |
  159.         {; W1 y: ?4 b2 |. D8 I5 C
  160.             if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
    0 p- `& g( G9 ^+ F' B
  161.             {5 o0 y* |. u9 k7 O
  162.                 TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽0 j* H: H: d: M$ S
  163.                 TIM2CH4_CAPTURE_VAL=TIM2->CCR4;//获取当前的捕获值
    ( R% c$ v  E' W! [
  164.                 TIM2->CCER&=~(1<<13);    //CC1P=0 设置为上升沿捕获- I8 h7 c$ q; e, p8 J4 R5 {
  165.             }else                       //还未开始,第一次捕获上升沿
      w) B1 n& C9 Q
  166.             {
    - U  o  k5 _  t) a& K/ F
  167.                 TIM2CH4_CAPTURE_VAL=0;! x1 r$ ~. e, B
  168.                 TIM2CH4_CAPTURE_STA=0X40; //标记捕获到了上升沿
    7 h9 @3 h1 l8 F' M8 d1 _- g
  169.                 TIM2->CNT=0;             //计数器清空' L7 B+ [$ e( p& T: Z7 ~5 W0 T5 m
  170.           //    TIM2CH4_CAPTURE_VAL=TIM2->CCR4;, Z# b0 T/ j6 J$ R8 w6 p  {
  171.                 TIM2->CCER|=1<<13;        //CC1P=1 设置为下降沿捕获
    * `) c$ a: i( ^* o
  172.               TIM2->CR1|=0x01;7 B: Y/ V  b& A) @( B" o
  173.             }4 b- H9 a' s( S' i( P
  174.         }
    + I' o+ Q7 a# O1 _) a! N6 Z
  175.     }
    * u0 E4 ]- B3 j" E% [
  176.     if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获9 S2 J) D8 r% D
  177.     {( G5 K* }; T3 r% g8 w' W
  178.         if(tsr&0X01)//溢出7 T8 x% f. H2 v  T0 t
  179.         {  ^" w2 z1 ^1 o2 L# ?' I
  180.             if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了& K' Y. f  K/ b+ p) P' L  n
  181.             {
    / G. A. {5 Q! h) \; _7 ~3 [
  182.                 if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了0 T$ ?+ n( ^% n& I# O
  183.                 {
    6 _# l+ R* m2 F
  184.                     TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
    6 d* @/ W# p( s3 c
  185.                     TIM2CH2_CAPTURE_VAL=0XFFFF;( C" d7 o3 i! l! G9 h
  186.                 }else TIM2CH2_CAPTURE_STA++;1 d4 X' M5 y" T' F, j; ~
  187.             }
    , |* y3 s5 P% p8 t5 ^
  188.         }% i% w3 C2 _6 y6 h( q- g
  189.         if(tsr&0x04)//捕获1发生捕获事件
    ; p# U+ |# g1 S4 N. ^
  190.         {
    % V9 [* f; y. s% l
  191.             if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿/ l2 j3 n8 e  ^$ Q. m1 f4 l
  192.             {. i; Q. y1 q2 E1 x! c
  193.                 TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
    . s+ T+ ^* |" J2 M: F
  194.                 TIM2CH2_CAPTURE_VAL=TIM2->CCR2;//获取当前的捕获值5 x0 w, j& _- Y9 V3 h
  195.                 TIM2->CCER&=~(1<<5);    //CC1P=0 设置为上升沿捕获
    1 b+ N, L  y5 v5 _
  196.             }else                       //还未开始,第一次捕获上升沿7 T. l* {. _) ^! G& O) u
  197.             {4 U- d' m. G' G+ l: F" B, u
  198.                 TIM2CH2_CAPTURE_VAL=0;7 S; z* P- U! p: p: `8 w9 f
  199.                 TIM2CH2_CAPTURE_STA=0X40; //标记捕获到了上升沿
    # B; {0 o5 Y- E
  200.                 TIM2->CNT=0;             //计数器清空5 x% }8 B( I* }) W" C& T. H
  201.                 TIM2->CCER|=1<<5;        //CC1P=1 设置为下降沿捕获; J5 g) w2 v, E% C
  202.               TIM2->CR1|=0x01;
    ' F+ a2 Y- i8 j. @
  203.             }( j7 s2 r- ?6 x
  204.         }
    ' A0 S9 r' |. t
  205.     }2 M, H$ A1 |8 L, a6 K" @$ W! N
  206.     # V5 x+ q+ k2 e7 y/ s; _- J. _
  207.     if((TIM2CH3_CAPTURE_STA&0X80)==0)//还未成功捕获: g$ e0 G: i. ]4 }
  208.     {
    : f" X  f: W, a
  209.         if(tsr&0X01)//溢出
    7 W1 r, E8 x" [& T
  210.         {
    " Y! b3 Z" O1 x, m
  211.             if(TIM2CH3_CAPTURE_STA&0X40)//已经捕获到高电平了- Q) l2 F% k, I
  212.             {! S* _# b6 G. S- l
  213.                 if((TIM2CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了  `: d$ W# u5 |3 g* I
  214.                 {& h3 E; m4 ~( ~  j; N! t  u
  215.                     TIM2CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
    1 _& R' R# ^( \1 ]1 n
  216.                     TIM2CH3_CAPTURE_VAL=0XFFFF;
    2 z0 d1 h6 U# H  V
  217.                 }else TIM2CH3_CAPTURE_STA++;
    # x! h, ~% M% v
  218.             }7 A& v( n# M; T- u
  219.         }
    + X. @; d! p* p& i
  220.         if(tsr&0x08)//捕获1发生捕获事件
    ( r! U4 D. g& w" j% F
  221.         {& K1 M& g8 D2 {7 J
  222.             if(TIM2CH3_CAPTURE_STA&0X40) //捕获到一个下降沿' s- Z; w% z7 ?8 k
  223.             {
    $ C3 [7 z5 G7 ]9 W( S$ @
  224.                 TIM2CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
    ( t2 m9 F% s0 o! t7 G% M
  225.                 TIM2CH3_CAPTURE_VAL=TIM2->CCR3;//获取当前的捕获值5 i" j) ^2 F! D/ I) W: b! j
  226.                 TIM2->CCER&=~(1<<9);    //CC1P=0 设置为上升沿捕获
    : J4 n$ ]: V' ~' x+ V
  227.             }else                       //还未开始,第一次捕获上升沿
    1 {* j/ Q7 a1 I- m% P% F7 `
  228.             {6 I0 A$ u$ u- f' B
  229.                 TIM2CH3_CAPTURE_VAL=0;! Z; Z& R0 _2 d$ ~# C
  230.                 TIM2CH3_CAPTURE_STA=0X40; //标记捕获到了上升沿( v" Z4 ]9 y: _
  231.                 TIM2->CNT=0;  % X/ {, ~# p# l, I6 _9 x
  232.             //    TIM2CH3_CAPTURE_VAL=TIM2->CCR3;              //计数器清空# _/ _- v3 W6 \1 @% \
  233.                 TIM2->CCER|=1<<9;        //CC1P=1 设置为下降沿捕获
    " j+ U5 ?" F0 e" `' ^% y
  234.               TIM2->CR1|=0x01;
    + Z! V; z; w- _$ A1 {9 N6 c; X
  235.             }
    9 @3 r! y* y% U5 u9 [& A
  236.         }
    % i0 C0 C7 d5 j- ^
  237.   }3 T9 u3 G& }. }0 V& ~, b: p
  238.     3 w$ N9 m, g2 T% e
  239.         + v) |* Q  `3 N, ~+ ]
  240.     TIM2->SR=0;//清除中断标志位7 l* e, J$ _3 m# G: G- J
  241.     1 K6 \9 \& k! P9 l
  242. }
    ' h- k3 v0 f: H5 w( f2 i! ^$ g, N
  243. $ }- C: O1 z6 A6 s# I- b3 w
  244. hcsr.h* i! n9 d: @8 x
  245. #ifndef __HSCR04_H
    0 L, i. u0 p6 e1 e5 P1 f
  246. #define __HSCR04_H6 e3 E& N% ]( n  q2 F4 i
  247. #include "sys.h"
    % [) J1 E5 `: i0 B( x8 h
  248. 3 ?; k3 t% V8 c. O# b
  249. #define Echo1 PBout(7) // PB77 N% z7 t( y0 v2 r" i0 X* E
  250. #define Echo2 PBout(6) // PB7: q8 K! |& i- U/ ^8 x
  251. #define Echo3 PBout(5) // PB7! z2 i4 V9 i: k1 v/ Q2 Q
  252. ) ^% N$ ^4 s8 \0 ]& @# `) Q0 B
  253. void HCSR04_Init(u16 arr,u16 psc);  `; ^6 M/ _+ |7 K
  254. . \1 `5 X0 Z' T' p0 @! U/ E( `" i7 e
  255. #endif
复制代码

. ~5 `( _  I& ^6 D
最后发现,输入捕获代码中,中断服务函数中,TIM2->CNT不能清零,因为初始化中,用的是同一个定时器的通道2,3,4。如果每一次中断函数的某个通道函数将TIM2->CNT清0,那么其他通道的记录的TIM2->CNT的值就发生变化,从而导致了各种各样的情况。
% h+ l- P8 g! ]
问题二就是从串口读取数据,当时挺崩溃的。首先是keil5模板问题,当时串口怎么都显示不出来数据,我们当时都很疑惑。一直反复的看代码,考虑各种情况,但还是显示不出来数据。一开始我们以为是超声波接受的反馈的数据不满足某个条件,所以没有显示。到后面查来查去,又在想是开发板并没有给电压?超声波集体歇B?最终发现,usart.c文件写的串口不是我们接线串口所对应的。当时心态挺炸的,改了之后终于可以测试数据了。

* g0 D# M( p8 b7 x2 |0 a$ s" b4 O3 i
问题三是我们在没接电机驱动之前,超声波接收的数据无论准不准确,最起码能接收到,可是接了电机驱动却发现每次返回的值都是0。我们当时并没有找到原因,又在猜想是不是电机用到的定时器对超声波的定时器有影响?又在想是不是外部电子设备把信号影响了?又在想各种各样的问题?

5 I8 N% b/ U: R. V0 N
最终解决的方法是,串口模块给的电压不够。(我也不知道这样形容的对不对,但感觉就是),为什么这样说呢?

0 |' w. ~, o- s' T/ h
当时一开始我想的是,超声波的模块在用转串口模块给其供电时,是不是超声波模块的VCC和GND引脚并没有电压,从而导致信号发射不出去。于是我用万用表测试两侧电压,发现是5V没错。又在想是不是发出信号并没有发去,于是我让TRIG引脚一直为1,测试TRIG电压发现为2.6v左右。在此之后,我又用12v的电池降压给开发板供电,发现TRIG电压为3.3V左右。我想验证,是不是电压问题而导致的接收数据为零。所以我想用电池给开发板供电,然后打开串口监视器看数据。但是要想启用串口监视器,必须要用串口给开发板供电。最后我们选用了蓝牙模块,从手机的接收器来观察数据。终于,果然是电压的问题,数据成功出现了!!!(哭了)
& [6 {; N# [5 B3 M: `
2.用PWM调控电机速度
这一过程能稍微简单一些,就是一开始还是电压的问题,四个轮子根本带不起来。反复查看代码后并没有太多问题,可是轮子还是不转,但是发现电机嗡嗡响,去掉一个电机后,将速度调大,发现两个轮子缓缓的动了。验证时,我们将轮子速度调小,发现轮子不转,证明了代码并无问题。

  K% y* l  ]" n3 X- x  _
pwm控制部分代码:
  1. #include "dianji.h"3 X9 t, F) i( I
  2. #include "sys.h"
    + a3 x5 |7 {- k
  3. #include "delay.h"- T9 R$ J  ]* `5 @7 _2 q: a8 Z$ N

  4. * D% r4 T- t- s
  5. void TIM_PWM1_Init(u16 arr,u16 psc)
    5 \. ]/ K2 A8 g) x4 o# C2 }
  6. {               
    ; _7 Z5 n1 b; c+ s9 H- L
  7.   //此部分需手动修改IO口设置' |, M/ i2 [$ L/ N+ z$ h
  8.   RCC->APB1ENR|=1<<1;   //TIM3时钟使能   
    6 A) c9 p% F* D+ o" ]8 p2 }- |4 `( ]
  9.   RCC->APB2ENR|=1<<2;    //GPIOA使能
    $ P3 J. |; f# `0 G0 G
  10.   RCC->APB2ENR|=1<<3;   //GPIOB使能( L' d8 o0 z- C% _  B
  11.   RCC->APB2ENR|=1<<4;$ j- a9 O9 n+ w
  12.   GPIOA->CRL&=0X00FFFFFF;  //PA(7)PA(6)做复用,PA(3)是BIN1 PA(4)BIN2 PA(5)STBY
    * o. {7 P% C/ L% ]- w$ z( \0 t
  13.   GPIOA->CRL|=0XBB000000;
    $ i- p2 K6 }9 V, ?" ~
  14.   //GPIOA->ODR|=1<<7;6 ~" @" s' O' O8 Q/ M
  15.   //GPIOA->ODR|=1<<6;
    6 }" |* S0 i0 Q6 C3 d+ n! @/ l7 ?( u" g
  16.   GPIOC->CRH&=0X000FFFFF;% H+ }2 U* A% L% k; x
  17.   GPIOC->CRH|=0X33300000;# |3 p9 Y# z; F  j; i
  18.   GPIOB->CRL&=0XFFFFF000; //PB(0)是AIN1 PB(1)是AIN2
    3 p9 h8 o8 j7 ~
  19.   GPIOB->CRL|=0X00000333;
    ' x4 E) B. `, u* o& |; F1 \
  20.   TIM3->ARR=arr;      //设定计数器3自动重装值
    ( i: Q8 Y3 B% B) i5 w
  21.   TIM3->PSC=psc;      //预分频器设置5 i8 d9 s3 l. Q$ f( Q; Q
  22.   
    % v6 f! c; t, l' T+ [
  23.   TIM3->CCMR1|=6<<4;    //CH1 PWM2模式     
    5 |1 T4 _$ I' W
  24.   TIM3->CCMR1|=1<<3;     //CH1预装载使能   2 ?: q, l) r( a5 m# }1 @
  25.   TIM3->CCMR1|=6<<12;    //CH2 PWM2模式     : _, d2 m; Q3 \! g2 V% N  D4 C2 f( |( ^
  26.   TIM3->CCMR1|=1<<11;     //CH2预装载使能  
    ( W4 D9 d- X8 B. ^8 j: \) N
  27.   
    ; ~& _& V* `' `( D9 @! [% E7 L1 U
  28.    TIM3->CCER|=1<<0;     //OC1 输出使能
    $ ^4 H% \9 L" }% b6 r: q+ c9 d& P
  29.   TIM3->CCER|=1<<4;     //OC1 输出使能  6 g8 I" O# c& g' v# |% }1 L+ K
  30. //  TIM3->BDTR|=1<<15;     //MOE 主输出使能     , d/ F) `7 i* L+ s! x1 E$ A
  31. ! p5 i& {1 O2 s9 r, A1 g
  32.   TIM3->CR1=0x0080;     //ARPE使能
    7 T* N  P( X+ |5 ^
  33.   TIM3->CR1|=0x01;      //使能定时器3 4 t( T/ `0 K8 J# x$ P% o
  34. # ^+ N2 T2 e5 h, ^% i3 u1 c
  35.   RCC->APB2ENR|=1<<11; //TIM1定时器使能0 o, v/ G+ O1 h+ b2 k. }+ [( Y
  36.   GPIOA->CRH&=0XFFFF0FF0;2 V& Y# C8 D) i  w. P/ c! L
  37.   GPIOA->CRH|=0X0000B00B;
      l1 y4 s+ _8 l) k- F# R4 p+ Z
  38.   //GPIOA->ODR|=1<<8;9 K1 M- {4 {/ `
  39.   //GPIOA->ODR|=1<<11;
    , x. j& z8 o8 A5 e5 a
  40.   
    ( L2 Y' K7 w) \9 L7 R: y
  41.   GPIOB->CRH&=0X0000FFFF;
    8 B( p. v  M; l1 w5 X7 l
  42.   GPIOB->CRH|=0X33330000;
    # P9 _& M" t8 ?" P+ A
  43.   
    $ ?9 v/ ]3 `# ~. Q
  44.   TIM1->ARR=arr;      //设定计数器自动重装值
    - D( o; z! I7 h/ g
  45.   TIM1->PSC=psc;      //预分频器设置
    5 [7 J( B$ W* T3 i9 e
  46.   
    ) r: L7 }+ }0 n+ ~8 ?% c0 w7 i: Y- S
  47.   TIM1->CCMR1|=6<<4;    //CH1 PWM2模式     
    9 I( z$ k& Y8 ?. \7 B
  48.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    8 G( j% C8 L' x! u- x: X+ j5 N
  49.   TIM1->CCMR2|=6<<12;    //CH4 PWM2模式     
    6 h/ {, m& r! {$ T1 M- ~* D1 ~
  50.   TIM1->CCMR2|=1<<11;     //CH4预装载使能  
    9 K# |, S% i# }
  51.   0 C6 C/ z  Q/ _+ @5 B* P+ ]
  52.   TIM1->CCER|=1<<0;     //OC1 输出使能$ J* P. h: p) {: W0 y, I, B+ v
  53.   TIM1->CCER|=1<<12;     //OC4 输出使能  
    7 N) Q, j2 j$ L2 t4 g
  54.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     ) j$ d* E- J( X3 q! S
  55. % N5 x. X8 T: ^0 Z  s& l
  56.   TIM1->CR1=0x0080;     //ARPE使能 9 {# v" y8 R3 U7 c2 N2 [
  57.   TIM1->CR1|=0x01;      //使能定时器1 3 e1 {+ g3 Q! W7 v: u
  58.   
    , J# q$ J+ ^! @/ ?( P$ f* e6 ?& H
  59.   STBY=1;1 s$ \- y. I# a/ o. G% _
  60.   STBY1=1;! r; P; u1 I9 |
  61. }
    / ^5 \$ e, }7 t7 E% G8 y- g& |
  62. $ r; t4 V/ y% X( b2 M* a, I4 B
  63. void GO(u16 a,u16 b)* F5 l& c' O3 s6 b% ^
  64. {
    . K) m# C7 k6 v& k4 j& t8 _7 O: p
  65.   AIN1=0;     //AIN1,BIN1,AIN2,BIN2控制轮子方向
    1 T8 u. S3 }% ~) d7 x
  66.   AIN2=1;
    $ }( X( Q0 V9 T
  67.   BIN1=0;4 h% D9 S' e% a% V- I5 e6 ~
  68.   BIN2=1;
    - y& X; ?3 Y6 D: R+ H2 u
  69.   AIN3=1;$ W- Y4 Z1 K  a5 k
  70.   AIN4=0;
    ! @' z- f# P* J0 U
  71.   BIN3=1;
    : ]) R: v* U3 {/ v
  72.   BIN4=0;  9 O+ G# @2 k5 V
  73.   9 ~1 f! ~" a2 O3 m9 r1 Y: p- c6 f
  74.   TIM3->CCR1=a;//右上,控制速度
    ( J9 P5 R' l1 q' s2 f
  75.   TIM3->CCR2=b;//左上! p& I& {+ [* D1 t" d# x
  76.   TIM1->CCR1=a;//右下
    9 l! }6 h* Q' F, R3 q
  77.   TIM1->CCR4=b;//左下2 ^1 a* n8 Y+ a/ c- l
  78.   //delay_ms(2000);
    , ^2 t- ^/ T8 r! h2 J  C! V5 F
  79. }
    ! g. h8 Y$ x. w) Y0 a# }/ E
  80. $ y% a9 F  H4 s1 [. F
  81. void STOP(void)
    - o+ a- D# t0 Q. Y. y  h8 Q1 Z2 y
  82. {
    % ^; f; G5 |, H3 c
  83.   AIN1=0;
      p$ r. r; m4 ?* r! E
  84.   AIN2=0;/ X+ |0 V& F, n
  85.   BIN1=0;, P2 A/ P* b; q$ _
  86.   BIN2=0;
    6 h# B1 D+ u* W1 {
  87.   AIN3=0;; ?  v/ @  H* E& @4 e$ _
  88.   AIN4=0;! ]4 o& L! p' `6 I' L
  89.   BIN3=0;
    ' ?0 W8 r. a' ^1 E
  90.   BIN4=0;  
    0 Q/ t, X$ m/ L% B* q, J; u0 ]
  91. }
    : A+ f" o/ l2 @/ Z+ h! G

  92. / D- N, Y2 D+ o* @/ b
  93. void BACK(u16 a,u16 b)9 R: S& c/ J  r7 ]
  94. {) |9 N( M# ?7 a, C" G1 P/ Y+ l7 B: Y; z
  95.   AIN1=1;1 ^4 R0 H9 e/ G" x
  96.   AIN2=0;6 |7 F) k2 }8 c1 {% e
  97.   BIN1=1;' G# f, {- _+ ^' V& a" Y
  98.   BIN2=0;
    1 D7 p; c$ n7 G8 I5 Y
  99.   AIN3=0;4 p; B( g. g9 z) g
  100.   AIN4=1;
    : \! x& I$ C% |/ J8 {
  101.   BIN3=0;/ n' w" g/ j" V) D/ x( W& W( h% p
  102.   BIN4=1;  ' m8 O6 W/ e" q$ Q' y. L9 \
  103.   + l7 s( h( F4 r3 Q
  104.   TIM3->CCR1=a;//右上
    1 g4 T) {2 U: d% b
  105.   TIM3->CCR2=b;//左上
    : r6 b9 d: H, b/ m1 H4 z, |$ g, Y
  106.   TIM1->CCR1=a;//右下
    + j& z) ?7 {9 u! n4 v
  107.   TIM1->CCR4=b;//左下, T2 ~* y! P9 x- C, Y- K; m. S
  108. //  delay_ms(1000);6 Z& |) `( U; }, S
  109. }
    6 r/ T2 B) Q4 h9 j! b

  110. 8 P1 l' a; ~3 X) G+ P0 G
  111. void RIGHT(u16 a,u16 b)
    * I5 y/ t% |  V' S8 d2 b
  112. {
    8 K% u3 |2 R7 [( B. B
  113.   AIN1=1;
    ) I5 Y7 p2 ?% r8 H
  114.   AIN2=0;
    & }6 W! {9 d' [. ~6 z' G7 E& P. i2 L
  115.   BIN1=0;
    & C9 p% y5 e* T# h0 N) ^
  116.   BIN2=1;" V5 l6 c5 c4 M9 ~# c5 E
  117.   AIN3=0;
    6 _. \9 B4 k$ {. x" z, C
  118.   AIN4=1;: ]6 S! G& M- Y1 D/ R; s3 x8 ^
  119.   BIN3=1;/ ^0 p4 ^$ G3 N. L/ B+ a0 O
  120.   BIN4=0;  
    6 l9 @5 }4 x8 o: n9 B  b
  121.   : S0 [/ F7 t( e+ |* }
  122.   TIM3->CCR1=a;//右上- i! g) X# [, S& a2 `2 ~2 }
  123.   TIM3->CCR2=b;//左上9 k% I( M) O+ d/ h; e9 X
  124.   TIM1->CCR1=a;//右下
    / |$ Y+ R( u& L0 Z) \" y
  125.   TIM1->CCR4=b;//左下+ T5 d6 {9 M4 W  u) Y
  126. //  delay_ms(1000);
    6 N7 d/ O9 f" s( J$ D
  127. }; p; u- {, |! T; j5 E+ F) I
  128. ! l5 r3 m1 ^) Z! _
  129. void LEFT(u16 a,u16 b)/ V; \% M7 R" r$ Q$ s* G) v/ [! e" m
  130. {# ^- U4 z) ~6 t' L) {" Y/ y0 r
  131.   AIN1=0;
    $ _' `6 x+ H, i( f5 c' x% T
  132.   AIN2=1;) c- j4 ]) _. D+ Q# p% i3 s0 a8 j
  133.   BIN1=1;! ]9 q% Y3 w2 l6 K0 x* ?. t
  134.   BIN2=0;8 x' D: Y1 x. ]* F! J! E' A6 k1 O
  135.   AIN3=1;
    5 [+ v/ u( o, E
  136.   AIN4=0;+ _! D! z) t* z6 d, n  e
  137.   BIN3=0;
      C$ h; g+ I! k
  138.   BIN4=1;  3 Q9 X+ u3 z% S5 t8 _" `
  139.   0 Z: h+ Q6 Z+ u
  140.   TIM3->CCR1=a;//右上
    . E9 [6 \# ~( G
  141.   TIM3->CCR2=b;//左上
    7 ~$ n) r! G! f1 e9 |# k
  142.   TIM1->CCR1=a;//右下" Y4 ?9 Y: {0 p3 ~3 `+ G
  143.   TIM1->CCR4=b;//左下
    3 Y4 q4 n# O8 P
  144. //  delay_ms(1000);
    / p; D$ Q. C; T, g
  145. }
复制代码

: {9 F) q5 }8 G% m. Z3.蓝牙控制
蓝牙控制这一内容是小伙伴写的,大概内容和串口一章内容相似,就是多做出了判断,即没通过蓝牙输入数据来改变小车此时的模式,在蓝牙控制模式下,也可以相对应用蓝牙控制小车的方向。我们用的仍是串口一来控制蓝牙,为什么这样做?一是方便,二是就如前面所说,电机和超声波的分压严重,在电脑上上的串口监视器得出的数据并不准确,所以还不如用蓝牙来看数据,于是我们直接用了串口一来和蓝牙连接。初始化问题并不需要要修改,直接调用uart()函数即可,在中断控制代码下加入接收数据而触发的各种就好了。
9 E; m1 {1 b! I) x0 w
蓝牙控制部分代码:
  1. void USART1_IRQHandler(void)
    # V; P7 ^: |3 y& I2 [9 C) f
  2. {
    4 D3 z6 ~5 q9 c. _
  3.   char res;  9 O$ A5 e. M2 l( t9 z
  4.   if(USART1->SR&(1<<5))
    ! W8 l, M& g# C4 X2 D
  5.   {   
    : N9 i: x5 M6 M8 L" _' B/ Z
  6.     res=USART1->DR;( j& L. q) \: s' [% Z. [5 N: F
  7.     printf("\r\n%d",res);   
    ; y2 B" L! Y% P& q, q
  8.     if(res==50)                                              //输入2为前进) N1 J! ^3 i/ l& B
  9.     {  8 g* K  w3 p. J- _" ~+ w6 R) ?
  10.       GO(300,300);% Y% D# I! n* W$ F9 H1 c; q
  11.       printf("\r\nGo Stright");
    3 ?" }1 _& G0 j; E' w
  12.     }: E6 Y4 |, ~9 V
  13.     else if(res==56)                       //输入8为后退" @) p& _" u1 Z7 n8 x( E+ ?
  14.     {. T- l) I) o, N7 c9 Z
  15.       BACK(300,300);6 R1 I( Y4 p: \, X/ R2 q
  16.       printf("\r\nGo Back");1 o, u  N2 Y) y) R: Y
  17.     }9 r  f  w$ \2 q# b( h
  18.     else if(res== 52)                //输入4为左转4 `) H  l. z  m
  19.     {
    $ z5 C9 q0 M8 |- z7 u% c) q% @
  20.       LEFT(300,300);
    , L# ]/ }$ U# T1 F) \5 c+ Q
  21.       printf("\r\nTurn Left");      3 d  }" X1 F2 s! A$ k0 h& a& {
  22.     }7 x) M- \' `4 r# [
  23.     else if(res==54)                //输入6为右转5 d1 ~5 |2 l& a0 S2 i& c7 K. r
  24.     {1 n& _" B$ D# B( m7 I
  25.       RIGHT(300,300);
    # I* v1 Z, [% N, ]" d6 w0 t- b  x
  26.       printf("\r\nTurn Right");
    7 ]- f1 z3 c6 ^$ s9 s& F
  27.     }
    + A+ S, |) O. b
  28.     else if(res==53)                //输入5为停止& T: M# [! S  V+ o( {4 \' H* J
  29.     {
    1 c0 g* Q* N( g' n
  30.       STOP();
    7 E! [) g9 g, Y0 L
  31.       printf("\r\nStop");' [7 N$ S  u* H0 L$ _+ x+ z
  32.     }
    ) T8 l6 y3 z* d% }
  33.     else if(res=='9')                //进入超声波避障模式3 V( a9 u. Z7 @, L  a
  34.     {
    9 U2 U/ N; V6 \0 [
  35.       opq=0;; y6 p4 }) X: N0 I9 {, S
  36.     }3 g2 S9 P  d6 y# I! }1 M4 `2 u0 t
  37.   }' D& p( J6 l9 p0 i
  38. }
复制代码

# B+ {$ A- }/ f. R
总的来说蓝牙控制这块并没有踩多少坑(大概这不是我写的吧^ _ ^,感谢小伙伴)

! q/ v( L! u! c: c4.走矩形
2 x7 S! B: Q& G# K% P0 N( \
$ i3 G5 Z: W' ~- l走矩形功能也是小伙伴写的,设计思路大致是通过蓝牙输入长和宽,小车通过接受的数据进行矩形运动。在这唯一遇到的问题就是小车的速度问题和转向时间。这个是他们弄得,自我感觉还是很不好调的,因为要考虑电池可供电压,小车行驶的惯性,不同地面的摩擦程度等等。考虑的方面比较多,根据不同的情况可能还要修改小车的速度和转向时间。我们就是在光滑地砖上测得,摩擦力应该是比较小的。/ J) ~" w: x( j. G/ ?6 R8 q
走矩形代码:
  1. void Juxing()//小车的矩形运动函数
    8 a# `. w/ K) l# T) w* K3 h
  2. {
    1 p( f' w7 B0 I9 I. h* F
  3.   u8 chang,kuan,x,y;//chang、kuan分别是小车要走矩形的长和宽的值3 c) E/ U9 ]0 n& y6 t9 H
  4.   delay_ms(200);1 m5 ~* a3 R+ A; c% e
  5.   printf("Chang:\r\n");+ C, ]; D. p+ w( [# l  ~9 s
  6.   while(1)+ }9 ~7 X. D+ a0 K& @
  7.   {
    ' H; M' {& B6 z* h* m
  8.     printf("Input Chang:\r\n");; S* Q1 @, t/ V0 s
  9.     delay_ms(200);
    ( K/ a* b% m  A9 P& `( V3 l/ {0 b
  10.     if(USART1->SR&(1<<5))//当串口接收到消息后跳出循环7 J8 ^. q- X8 Y
  11.     {
    " t& q) L! k# K% }6 I
  12.       chang=USART1->DR-'0';//将字符型的数据转换为整型数据6 q$ v1 b- T' G; }6 d: e
  13.       break;
    9 j+ b- v/ n5 v4 k5 V" u
  14.     }
    7 T/ V7 K7 _- J! U5 B5 R3 A, n6 L- V$ j. F
  15.   }" _% j- Y) x% m' s4 ~+ w
  16.   printf("长:%d\r\n",chang);//打印串口接收到的数据
    : X# k  o; |% b0 b
  17.   USART1->SR=0;//串口的接收标志位清零,为下一次接收宽度数据做准备
    * G- T9 C& g, o+ k& m
  18.   while(1)
    * D- V  m) q8 o$ s: y; x( t# X1 L
  19.   {
      _+ ]3 \. _1 ?# Q7 |. _
  20.     printf("Input Kuan:\r\n");5 P9 R# X5 N# G, g! J5 K, [# u
  21.     delay_ms(200);
    4 V7 y  c# t/ D9 j; c6 b
  22.     if(USART1->SR&(1<<5)); B4 K6 H: i/ Q
  23.     {1 M9 x: R  S6 f
  24.       kuan=USART1->DR-'0';//当串口接收到数据后跳出循环
    $ \9 ^* [, g8 e1 F4 n4 P" j
  25.       break;
    % O. c; p: v% D5 V4 L: b$ m
  26.     }
    * b: i/ m, H+ f2 W; D! u" c
  27.   }
    # u5 |' v' @  T; w) g$ d6 f
  28.   printf("宽:%d\r\n",kuan);//打印宽度数据
    ( n5 C% x+ D6 d' i
  29.   //当前小车速度为0.25米每秒则小车每走1cm要用40ms所以以1cm为单位每走1cm耗时40ms用for函数驱动小车运动
      u* F7 Q7 L% i; r7 e6 W0 M
  30.   for(x=0;x<chang*10;x++)//直走长
    5 y, b4 U8 ]" q* t" d0 N' S. }* E' j: w
  31.   {: `( V4 F- V! N' J6 W& [
  32.     GO(300,300);- A0 G) q# V+ G1 }5 K0 x
  33.     delay_ms(40);2 C& i, d. B9 }  t
  34.   }; ^8 ]' u" M6 ^6 Z& t: n( a" f
  35.   RIGHT(300,300);//右拐- W- D0 X, p0 W, P  p
  36.   delay_ms(785);4 T# ^4 i1 e9 O/ O( S# e  h' L$ c# }
  37.   for(y=0;y<kuan*10;y++)//直走宽3 V3 R3 v  c3 g3 W# R
  38.   {
    # o; {) A1 x5 P2 ^
  39.     GO(300,300);1 Q/ W, H( Z; `8 m- B6 }
  40.     delay_ms(40);
    4 }" N3 D  ?9 v. }5 p) a
  41.   }
    6 a+ v% B$ w5 n. L9 H* |  ~
  42.   RIGHT(300,300);//右拐$ I! A4 c) \* r- A9 B5 t, x( b
  43.   delay_ms(785);, ^9 k0 W- ?, k) Z6 w4 `- L
  44.   for(x=0;x<chang*10;x++)//直走长
    ) k: y+ m: v$ t. V4 S: j( u9 L* ^
  45.   {. t; E1 K/ D5 N( k
  46.     GO(300,300);
    & i, o  S, Q. ~- h5 ?5 [* {
  47.     delay_ms(40);
    0 Y( k) U& j+ f9 E
  48.   }4 B; U- k! y6 G" O1 U+ G; `6 s
  49.   RIGHT(300,300);//右拐
    4 L' v: b/ i0 @2 h, {
  50.   delay_ms(785);. F6 N  L6 r1 ]1 c* C
  51.   for(y=0;y<kuan*10;y++)//直走宽8 w) f* W, b8 `# e: i
  52.   {
    8 K, `* ~1 }, Q- P* \( L) C6 w
  53.     GO(300,300);
    / o8 V# n% @1 B- y& ]6 a
  54.     delay_ms(40);
    8 P2 |- i+ r) M) q+ [
  55.   }7 f& ]! h4 C& J* Z7 W, v; p. D' J
  56.   RIGHT(300,300);//右拐
      G9 S1 Y. W$ G3 V# Q0 r6 ~& P
  57.   delay_ms(785);
    ( k( z( Y5 g! i# X1 S& L
  58.   STOP();
    5 E, b" V4 S# ^
  59.   
复制代码
$ t+ I1 D+ f/ M1 Y" d) e

6 ]9 q: G5 Y! B4 C' }转载自: 古月居
$ H3 q' q' l$ `0 ^' X
收藏 评论0 发布时间:2022-9-3 15:17

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版