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

stm32智能小车设计

[复制链接]
STMCU小助手 发布时间:2022-9-3 15:17
历时两周,总算把小车弄好了,总体上来说做的太慢了。自己在32的学习中还不够仔细深入,只是浅面的学习,当真正做一个项目时,暴露的问题就太多了。这次在小车的制作的过程中,遇到了各种各样的问题,软件,硬件,各式各样的问题迎面而来,真的好几次心态崩了。不过还好小车这个项目不只是我一个人在搞,组里的其他成员也在一直在考虑问题,想办法,不断地解决解决,总归小车终于做好了,下面是小车完成图:
微信图片_20220903151642.jpg
微信图片_20220903151646.jpg

是有点灵魂接线(·<·)。



模块清单


  • stm32f103C8T6开发板
  • 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




完成功能


  • 超声波避障
  • 蓝牙控制
  • 走矩形



各个模块就不再介绍了,具体介绍大家可以自行百度或者看一下我的前几篇Arduino智能小车博客,里面有简单的介绍。


那么,开始吧。


准备工作


1.首先配置好keil5 c8t6模板(温馨提示:多看看模板的核心驱动,包括sys.h delay.h usart.h等,这些核心文件一定要保证准确无误!)
2.了解开发板和确保开发板无误
3.熟悉怎么用转串口模块和st-link将驱动下载到开发板上。

下图示为c8t6开发板的引脚图

微信图片_20220903151652.jpg

1.超声波避障功能
我们设计的思路如下,用三个超声波来避障。为什么用三个超声波呢?我们想的是如果用舵机的话,小车在行进过程中并不好判断,只能将车停下,舵机转动来检测哪个方向无障碍物,而用3个超声波不仅可以在行进中判断,也可以让小车没有停下的动作,显得整个过程比较流畅。这就是我们使用三个超声波的原因了。

我们使用的是定时器二的通道一,通道二,通道三来进行输入捕获的,那么,第一个问题就来了。

我们在写超声波代码时,用一个超声波先测试,发现超声波测试的并没有问题 ,串口显示的数据也并没有问题。但是,但是,在用三个超声波同时测试是,却发现数据显示的总有问题,输出的数据总是毫无规律,且数字都非常大,我们就在想是什么问题。

