基于串口的BLE模组CC2640R2使用总结

之前写过蓝牙控制芯片nRF52832的一篇概述,里面主要记录了蓝牙的分层结构,需要的话可参考:nRF52832蓝牙概述_路溪非溪的博客-CSDN博客

这篇文章记录的是蓝牙模组的基本使用。

二者有何区别呢?

nRF52832是一款基于蓝牙的主控芯片,灵活度较高,能够实现更多的功能,它几乎和STM32芯片类似,有各种各样实现功能的外设,蓝牙只是其主打的一个外设而已,蓝牙协议实现得很全面。

而BLE模组,基本上就是作为一个透传的模块来使用,等同于一根导线,试想下,如果是一个传感器需要跟主控芯片通信,通过导线就可以了,但是蓝牙因为是无线的,没有导线,那怎么传输信号呢?这时候就需要一个透传模块。而CC2640R2所起的就是这个作用。

这个概念,就是透传。

什么是透传?

假如我现在有个蓝牙从机在板子上和单片机通过串口连接,这时,蓝牙主机通过蓝牙协议连接上蓝牙从机,此时,双方如何通信呢?

蓝牙主机发消息给蓝牙从机,蓝牙从机模组不会对这个数据进行任何额外的处理,而是会直接将这个数据转发给串口,此时单片机通过串口读到数据;当单片机需要发数据给主机时,直接将数据通过串口发送给蓝牙从机模组,同样的,蓝牙从机模组不会对数据进行任何的额外处理,而是直接将数据转发给主机。

从上面描述的过程来看,是不是蓝牙从机就好像不存在一样,单片机通过串口就能直接跟主机进行通信,我们也不需要在蓝牙从机上做任何数据操作,就好像这个蓝牙从机就是一根导线。

这种传输模式,就叫做透明传输。

理解透传之后,我们再来了解一下蓝牙模组的模式。

AT指令模式和透传模式

其实,市面上的各种集成模组,大部分都是采样这样的方式来实现,即存在两种模式,那就是AT指令模式和数据透传模式。

为什么有这两种模式呢?就以BLE模组CC2640来讲一下。

首先,如果要让模组实现功能,肯定要对其进行一些设置,设置成功之后,才能进行正确的数据传输,任何外设都是如此,一定是要先初始化,设置需要的一些参数,之后才能正常通信。

蓝牙模组也不例外,所以,模组通常就集成了相应的AT指令,我们只要发送指令给模组,就能对模组进行设置,此时,蓝牙模组就处于AT指令模式,在这种模式下,单片机发送的指令,模组在接收之后,并不会透传出去,而是会自己执行;当我们在AT指令模式下将模组的参数设置好,蓝牙也连接上了之后,就可以进入透传模式,这时,单片机给模组发的数据,就会透传出去,模组本身并不会对其进行任何额外处理。

示例如下:

对于这两种模式的切换,不同的模组有不同的方式,有的模组会通过一个引脚的电平切换来实现模式的转换,而有的模组,在连接之前处于AT指令模式,只要连接上了蓝牙,就会自动进入到透传模式,不用进行额外的操作。

BLE模组CC2640采用的就是第二种自动切换的方式。

透传模式,是模组内部就实现了数据的转发,而不需要我们去实现。

注意:

如果处于透传模式,即使发了AT指令,模组也不会执行,而是会当做数据透传出去。

说明下:

nRF52832不是蓝牙模组,而是一个蓝牙主控芯片,所以除了蓝牙的协议,其他部分需要我们自行设置和实现,就比如透传,就需要我们自己写代码去实现数据的转发。

CC2640使用

CC2640 R2 透传分为蓝牙主机版本,以及蓝牙从机版本

本文以蓝牙从机为例,场景是:MCU和手机APP的通信。

透传模式,又叫桥接模式。

桥接模式:这是常用模式,搭建传统 MCU 与手机蓝牙之间的通信桥梁。用户MCU 可以通过模块的通用串口和移动设备进行双向通讯,用户也可以通过特定的串口 AT 指令,对某些通讯参数进行管理控制。用户数据的具体含义由上层应用程序自行定义。移动设备可以通过 APP 对模块进行写操作,写入的数据将通过串口发送给用户的 MCU。模块收到来自用户 MCU 串口的数据包后,将自动转发给移动设备。此模式下的开发,用户必须负责主 MCU 的代码设计,以及智能移动设备端 APP 代码设计。

