美文网首页
基于stm32的多功能时钟8——蓝牙串口通信(测试篇)

基于stm32的多功能时钟8——蓝牙串口通信(测试篇)

作者: 世缘 | 来源:发表于2020-02-08 17:41 被阅读0次

        读者们,想你们的小编又回来了。

        从这一章开始,小编将进行上位机与下位机通信的开发,将单片机采集到的数据传输到手机实时显示。当然,考虑到这部分还是有点难度的,并且,在调试过程中,我找到两个蓝牙软件,一个是《蓝牙串口》,一个是《蓝牙调试器》。其中《蓝牙串口》可以简单发送和接收一些字符和16进制数,《蓝牙调试器》的功能比较强大,但在接收发界面里显示不出来,不知道是软件本身问题,还是我没设置好相关参数。但这款软件里的专业调试界面可以自己布局控件,即不需要编写代码就能做出符合自己项目的上位机来,所以还是得佩服一下该开发者。

        在本章中,小编将开发下位机通信程序,结合《蓝牙串口》软件,实现从手机发送控制指令,手机再接收单片机发送过来的相应数据。在这里,人为规定,发送0x01,则手机串口接收到温度数据(1字节),发送0x02,则手机串口接收到湿度数据(1字节),发送0x03,则手机串口接收到空气质量数据(若0~255,1字节,若大于255,2字节),发送0x04,则手机串口接收到距离数据(若0~255,1字节,若大于255,2字节)。


1.资源分析

        蓝牙模块HC-05,是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口用。当建立连接,两设备共同使用一通道也就是同一个串口,一个设备发送数据到通道中,另外一个设备便可以接收通道中的数据。

HC-05蓝牙模块

        蓝牙模块,共有4个引脚,其中两个电源引脚VCC和GND,一个数据发送端TX,一个数据接收端RX。而stm32f103c8t6具有3个USART串口,USART是一个全双工通用同步/异步串行收发模块。而本次制作,由于USART1串口接口已经焊接设计好,用于与电脑串口通信的(有点尴尬,已损坏,但影响不大),所以采用USART2来通信(TX—>PA2,RX—>PA3)。

2.软件分析

(1)配置串口相关的GPIO

void usart_release_gpio_init(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);

    /*配置PA2为复用推挽输出*/

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /*配置PA3为复用浮空输入*/

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

}

        将USART2的TX端口设置成复用推挽输出,RX端口设置成浮空输入,在开启相关GPIOA时钟的同时,开启串口时钟和复用时钟。

(2) 配置相应串口模式

void usart_para_config(void)

{

    USART_InitTypeDef USART_InitStruct;

    USART_InitStruct.USART_BaudRate = 115200;//设置波特率为115200

    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控

    USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//发送和接收模式

    USART_InitStruct.USART_Parity = USART_Parity_No;//无奇偶校验

    USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位1位

    USART_InitStruct.USART_WordLength = USART_WordLength_8b;//字长为8位

    USART_Init(USART2, &USART_InitStruct);//串口初始化

    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能接收中断

    USART_ClearFlag(USART2, USART_FLAG_TC);//清除发送完成标志位

    USART_Cmd(USART2, ENABLE);//使能串口2

}

        串口模式函数里,由于蓝牙AT指令设置的波特率为115200(不会设置的可以网上查),设置成接收模式,通信的数据结构为字长为8,无奇偶校验位,1位停止位。使用USART_Init()函数,将USART2串口初始化。接着,使能接收中断,清除发送完成标志位,最后使能串口2。

(3)配置NVIC

void usart_nvic_init(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);            //设置组优先级

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;          //设置串口2中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //设置抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //设置子优先级

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能

    NVIC_Init(&NVIC_InitStructure);

}

        由于stm32需要接收手机发过来的控制指令,而接收通常不是每时每刻的,因此采用中断的方式去做,所以需要设置NVIC,以及使能串口中断。中断优先级的配置已经经过多次了,如果还是不清楚的话,就上网再查查。

(4)编写串口接收中断程序

void USART2_IRQHandler(void)

{

    if(USART_GetITStatus(USART2, USART_IT_RXNE)!=RESET)

    {

        rev_data = USART_ReceiveData(USART2);            //接收数据

        usart_flag = CHAN_IN;

    }

    USART_ClearITPendingBit(USART2, USART_IT_RXNE);      //清除接收中断标志

}

        串口接收中断程序里,我们调用串口接收数据函数,暂存在变量rev_data里,然后将接收标志位置位,即可在主程序里调用数据发送语句,否则,主程序是不会发送数据给手机的。

(5)发送采集数据函数

void bluetooth(void)

{

    if(usart_flag == CHAN_IN)

    {

        //接收到0x01:发送温度,接收到0x02:发送湿度,

        //接收到0x03:发送空气质量,接收到0x04:发送距离

        switch(rev_data)

        {

            case 0x01:send_data = temperature;break;

            case 0x02:send_data = humidity;break;

            case 0x03:send_data = value;break;

            case 0x04:send_data = distance/100;break;

            default:break;

        }

        if(rev_data>=0x01&&rev_data<=0x04)

        {

            send_data = send_data/100*256+((send_data%100)/10)*16+send_data%10;

            if(send_data<=255&&send_data>0)

            {

                USART_SendData(USART2, send_data);

                while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

            }

            else

            {

                USART_SendData(USART2, send_data/256);

                while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

                USART_SendData(USART2, send_data%256);

                while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

            }

        }

        usart_flag = NO_CHAN;

    }

}

        该函数在主程序中调用,当接收标志位被置位,则说明单片机接收到手机发过来的指令数据,根据所发的不同指令,则单片机发送不同的采集数据给手机,手机接收到,则在手机界面显示出数据。但别忘了,调用完该发送函数,需要将接收标志位复位,否则单片机将不断地发送数据给手机,显得有些无意义。这里,说明一下,我们有两个宏定义#define NO_CHAN 0x00 #define CHAN_IN 0x01,这样做,可能意义会更明显。在stm32里,小编感觉像宏定义,结构体等用得比较多(可以看一下固件库函数,都是这样的),阅读程序起来也好理解。

蓝牙通信1 蓝牙通信2

        通过上面的操作,我们将蓝牙模块接好,注意这里蓝牙的TX,RX分别接USART2的RX,TX,然后下载好程序,打开《蓝牙串口》软件,点击搜索,即可搜索到蓝牙。在对话框界面,发送和接收对话框都勾选16进制,在发送对话框发送0x01,即可在接收对话框接收到数据,此时显示的是温度的数据,为12度。此时再依次输入0x02、0x03、0x04,即可显示所有数据,此时温度为12度,湿度为69%,空气质量为104PPM,距离为26cm。界面里如果不勾选16进制,则显示乱码,因为此时显示的是字符数据。你可以在程序中发送英文字符串,即可将字符串打印出来。但这个软件不支持中文显示,所以不能打印中文。

        在这里,我声明一下,本章的内容,是为了测试stm32串口配置的代码以及蓝牙模块是否正常工作(由于stm32的usart1硬件电路已损坏,不能连接电脑来调试串口通信)。在后面,我会介绍如何通过《蓝牙调试器》达到数据的实时显示和监控。

相关文章

网友评论

      本文标题:基于stm32的多功能时钟8——蓝牙串口通信(测试篇)

      本文链接:https://www.haomeiwen.com/subject/djbmthtx.html