我的小车调试进度之:实现蓝牙通信

小车调试进度二更~~


  • 单片机USART通信的实现
  1. 首先,要写一个USART的底层,具体可参考:STM32之USART串口通信,这篇博客里我写了USART2的底层,然后在我的小车主板上我用的USART1,emmm,其实都一样,把GPIO口和使能的时钟换一下就好啦,别的地方还是差不多啦,我贴一下代码吧,大家可以直接复制使用:
#include "usart.h"

void USART1_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	//开启GPIOA和USART1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
	
	//USART1的中断向量配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	//RXD-PA10 设置为浮空模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//TXD-PA9 设置为推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//USART1的配置
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);
	
	USART_Cmd(USART1, ENABLE);//开启USART1
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启USART1接收中断
	
}

void USART1_SendString(u8 *str)//发送一个字符串的函数
{
	u8 index = 0;
	
	while(str[index++] != 0)
	{
		USART_SendData(USART1, str[index-1]);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == 0);//查询用Flag
	}
}
//接收函数
extern u8 RxdCnt;
extern u8 RxdOver;
extern u8 RxdBuf[20];

void USART1_IRQHandler(void)
{
	u16 tmp;
	
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == 1)//检测接收中断标志位,RXNE为1表示接收到了数据
	{
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除中断标志位(即清除RXNE)
		tmp = USART_ReceiveData(USART2);//读取串口2的数据
		if(tmp == '\n')//‘/n’表示本次读取结束
		{
			RxdBuf[RxdCnt-1] = 0;//避免\r显示在LCD发生的乱码
			RxdCnt = 0;//读取结束清RxdCnt
			RxdOver = 1;//本次数据读取结束标志置1
			USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//接收完毕后关闭,防止处理过程发生干扰。
		}
		else
		{
			RxdBuf[RxdCnt++] = tmp;//将读取到的数据存到RXDBuf中
		}
	}
}

我们先写一个通用版的底层,写完之后,先试试可不可以实现单片机和串口助手的正常通信 (发送数据+接收数据),这个时候需要用到显示屏啦,要将接收到的数据显示出来,这样才能看出来是否成功接收到数据啦,如果你的主控板上没有加显示屏,可以把写的程序下载到开发板上测试一下,具体过程我上面的链接里详细介绍。测试小车主板的话,还需要用到USB-TTL 的下载器按照线序连接主板上的蓝牙接口,然后插到电脑上。(当然,这一步也可以跳过,可以直接写程序,然后直接下载,但是,后面如果出现问题,你还是需要这样一步一步测试的,所以,不如提前把工作做好,确保你的每一步都是没问题的。)
2. 经测试可以实现正常通信后,修改我们的接收函数,执行你想要的执行的内容(以我的函数举例):

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
    uint8_t tmp;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收到数据
    {
        tmp =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
        if(tmp == '\n')
		{
			RxdOver = 1;
			USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//接收完毕后关闭,防止处理过程发生干扰。
		}
		else
		{
			bull = tmp;//将读到的数据存储到bull这个变量里
            Read_Kz();//根据读到的数据(bull的不同取值)执行不同的动作
		}
    }
}
  • 蓝牙的配置
  1. 配置蓝牙,我用的是HC-05,具体配置过程可参考:蓝牙配置相关:HC-05
  2. 测试是否可实现蓝牙串口SPP(手机上的APP) 串口助手(电脑上的串口调试软件) 的正常通信,这两个软件没有的,可以去网上下载,具体过程可参考我上面给的链接,有详细的说明,(emmm,我在配对的时候出现过搜索不到设备的情况,然后我就又重新配置了一次就解决了)。
  • 手机APP和小车的通信
    上面的两个步骤都没有问题的话,就只需要把蓝牙插入小车主板上的蓝牙接口,然后在主函数里while(1)内写上:Read_Kz();这个动作函数就可以测试啦,别忘了写串口初始化函数:
   while (1)
    { 	
        if(RxdOver)
		{
			RxdOver = 0;
            Read_Kz();
			USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//接收的数据处理完毕后打开接收中断
		}

我的动作函数:

void Read_Kz(void)
{
    //2.油门  三个档位
    if ( bull == '7') 
    {
        PWML = 70;
        PWMR = 70;
    }
    if ( bull == '8') 
    {
        PWML = 80;
        PWMR = 80;
    }
    if ( bull == '9') 
    {
        PWML = 90;
        PWMR = 90;//最大值899   速度太快容易导致无线模块断线  ,可以增加容量大的电池来解决
    }
    switch(bull)
    {
    case 'A': motor(M_FOR, M_FOR, M_FOR, M_FOR);PWM2_Init(); LED_ON;break;   //前进
    case 'a': motor(M_REV, M_REV, M_REV, M_REV);PWM2_Init(); LED_ON;break;   //后退

    case 'B': motor(M_REV, M_FOR, M_FOR, M_REV);PWM2_Init(); LED_ON;break;  //←左横13后退;24前进
    case 'b': motor(M_FOR, M_REV, M_REV, M_FOR);PWM2_Init(); LED_ON;break;  //→右横13前进;24后退

    case 'C': motor(0, 0, M_FOR , M_FOR, 0, 0);PWM2_Init(); LED_ON;break; //↖ 二四前进
    case 'c': motor(M_FOR, 0, 0 , 0, 0, M_FOR);PWM2_Init(); LED_ON;break; //↗ 一三前进
        
    case 'D': motor(M_REV, 0, 0 , 0, 0, M_REV);PWM2_Init(); LED_ON;break; //↙ 一三后退
    case 'd': motor(0, 0, M_REV , M_REV, 0, 0);PWM2_Init(); LED_ON;break; //↘ 二四后退

    case 'F': motor(M_REV, M_REV, M_FOR, M_FOR);PWM2_Init(); LED_ON;break; //左旋转
    case 'f': motor(M_FOR, M_FOR, M_REV, M_REV);PWM2_Init(); LED_ON;break; //右旋转
         
    case 'S': motor(M_FREE, M_FREE,M_FREE, M_FREE); LED_OFF;break;   //停止
    }
}

成功通信的现象: 用手机上的蓝牙串口SPP向单片机发送变量bull的不同取值可执行相应的动作。


对于蓝牙通信的一点理解:
之前自己并不是很理解这个东东,后来在调试程序的过程中,突然就理解了,蓝牙我们可以把它看成一个媒介,一个沟通手机和单片机的媒介,但是这个媒介需要配置,也就是我们上面所说的蓝牙配置过程,配置完毕后,把蓝牙与单片机对应的通信接口相连,就相当于单片机(小车)具有了和外界沟通的媒介,手机上的APP连接上蓝牙,也就可以实现手机和小车之间的通信了(也可以联想手机和手机之间通过连接蓝牙,就可以实现文件的传输)。
在这里插入图片描述

你可能感兴趣的:(麦克纳姆轮小车制作)