美文网首页
基于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