模块通过初始设置后会自动进行广播,与打开特定 APP 的手机会对其进行扫描和对接,成功之后便可以通过 BLE 协议对其进行监控。
实物图展示:
引脚说明:
这里面除了串口引脚之外,还有几个比较重要的引脚。
Wakeup引脚,用来唤醒模组,之后才能进行串口传输。
BleCtrl引脚,用来控制广播的开启和关闭。
BleState引脚,用来监测模组当前处于连接还是断开状态。
一般的工作步骤是这样的。
上电后,先要发指令,发指令时,要Wakeup唤醒模组,然后才能发,指令发完之后,根据实际情况,在必要时通过BleCtrl打开广播,打开广播后,主机就可以连接模组了,连接成功后,模组就会进入透传模式,此时,就可以收发数据了,发送数据时,也要先唤醒模组。
然后,通过BleState实时监测蓝牙的连接和断开,以便做不同的处理。
桥接模式
可以看到,这里的通道分为BLE参数配置通道和用户数据通道,就是分别在AT指令模式和透传模式下使用的信道。
AT指令说明
此处仅部分AT指令,更多查看数据手册。
需要注意的是,AT指令的结尾就是回车换行符,也就是\r\n
指令格式如下:
模组主动发出的提示信息
关于指令的详细内容,自行查看数据手册。
以下仅以设置模组名称举例说明。
有的指令只能写,有的指令只能读,有的只能既能写也能读。
比如设置模组名称指令,既能写,也能读。
写的时候,就是给模组取名。
读的时候,就是读当前模组的名称。
比如上述的回复:
AT+OK
TTC-BLE
首先,总是会返回AT+OK+回车换行,之后如果有内容,再返回内容+回车换行。

透传的软件实现

先附上代码,然后再进行说明。

#include "ble.h"
#include "a_board.h"

//定义串口接收数据相关的变量
uint8_t g_Uart1RecvBuf[200];//接收缓冲,一帧数据
uint16_t g_Uart1RecvCount = 0;//接收数目
uint8_t USART1_FRAME_RX_STA = 0;//接收状态标记

void ble_uart_send_data(uint8_t *data, uint16_t len);
void wakeup_ble_usart(void);

//初始化蓝牙模块的IO(除串口外)
//PA8   BLE-WAKEUP-MCU输出
//PC7   BLECtrl-MCU输出
//PC8   BLEState-MCU输入
//PC9   BLE-INT-MCU输入
static void ble_io_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
        
    //配置时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);	 //使能PA端口时钟

    //IO通用参数配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    
    //PA8
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				 //PA8 端口配置
    GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
    
    //PC7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;				 //PC7端口配置
    GPIO_Init(GPIOC, &GPIO_InitStructure);					 //根据设定参数初始化GPIOC.7
    
    //PC89
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOC, &GPIO_InitStructure);  
}

//蓝牙的通信串口初始化
//PA9   BLE-TX-串口1
//PA10  BLE-RX-串口1
static void ble_usart_init()
{
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1时钟和GPIOA时钟

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	//USART1_RX	  GPIOA.10初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);  

	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = 256000;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口1
    
    //USART1中断配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器
    
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断
    
    USART_Cmd(USART1, ENABLE);                    //使能串口1
}

//蓝牙串口1数据发送函数
void usart1_send_data(uint8_t *txData, uint8_t txLength)
{
	for(uint8_t i = 0; i < txLength; i++)
	{
        USART_SendData(USART1, txData[i]);//向串口1发送数据
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) != SET);//等待发送结束
	}
}

//蓝牙-串口1数据接收函数
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
    uint8_t clear;//清除空闲中断
    
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
        USART_ClearFlag(USART1, USART_IT_RXNE);
		g_Uart1RecvBuf[g_Uart1RecvCount++] = USART_ReceiveData(USART1);
	}
    else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
	{
		clear = USART1->SR; // 清除空闲中断
        clear = USART1->DR; // 清除空闲中断

		USART1_FRAME_RX_STA = 1;//一帧数据接收完成
	}
}

//唤醒蓝牙串口传输
void wakeup_ble_usart(void)
{
    GPIO_ResetBits(GPIOA, GPIO_Pin_8);//置低电平
}

//关闭蓝牙串口传输
void close_ble_usart(void)
{
    GPIO_SetBits(GPIOA, GPIO_Pin_8);//置高电平
}

//开启从机广播
void open_slave_broadcast(void)
{
    GPIO_ResetBits(GPIOC, GPIO_Pin_7);//置低电平
}

//关闭从机广播
void close_slave_broadcast(void)
{
    GPIO_SetBits(GPIOC, GPIO_Pin_7);//置高电平
}

