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

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

        从这一章开始,小编将进行上位机与下位机通信的开发,将单片机采集到的数据传输到手机实时显示。当然,考虑到这部分还是有点难度的,并且,在调试过程中,我找到两个蓝牙软件,一个是《蓝牙串口》,一个是《蓝牙调试器》。其中《蓝牙串口》可以简单发送和接收一些字符和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硬件电路已损坏,不能连接电脑来调试串口通信)。在后面,我会介绍如何通过《蓝牙调试器》达到数据的实时显示和监控。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 姓名:周崇杰 学号:16140120059 专业:机械设计制造及其自动化 转载自:http://blog.csd...
    CJbaby阅读 3,472评论 0 3
  • //通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据. //如果2个字符接收间隔超过1...
    呼啦啦的爱阅读 371评论 0 0
  • 姓名:周崇杰 学号:16140120059 专业:机械设计制造及其自动化 转载自:http://blog.csd...
    CJbaby阅读 4,676评论 0 5
  • # STM32之串口DMA接收不定长数据 ## 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,...
    杰杰T_T阅读 529评论 0 0
  • 有一次做一个东西,为了尽量不占用CPU的处理数据时间,所以就使用DMA接收串口的数据,但是呢问题来了.,,,,,怎...
    杨奉武阅读 3,123评论 0 1