小车调试进度二更~~
#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的不同取值)执行不同的动作
}
}
}
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连接上蓝牙,也就可以实现手机和小车之间的通信了(也可以联想手机和手机之间通过连接蓝牙,就可以实现文件的传输)。