//发送指令
void ble_uart_send_cmd(char *cmd)
{
	int len = strlen(cmd);
    
    wakeup_ble_usart();//唤醒蓝牙串口传输
    delay_ms(2);
    
    //发送指令数据
	usart1_send_data((uint8_t *)cmd, len);
}

//发送透传数据
void ble_uart_send_data(uint8_t *data, uint16_t len)
{
	wakeup_ble_usart();//唤醒蓝牙串口传输
    delay_ms(2);
	
    //发送透传数据
	usart1_send_data(data, len);
}

//蓝牙初始化
void ble_init(void)
{
    ble_io_init();//蓝牙io初始化
    ble_usart_init();//蓝牙串口初始化
    
    //设置蓝牙名称
    ble_uart_send_cmd("AT+NAME=TEST\r\n");
    
    //初始先关闭从机广播
    close_slave_broadcast();
}

//蓝牙透传接收到数据后的处理函数
void ble_received_data_handler(void)
{
    if(USART1_FRAME_RX_STA)
    {   
        //接收到一帧数据后,就直接发给模拟板
        SendDataToAnBoard(g_Uart1RecvBuf, g_Uart1RecvCount);
        
        USART1_FRAME_RX_STA = 0;
        g_Uart1RecvCount = 0;
    }
}

//检测蓝牙当前状态
uint8_t CheckBleState(void)
{
    if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8) == SET)
    {
        return 0;//断开状态
    }
    else
    {
        return 1;//连接状态
    }
}

注意,这里从机取的蓝牙名称,要在主机的过滤器有效范围内。

补充说明:

这里需要对串口做一些补充。

其实,不管是不是串口,或者其他接收数据的外设,都有一个值得重点注意的问题。

那就是,接收数据时,不要一个一个地去处理,而是必须先将其存储在一个缓存中,然后需要的时候再去缓存里拿数据进行处理转发等操作。

为什么?因为底层数据接收的速度非常快,而通常数据处理的速度就慢得多,慢的操作绝对无法跟上快的操作,所以必定导致一种现象:数据来得太快,我拿数据处理时,当前数据还没处理完,就已经过去好多数据没被接收到,这样,就会漏数据。而且,可能导致数据位错乱,导致拿到的数据是乱码。

可以看到,上面单次处理的方式,在第四次处理时,你以为你处理的只是第4个点的数据,其实,可能已经过去成百上千个数据了,如果用一个变量来接收,那早就被覆盖了。

所以,必须先缓存下来,然后需要的时候去处理

注意,我这里没有说建议,而是必须,因为如果不这么做的话,数据就不对。

还有一个问题就是,很多时候,我们都必须知道接收了多少字节的数据,这样才方便处理,如果接收的是定长数据就比较好办,但如果是不定长数据就比较麻烦。之前提到过一种串口空闲中断+DMA的方式,因为DMA提供了一个函数,可以间接算出接收了多少字节。但是如果不用DMA呢?那就可以通过串口接收中断+空闲中断的方式来处理。

举例说明

这里假如接收到一帧5个字节的数据,那么,接收中断就会进入5次,在第5次接收中断之后,就会出现一个空闲中断,此时,就不会再进入接收中断,而是空闲中断,这样,就能知道到底接收了多少个字节的数据。

这一点非常非常重要。