下面是三个超声波控制的代码:

  1. //main.c
  2. #include "sys.h"
  3. #include "usart.h"   
  4. #include "delay.h"  
  5. #include "led.h"  
  6. #include "dianji.h"
  7. #include "hcsr.h"
  8. u32 DIS_Init(u8 STA,u16 VAL)
  9. {
  10.     u32 temp;
  11.     u32 lenth;
  12.     if((*STA)&0X80)//成功捕获到了一次高电平
  13.     {
  14.         temp=STA&0X3F;
  15.         temp*=65536;               //溢出时间总和
  16.         temp+=VAL; //得到总的高电平时间
  17.         lenth=temp*0.017;           //计算长度
  18.         STA=0;     //开启下一次捕获
  19.     }
  20.     return lenth;
  21. }

  22. extern u8 TIM2CH2_CAPTURE_STA; //输入捕获状态
  23. extern u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值

  24. extern u8 TIM2CH3_CAPTURE_STA; //输入捕获状态
  25. extern u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值

  26. extern u8 TIM2CH4_CAPTURE_STA; //输入捕获状态
  27. extern u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值

  28. int main(void)
  29. {   
  30.   u32 temp=0;
  31.   u32 length1;
  32.   u32 length2;
  33.   u32 length3;   
  34.   Stm32_Clock_Init(9); //系统时钟设置
  35.   delay_init(72);       //延时初始化
  36.   uart_init(72,9600);  //串口初始化        //初始化与LED连接的硬件接口
  37.   TIM_PWM1_Init();//10000-1,36-1);//不分频。PWM频率=72M/(0.036M)=2Khz
  38.   Echo1=0;
  39.   Echo2=0;
  40.   Echo3=0;
  41.   HCSR04_Init(0XFFFF,72-1);//以1Mhz的频率计数
  42.   /*while(1)
  43.   {
  44.    
  45.   }*/
  46.   while(1)
  47.   {
  48.     Echo3=1;
  49.     delay_us(20);
  50.     Echo3=0;
  51.     length1=DIS_Init(&TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL);
  52.     delay_ms(1000);
  53.     Echo1=1;
  54.     delay_us(20);
  55.     Echo1=0;
  56.     length2=DIS_Init(&TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL);
  57.     delay_ms(1000);
  58.     Echo2=1;
  59.     delay_us(20);
  60.     Echo2=0;
  61.     length3=DIS_Init(&TIM2CH3_CAPTURE_STA,TIM2CH3_CAPTURE_VAL);
  62.     printf("%d %d %d\r\n",length1,length2,length3);
  63.   //  GO();
  64.     delay_ms(500);
  65.   }
  66. }

  67. hcsr.c
  68. #include "sys.h"
  69. #include "delay.h"
  70. #include "usart.h"
  71. #include "hcsr.h"
  72. void HCSR04_Init(u16 arr,u16 psc)
  73. {
  74.     RCC->APB1ENR|=1<<0;    //TIM2时钟使能
  75.     RCC->APB2ENR|=1<<2;    //使能PORTA时钟
  76.     RCC->APB2ENR|=1<<3;     //使能PORTB时钟
  77.     GPIOA->CRL&=0XFFFF000F;//PA1 清除之前设置
  78.     GPIOA->CRL|=0X00008880;//PA1输入
  79. //    GPIOA->ODR|=0<<0;
  80.     GPIOA->ODR|=0<<1;      //PA1下拉
  81.     GPIOA->ODR|=0<<2;
  82.     GPIOA->ODR|=0<<3;
  83.   
  84.     GPIOB->CRL&=0X000FFFFF;//PB7清除之前设置
  85.     GPIOB->CRL|=0X33300000;//PB7推挽输出
  86.     GPIOB->ODR|=1<<7;      //PB7 输出高
  87.     GPIOB->ODR|=1<<6;
  88.     GPIOB->ODR|=1<<5;
  89.   
  90.     TIM2->ARR=arr;         //设定计数器自动重装值
  91.     TIM2->PSC=psc;         //预分频器
  92.   
  93.     TIM2->CCMR1|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
  94.     TIM2->CCMR1|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
  95.     TIM2->CCMR1|=0<<10;    //IC2PS=00 配置输入分频,不分频
  96.   
  97.     TIM2->CCER|=0<<5;      //CC2P=0 上升沿捕获
  98.     TIM2->CCER|=1<<4;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
  99.    
  100.     TIM2->CCMR2|=1<<0;     //CC2S=01 选择输入端IC1映射到TI1
  101.     TIM2->CCMR2|=1<<4;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
  102.     TIM2->CCMR2|=0<<2;    //IC2PS=00 配置输入分频,不分频
  103.   
  104.     TIM2->CCER|=0<<9;      //CC2P=0 上升沿捕获
  105.     TIM2->CCER|=1<<8;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
  106.    
  107.     TIM2->CCMR2|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
  108.     TIM2->CCMR2|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
  109.     TIM2->CCMR2|=0<<10;    //IC2PS=00 配置输入分频,不分频
  110.   
  111.     TIM2->CCER|=0<<13;      //CC2P=0 上升沿捕获
  112.     TIM2->CCER|=1<<12;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
  113.    
  114.     TIM2->DIER|=1<<2;      //允许捕获中断
  115.     TIM2->DIER|=1<<3;      //允许捕获中断
  116.     TIM2->DIER|=1<<4;      //允许捕获中断
  117.     TIM2->DIER|=1<<0;      //允许更新中断
  118.     //TIM2->CR1|=0X01;       //使能定时器2
  119.     MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
  120. }

  121. u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
  122. u16 TIM2CH1_CAPTURE_VAL;  //输入捕获值

  123. u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态
  124. u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值

  125. u8 TIM2CH3_CAPTURE_STA=0; //输入捕获状态
  126. u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值

  127. u8 TIM2CH4_CAPTURE_STA=0; //输入捕获状态
  128. u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值

  129. //定时器2中断服务程序
  130. void TIM2_IRQHandler(void)
  131. {
  132.     u16 tsr;
  133.     tsr=TIM2->SR;
  134.   
  135.     if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
  136.     {
  137.         if(tsr&0X01)//溢出
  138.         {
  139.             if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
  140.             {
  141.                 if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
  142.                 {
  143.                     TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
  144.                     TIM2CH4_CAPTURE_VAL=0XFFFF;
  145.                 }else TIM2CH4_CAPTURE_STA++;
  146.             }
  147.         }
  148.         if(tsr&0x10)//捕获1发生捕获事件
  149.         {
  150.             if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
  151.             {
  152.                 TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
  153.                 TIM2CH4_CAPTURE_VAL=TIM2->CCR4;//获取当前的捕获值
  154.                 TIM2->CCER&=~(1<<13);    //CC1P=0 设置为上升沿捕获
  155.             }else                       //还未开始,第一次捕获上升沿
  156.             {
  157.                 TIM2CH4_CAPTURE_VAL=0;
  158.                 TIM2CH4_CAPTURE_STA=0X40; //标记捕获到了上升沿
  159.                 TIM2->CNT=0;             //计数器清空
  160.           //    TIM2CH4_CAPTURE_VAL=TIM2->CCR4;
  161.                 TIM2->CCER|=1<<13;        //CC1P=1 设置为下降沿捕获
  162.               TIM2->CR1|=0x01;
  163.             }
  164.         }
  165.     }
  166.     if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获
  167.     {
  168.         if(tsr&0X01)//溢出
  169.         {
  170.             if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
  171.             {
  172.                 if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
  173.                 {
  174.                     TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
  175.                     TIM2CH2_CAPTURE_VAL=0XFFFF;
  176.                 }else TIM2CH2_CAPTURE_STA++;
  177.             }
  178.         }
  179.         if(tsr&0x04)//捕获1发生捕获事件
  180.         {
  181.             if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿
  182.             {
  183.                 TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
  184.                 TIM2CH2_CAPTURE_VAL=TIM2->CCR2;//获取当前的捕获值
  185.                 TIM2->CCER&=~(1<<5);    //CC1P=0 设置为上升沿捕获
  186.             }else                       //还未开始,第一次捕获上升沿
  187.             {
  188.                 TIM2CH2_CAPTURE_VAL=0;
  189.                 TIM2CH2_CAPTURE_STA=0X40; //标记捕获到了上升沿
  190.                 TIM2->CNT=0;             //计数器清空
  191.                 TIM2->CCER|=1<<5;        //CC1P=1 设置为下降沿捕获
  192.               TIM2->CR1|=0x01;
  193.             }
  194.         }
  195.     }
  196.    
  197.     if((TIM2CH3_CAPTURE_STA&0X80)==0)//还未成功捕获
  198.     {
  199.         if(tsr&0X01)//溢出
  200.         {
  201.             if(TIM2CH3_CAPTURE_STA&0X40)//已经捕获到高电平了
  202.             {
  203.                 if((TIM2CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
  204.                 {
  205.                     TIM2CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
  206.                     TIM2CH3_CAPTURE_VAL=0XFFFF;
  207.                 }else TIM2CH3_CAPTURE_STA++;
  208.             }
  209.         }
  210.         if(tsr&0x08)//捕获1发生捕获事件
  211.         {
  212.             if(TIM2CH3_CAPTURE_STA&0X40) //捕获到一个下降沿
  213.             {
  214.                 TIM2CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
  215.                 TIM2CH3_CAPTURE_VAL=TIM2->CCR3;//获取当前的捕获值
  216.                 TIM2->CCER&=~(1<<9);    //CC1P=0 设置为上升沿捕获
  217.             }else                       //还未开始,第一次捕获上升沿
  218.             {
  219.                 TIM2CH3_CAPTURE_VAL=0;
  220.                 TIM2CH3_CAPTURE_STA=0X40; //标记捕获到了上升沿
  221.                 TIM2->CNT=0;  
  222.             //    TIM2CH3_CAPTURE_VAL=TIM2->CCR3;              //计数器清空
  223.                 TIM2->CCER|=1<<9;        //CC1P=1 设置为下降沿捕获
  224.               TIM2->CR1|=0x01;
  225.             }
  226.         }
  227.   }
  228.    
  229.         
  230.     TIM2->SR=0;//清除中断标志位
  231.    
  232. }

  233. hcsr.h
  234. #ifndef __HSCR04_H
  235. #define __HSCR04_H
  236. #include "sys.h"

  237. #define Echo1 PBout(7) // PB7
  238. #define Echo2 PBout(6) // PB7
  239. #define Echo3 PBout(5) // PB7

  240. void HCSR04_Init(u16 arr,u16 psc);

  241. #endif
复制代码

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

问题二就是从串口读取数据,当时挺崩溃的。首先是keil5模板问题,当时串口怎么都显示不出来数据,我们当时都很疑惑。一直反复的看代码,考虑各种情况,但还是显示不出来数据。一开始我们以为是超声波接受的反馈的数据不满足某个条件,所以没有显示。到后面查来查去,又在想是开发板并没有给电压?超声波集体歇B?最终发现,usart.c文件写的串口不是我们接线串口所对应的。当时心态挺炸的,改了之后终于可以测试数据了。

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

最终解决的方法是,串口模块给的电压不够。(我也不知道这样形容的对不对,但感觉就是),为什么这样说呢?

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

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

pwm控制部分代码:
  1. #include "dianji.h"
  2. #include "sys.h"
  3. #include "delay.h"

  4. void TIM_PWM1_Init(u16 arr,u16 psc)
  5. {               
  6.   //此部分需手动修改IO口设置
  7.   RCC->APB1ENR|=1<<1;   //TIM3时钟使能   
  8.   RCC->APB2ENR|=1<<2;    //GPIOA使能
  9.   RCC->APB2ENR|=1<<3;   //GPIOB使能
  10.   RCC->APB2ENR|=1<<4;
  11.   GPIOA->CRL&=0X00FFFFFF;  //PA(7)PA(6)做复用,PA(3)是BIN1 PA(4)BIN2 PA(5)STBY
  12.   GPIOA->CRL|=0XBB000000;
  13.   //GPIOA->ODR|=1<<7;
  14.   //GPIOA->ODR|=1<<6;
  15.   GPIOC->CRH&=0X000FFFFF;
  16.   GPIOC->CRH|=0X33300000;
  17.   GPIOB->CRL&=0XFFFFF000; //PB(0)是AIN1 PB(1)是AIN2
  18.   GPIOB->CRL|=0X00000333;
  19.   TIM3->ARR=arr;      //设定计数器3自动重装值
  20.   TIM3->PSC=psc;      //预分频器设置
  21.   
  22.   TIM3->CCMR1|=6<<4;    //CH1 PWM2模式     
  23.   TIM3->CCMR1|=1<<3;     //CH1预装载使能   
  24.   TIM3->CCMR1|=6<<12;    //CH2 PWM2模式     
  25.   TIM3->CCMR1|=1<<11;     //CH2预装载使能  
  26.   
  27.    TIM3->CCER|=1<<0;     //OC1 输出使能
  28.   TIM3->CCER|=1<<4;     //OC1 输出使能  
  29. //  TIM3->BDTR|=1<<15;     //MOE 主输出使能     

  30.   TIM3->CR1=0x0080;     //ARPE使能
  31.   TIM3->CR1|=0x01;      //使能定时器3

  32.   RCC->APB2ENR|=1<<11; //TIM1定时器使能
  33.   GPIOA->CRH&=0XFFFF0FF0;
  34.   GPIOA->CRH|=0X0000B00B;
  35.   //GPIOA->ODR|=1<<8;
  36.   //GPIOA->ODR|=1<<11;
  37.   
  38.   GPIOB->CRH&=0X0000FFFF;
  39.   GPIOB->CRH|=0X33330000;
  40.   
  41.   TIM1->ARR=arr;      //设定计数器自动重装值
  42.   TIM1->PSC=psc;      //预分频器设置
  43.   
  44.   TIM1->CCMR1|=6<<4;    //CH1 PWM2模式     
  45.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
  46.   TIM1->CCMR2|=6<<12;    //CH4 PWM2模式     
  47.   TIM1->CCMR2|=1<<11;     //CH4预装载使能  
  48.   
  49.   TIM1->CCER|=1<<0;     //OC1 输出使能
  50.   TIM1->CCER|=1<<12;     //OC4 输出使能  
  51.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     

  52.   TIM1->CR1=0x0080;     //ARPE使能
  53.   TIM1->CR1|=0x01;      //使能定时器1
  54.   
  55.   STBY=1;
  56.   STBY1=1;
  57. }

  58. void GO(u16 a,u16 b)
  59. {
  60.   AIN1=0;     //AIN1,BIN1,AIN2,BIN2控制轮子方向
  61.   AIN2=1;
  62.   BIN1=0;
  63.   BIN2=1;
  64.   AIN3=1;
  65.   AIN4=0;
  66.   BIN3=1;
  67.   BIN4=0;  
  68.   
  69.   TIM3->CCR1=a;//右上,控制速度
  70.   TIM3->CCR2=b;//左上
  71.   TIM1->CCR1=a;//右下
  72.   TIM1->CCR4=b;//左下
  73.   //delay_ms(2000);
  74. }

  75. void STOP(void)
  76. {
  77.   AIN1=0;
  78.   AIN2=0;
  79.   BIN1=0;
  80.   BIN2=0;
  81.   AIN3=0;
  82.   AIN4=0;
  83.   BIN3=0;
  84.   BIN4=0;  
  85. }

  86. void BACK(u16 a,u16 b)
  87. {
  88.   AIN1=1;
  89.   AIN2=0;
  90.   BIN1=1;
  91.   BIN2=0;
  92.   AIN3=0;
  93.   AIN4=1;
  94.   BIN3=0;
  95.   BIN4=1;  
  96.   
  97.   TIM3->CCR1=a;//右上
  98.   TIM3->CCR2=b;//左上
  99.   TIM1->CCR1=a;//右下
  100.   TIM1->CCR4=b;//左下
  101. //  delay_ms(1000);
  102. }

  103. void RIGHT(u16 a,u16 b)
  104. {
  105.   AIN1=1;
  106.   AIN2=0;
  107.   BIN1=0;
  108.   BIN2=1;
  109.   AIN3=0;
  110.   AIN4=1;
  111.   BIN3=1;
  112.   BIN4=0;  
  113.   
  114.   TIM3->CCR1=a;//右上
  115.   TIM3->CCR2=b;//左上
  116.   TIM1->CCR1=a;//右下
  117.   TIM1->CCR4=b;//左下
  118. //  delay_ms(1000);
  119. }

  120. void LEFT(u16 a,u16 b)
  121. {
  122.   AIN1=0;
  123.   AIN2=1;
  124.   BIN1=1;
  125.   BIN2=0;
  126.   AIN3=1;
  127.   AIN4=0;
  128.   BIN3=0;
  129.   BIN4=1;  
  130.   
  131.   TIM3->CCR1=a;//右上
  132.   TIM3->CCR2=b;//左上
  133.   TIM1->CCR1=a;//右下
  134.   TIM1->CCR4=b;//左下
  135. //  delay_ms(1000);
  136. }
复制代码

3.蓝牙控制
蓝牙控制这一内容是小伙伴写的,大概内容和串口一章内容相似,就是多做出了判断,即没通过蓝牙输入数据来改变小车此时的模式,在蓝牙控制模式下,也可以相对应用蓝牙控制小车的方向。我们用的仍是串口一来控制蓝牙,为什么这样做?一是方便,二是就如前面所说,电机和超声波的分压严重,在电脑上上的串口监视器得出的数据并不准确,所以还不如用蓝牙来看数据,于是我们直接用了串口一来和蓝牙连接。初始化问题并不需要要修改,直接调用uart()函数即可,在中断控制代码下加入接收数据而触发的各种就好了。

蓝牙控制部分代码:
  1. void USART1_IRQHandler(void)
  2. {
  3.   char res;  
  4.   if(USART1->SR&(1<<5))
  5.   {   
  6.     res=USART1->DR;
  7.     printf("\r\n%d",res);   
  8.     if(res==50)                                              //输入2为前进
  9.     {  
  10.       GO(300,300);
  11.       printf("\r\nGo Stright");
  12.     }
  13.     else if(res==56)                       //输入8为后退
  14.     {
  15.       BACK(300,300);
  16.       printf("\r\nGo Back");
  17.     }
  18.     else if(res== 52)                //输入4为左转
  19.     {
  20.       LEFT(300,300);
  21.       printf("\r\nTurn Left");      
  22.     }
  23.     else if(res==54)                //输入6为右转
  24.     {
  25.       RIGHT(300,300);
  26.       printf("\r\nTurn Right");
  27.     }
  28.     else if(res==53)                //输入5为停止
  29.     {
  30.       STOP();
  31.       printf("\r\nStop");
  32.     }
  33.     else if(res=='9')                //进入超声波避障模式
  34.     {
  35.       opq=0;
  36.     }
  37.   }
  38. }
复制代码

总的来说蓝牙控制这块并没有踩多少坑(大概这不是我写的吧^ _ ^,感谢小伙伴)

4.走矩形

走矩形功能也是小伙伴写的,设计思路大致是通过蓝牙输入长和宽,小车通过接受的数据进行矩形运动。在这唯一遇到的问题就是小车的速度问题和转向时间。这个是他们弄得,自我感觉还是很不好调的,因为要考虑电池可供电压,小车行驶的惯性,不同地面的摩擦程度等等。考虑的方面比较多,根据不同的情况可能还要修改小车的速度和转向时间。我们就是在光滑地砖上测得,摩擦力应该是比较小的。
走矩形代码:
  1. void Juxing()//小车的矩形运动函数
  2. {
  3.   u8 chang,kuan,x,y;//chang、kuan分别是小车要走矩形的长和宽的值
  4.   delay_ms(200);
  5.   printf("Chang:\r\n");
  6.   while(1)
  7.   {
  8.     printf("Input Chang:\r\n");
  9.     delay_ms(200);
  10.     if(USART1->SR&(1<<5))//当串口接收到消息后跳出循环
  11.     {
  12.       chang=USART1->DR-'0';//将字符型的数据转换为整型数据
  13.       break;
  14.     }
  15.   }
  16.   printf("长:%d\r\n",chang);//打印串口接收到的数据
  17.   USART1->SR=0;//串口的接收标志位清零,为下一次接收宽度数据做准备
  18.   while(1)
  19.   {
  20.     printf("Input Kuan:\r\n");
  21.     delay_ms(200);
  22.     if(USART1->SR&(1<<5))
  23.     {
  24.       kuan=USART1->DR-'0';//当串口接收到数据后跳出循环
  25.       break;
  26.     }
  27.   }
  28.   printf("宽:%d\r\n",kuan);//打印宽度数据
  29.   //当前小车速度为0.25米每秒则小车每走1cm要用40ms所以以1cm为单位每走1cm耗时40ms用for函数驱动小车运动
  30.   for(x=0;x<chang*10;x++)//直走长
  31.   {
  32.     GO(300,300);
  33.     delay_ms(40);
  34.   }
  35.   RIGHT(300,300);//右拐
  36.   delay_ms(785);
  37.   for(y=0;y<kuan*10;y++)//直走宽
  38.   {
  39.     GO(300,300);
  40.     delay_ms(40);
  41.   }
  42.   RIGHT(300,300);//右拐
  43.   delay_ms(785);
  44.   for(x=0;x<chang*10;x++)//直走长
  45.   {
  46.     GO(300,300);
  47.     delay_ms(40);
  48.   }
  49.   RIGHT(300,300);//右拐
  50.   delay_ms(785);
  51.   for(y=0;y<kuan*10;y++)//直走宽
  52.   {
  53.     GO(300,300);
  54.     delay_ms(40);
  55.   }
  56.   RIGHT(300,300);//右拐
  57.   delay_ms(785);
  58.   STOP();
  59.   
复制代码


转载自: 古月居
收藏 评论0 发布时间:2022-9-3 15:17

举报

0个回答

所属标签

相似分享

官网相关资源

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