可以参考这篇文章:STM32使用串口IDLE中断的两种接收不定长数据的方式

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CC2640R2F是一款广受欢迎的低功耗无线芯片,具有强大的性能和灵活的应用能力。下面是关于CC2640R2F的入门介绍。 CC2640R2F是德州仪器公司(Texas Instruments)推出的一款专为低功耗无线通信设计的芯片。它采用了ARM Cortex-M3内核,运行频率高达48MHz,内部集成了256KB的闪存和8KB的SRAM,功能强大。 CC2640R2F支持多种无线通信标准,包括蓝牙低功耗(Bluetooth Low Energy,BLE)和蓝牙5.2。它具有优异的射频性能和低功耗特性,可以实现长达几年的电池寿命。此外,CC2640R2F还具有良好的抗干扰能力和可信任的安全性能,可以满足不同应用场景的需求。 对于初学者来说,了解CC2640R2F的入门方法可以从以下几个方面入手: 1. 学习基础知识:首先,了解CC2640R2F的硬件结构和功能特性。可以查阅相关的技术手册和参考资料,深入了解芯片的主要组成部分和功能模块。 2. 硬件开发环境:为了开始使用CC2640R2F,需要准备相应的硬件开发环境。可以购买开发板或者评估板,或者自行设计底板并搭建相应的开发环境。 3. 软件开发环境:CC2640R2F的软件开发可以使用德州仪器公司提供的开发工具,如Code Composer Studio(CCS)或IAR嵌入式工具链。熟悉使用这些开发工具,可以编写并调试CC2640R2F的应用程序。 4. 学习编程:CC2640R2F的编程可以使用C语言或者基于C语言的工具。学习编程语言的基础知识,并深入了解CC2640R2F的编程接口和开发流程,可以帮助快速入门。 5. 示例和实践:德州仪器公司提供了丰富的示例代码和应用案例,可以帮助初学者更好地理解和应用CC2640R2F。通过参考这些示例,可以逐步掌握CC2640R2F的使用方法和开发技巧。 总之,CC2640R2F是一款功能强大的低功耗无线芯片,适用于各种物联网和物联网应用。初学者可以通过学习基础知识、准备开发环境、学习编程和实践等途径,快速入门并使用CC2640R2F进行开发。 ### 回答2: CC2640R2F是一款蓝牙低能耗无线芯片,具备较高的性能和低功耗的特点,适用于物联网和其他无线通信应用领域。以下是CC2640R2F的入门指南。 首先,要开始使用CC2640R2F芯片,您需要准备以下工具和材料:一个CC2640R2F开发板,JTAG调试器,用于编程的软件(如Code Composer Studio)和USB数据线。 第二步,将CC2640R2F开发板通过USB数据线连接到电脑上,并打开Code Composer Studio软件。在软件中,您可以选择使用现有的示例代码来帮助您进行快速原型开发,或者根据自己的需求进行定制开发。 第三步,使用JTAG调试器将CC2640R2F芯片与计算机连接。通过调试器,您可以在开发板上进行固件的编程和调试。在Code Composer Studio中,您可以选择下载、调试和单步执行程序。 第四步,开始开发您的应用程序。CC2640R2F支持多种通信协议,如蓝牙低能耗、Zigbee和Thread。您可以选择相应的协议,并利用CC2640R2F的特性进行开发。为了更好地了解CC2640R2F的使用和开发,可以参考官方提供的技术文档和开发板用户手册。 第五步,测试和调试您的应用程序。一旦开发完成,您可以将程序下载到CC2640R2F芯片上,并在开发板上进行测试和调试。可以利用开发板上的各种接口和传感器来验证您的应用程序的功能和性能。 最后,当您满意自己的应用程序并通过测试后,您可以考虑将CC2640R2F芯片集成到您的最终产品中。在进行产品化开发时,您需要考虑一些额外的因素,如电源管理、射频设计、外围电路设计等。 综上所述,CC2640R2F是一款功能强大且易于使用的蓝牙低能耗无线芯片,入门操作包括准备工具和材料、连接和配置开发板、开始开发应用程序、测试和调试,最终将芯片集成到您的产品中。通过深入学习和实践,您将能够灵活利用CC2640R2F芯片开发出适用于物联网和其他无线通信应用的创新解决方案。 ### 回答3: CC2640R2F是德州仪器(TI)公司推出的一款低功耗蓝牙(Bluetooth)无线通信芯片,它适用于物联网、智能家居、健康监测和可穿戴设备等领域。对于初学者来说,要入门CC2640R2F,首先需要了解它的主要特点和基本用法。 CC2640R2F采用了TI的BLE-Stack协议栈,支持标准的蓝牙5.2版本,并具有双模功能,即支持BLE和蓝牙经典模式。这意味着它不仅可以与其他BLE设备进行通信,还可以与传统的蓝牙设备兼容。此外,它具有很低的功耗和较长的电池寿命,非常适合低功耗需求的应用。 要入门CC2640R2F,可以首先了解其硬件和开发工具。CC2640R2F芯片提供了丰富的外设接口包括GPIO、SPI、UART和I2C等,可以与其他外部设备进行通信。TI也提供了相关的开发板和开发工具链,如CC2640R2-LAUNCHXL开发板和Code Composer Studio软件,供开发者进行软硬件开发和调试。 接下来,可以学习CC2640R2F的软件编程。TI提供了BLE-Stack软件包,其中包含一些示例代码和应用程序,帮助初学者快速上手。开发者可以使用C编程语言,基于BLE-Stack进行开发,实现蓝牙通信、数据传输和设备控制等功能。 另外,可以学习CC2640R2F的相关文档和参考资料,包括官方文档、用户指南和应用笔记等。通过阅读这些材料,可以更深入地了解CC2640R2F的功能和用法,并掌握开发和调试技巧。 总之,要入门CC2640R2F,需要了解其硬件特性和开发工具,学习软件编程和相关文档。随着不断的学习和实践,可以逐渐掌握CC2640R2F的开发和应用,从而在物联网和蓝牙通信领域取得更好的成果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值