本文最后修改时间:2017年11月13日 15:00
一、本节简介
本节以simple_peripheral工程为例,介绍如何使用串口。
二、实验平台
1)CC2640R2F平台
①协议栈版本:CC2640R2 SDK v1.40.00.45
②编译软件:CCS7.3.0.00019
③硬件平台:香瓜CC2640R2F开发板
④仿真器:香瓜XDS100V3下载器
2)PC端平台
①串口调试工具:SSCOM3.2
三、版权声明
1)作者:甜甜的大香瓜
2)声明:喝水不忘挖井人,转载请注明出处。
3)纠错/业务合作:[email protected]
4)香瓜BLE之CC2640R2F群:557278427
5)本文出处:原创连载资料《简单粗暴学蓝牙5》
6)完整开源资料下载地址(电脑端打开):
https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
7)香瓜CC2640R2F开发板购买链接:
https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4023-16963296339.8.21bfc58419sWKt&id=558653143169
8)香瓜XDS100V3下载器购买链接:
https://item.taobao.com/item.htm?spm=a230r.1.14.1.1d150040zvJBco&id=558356989143&ns=1&abbucket=6#detail
四、实验前提
1、在进行本文步骤前,请先阅读以下章节:
1)《简单粗暴学蓝牙5》的“第一章至第四章”章节。
2)《UARTCC26XX.h File Reference》:
C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\docs\tidrivers\doxygen\html\_u_a_r_t_c_c26_x_x_8h.html
2、在进行本文步骤前,请先实现以下章节:
1)《简单粗暴学蓝牙5》的“第三章 软件的安装及使用”章节。
2) 《简单粗暴学蓝牙5》的《香瓜CC2640R2F之LED》:http://blog.csdn.net/feilusia/article/details/78087346
3) 《简单粗暴学蓝牙5》的《香瓜CC2640R2F之自定义按键》:http://blog.csdn.net/feilusia/article/details/78239447
4) 《简单粗暴学蓝牙5》的《香瓜CC2640R2F之自定义周期事件》:http://blog.csdn.net/feilusia/article/details/78245788
5) 《简单粗暴学蓝牙5》的《香瓜CC2640R2F之有源蜂鸣器》:http://blog.csdn.net/feilusia/article/details/78144258
6) 《简单粗暴学蓝牙5》的《香瓜CC2640R2F之LCD》:http://blog.csdn.net/feilusia/article/details/78371371
五、基础知识
暂无
六、硬件原理
1、原理图
上图可知:
串口引脚 | 香瓜CC2640R2F开发板引脚 |
TXD | DIO_2 |
RXD | DIO_3 |
2、开发板对应位置
需将拨码开关的右11(TXD)、右12(RXD),共2个按键上拨。
七、实验步骤
1、编写并添加自定义的串口驱动
1)写一个串口驱动GUA_UART.c(存放在“……\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA”路径下)
//**********************************************************************
//name: GUA_UART.c
//introduce: 香瓜的串口驱动
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
#include
#include
#include
#include
#include "board.h"
#include
#include
#include
#include "GUA_Uart.h"
/*********************宏定义************************/
#define GUA_UART_RX IOID_2 //接收引脚
#define GUA_UART_TX IOID_3 //发送引脚
/*********************内部变量************************/
//串口号
typedef enum{
GUA_UART0 = 0,
GUA_UARTCOUNT
}GUA_UARTName;
//流控制所需的配置
const UARTCC26XX_HWAttrsV2 GUA_UART_CC26XXHWAttrs[GUA_UARTCOUNT] = {
{
.baseAddr = UART0_BASE,
.powerMngrId = PowerCC26XX_PERIPH_UART0,
.intNum = INT_UART0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.txPin = GUA_UART_TX,
.rxPin = GUA_UART_RX,
.ctsPin = PIN_UNASSIGNED,
.rtsPin = PIN_UNASSIGNED
}
};
//串口目标
static UARTCC26XX_Object GUA_UART_CC26XXObjects[GUA_UARTCOUNT];
static const UART_Config GUA_UART_Config[GUA_UARTCOUNT] = {
{
.fxnTablePtr = &UARTCC26XX_fxnTable,
.object = &GUA_UART_CC26XXObjects[GUA_UART0],
.hwAttrs = &GUA_UART_CC26XXHWAttrs[GUA_UART0]
},
};
//串口句柄
static UART_Handle stGUA_UART_Handle;
//串口参数
static UART_Params stGUA_UART_Params;
/*********************外部变量************************/
GUA_U8 gaGUA_UART_RxBuf[GUA_UART_MAX_NUM_RX_BYTES] = {0};
GUA_U8 gaGUA_UART_TxBuf[GUA_UART_MAX_NUM_TX_BYTES] = {0};
GUA_U32 gGUA_UART_WantedRxBytes;
GUA_U8 gGUA_UART_Size;
//**********************************************************************
//name: GUA_UART_Init
//introduce: 香瓜串口驱动初始化
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
void GUA_UART_Init(GUA_UART_Callback GUA_UART_ReadCallback)
{
//初始化为默认值
UART_Params_init(&stGUA_UART_Params);
//参数设置
stGUA_UART_Params.baudRate = 115200;
stGUA_UART_Params.writeDataMode = UART_DATA_BINARY;
stGUA_UART_Params.readMode = UART_MODE_CALLBACK;
stGUA_UART_Params.readDataMode = UART_DATA_BINARY;
stGUA_UART_Params.readCallback = GUA_UART_ReadCallback;
//打开串口
stGUA_UART_Handle = GUA_UART_Config[0].fxnTablePtr->openFxn((UART_Handle)&GUA_UART_Config[0], &stGUA_UART_Params);
//启动串口局部返回功能
GUA_UART_Config[0].fxnTablePtr->controlFxn(stGUA_UART_Handle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL);
//开始第一次的读取等待
gGUA_UART_WantedRxBytes = GUA_UART_MAX_NUM_RX_BYTES;
GUA_UART_Receive(gaGUA_UART_RxBuf, gGUA_UART_WantedRxBytes);
}
//**********************************************************************
//name: GUA_UART_Send
//introduce: 香瓜串口的写数据的函数
//parameter: npGUA_UART_TxBuf:写缓冲区
// nGUA_UART_Len:数据长度
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
void GUA_UART_Send(GUA_U8* npGUA_UART_TxBuf, GUA_U8 nGUA_UART_Len)
{
GUA_UART_Config[0].fxnTablePtr->writeFxn(stGUA_UART_Handle, npGUA_UART_TxBuf, nGUA_UART_Len);
}
//**********************************************************************
//name: GUA_UART_Receive
//introduce: 香瓜串口的写数据的函数
//parameter: npGUA_UART_RxBuf:读缓冲区
// nGUA_UART_Len:数据长度
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
void GUA_UART_Receive(GUA_U8* npGUA_UART_RxBuf, GUA_U8 nGUA_UART_Len)
{
GUA_UART_Config[0].fxnTablePtr->readFxn(stGUA_UART_Handle, npGUA_UART_RxBuf, nGUA_UART_Len);
}
“启动串口局部返回功能”是为了能在串口接收到数据时及时进回调函数。如果没有这条语句,将会在缓冲区满时才进入。
//**********************************************************************
//name: GUA_UART.h
//introduce: 香瓜的串口驱动头的文件
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
#ifndef _GUA_UART_H_
#define _GUA_UART_H_
/*********************宏定义************************/
//类型宏
#ifndef GUA_C
typedef char GUA_C;
#endif
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif
#ifndef GUA_8
typedef signed char GUA_8;
#endif
#ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif
#ifndef GUA_16
typedef signed short GUA_16;
#endif
#ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif
#ifndef GUA_32
typedef signed long GUA_32;
#endif
#ifndef GUA_U64
typedef unsigned long long GUA_U64;
#endif
#ifndef GUA_64
typedef signed long long GUA_64;
#endif
//缓冲区数据长度
#define GUA_UART_MAX_NUM_RX_BYTES 60 //最大接收字节
#define GUA_UART_MAX_NUM_TX_BYTES 60 //最大发送字节
/*********************外部变量************************/
extern GUA_U8 gaGUA_UART_RxBuf[GUA_UART_MAX_NUM_RX_BYTES];
extern GUA_U8 gaGUA_UART_TxBuf[GUA_UART_MAX_NUM_TX_BYTES];
extern GUA_U32 gGUA_UART_WantedRxBytes;
extern GUA_U8 gGUA_UART_Size;
/*********************函数声明************************/
typedef void (*GUA_UART_Callback) (UART_Handle nGUA_Handle, void *npGUA_Buf, size_t nGUA_Count);
extern void GUA_UART_Init(GUA_UART_Callback GUA_UART_ReadCallback);
extern void GUA_UART_Send(GUA_U8* npGUA_UART_TxBuf, GUA_U8 nGUA_UART_Len);
extern void GUA_UART_Receive(GUA_U8* npGUA_UART_RxBuf, GUA_U8 nGUA_UART_Len);
#endif
2、工程中添加驱动文件GUA_UART.c和GUA_UART.h
注:拖拽至CCS工程的Application文件夹下
添加文件过程中,选项选择如下
3、应用层调用
1)添加头文件(simple_peripheral.c中)
//GUA
#include "GUA_UART.h"
//GUA
2)添加初始化代码(simple_peripheral.c的SimpleBLEPeripheral_init函数末尾中)
//GUA
//串口初始化
GUA_UART_Init(GUA_UART_ReadCallback);
GUA_UART_Send("opengua\r\n", 9);
GUA_UART_Send("QQ Group:55727827\r\n", 19);
//串口处理定时器初始化
Util_constructClock(&GUA_UART_Clock, SimpleBLEPeripheral_clockHandler,
0, 0, false, SBP_GUA_UART_EVT);
//GUA
初始化时传入应用层的串口回调函数,以便串口接收到数据时能传到应用层中。
3)修改按键处理函数(替换simple_peripheral.c的GUA_HandleKeys函数)
//GUA
//**********************************************************************
//name: GUA_HandleKeys
//introduce: 应用层按键处理函数
//parameter: GUA_Keys:键值
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.04
//**********************************************************************
static void GUA_HandleKeys(uint8 GUA_Keys)
{
//UP按键
if(GUA_Keys & GUA_KEY_UP_VALUE)
{
//LED1亮
GUA_Led_Set(GUA_LED_NO_1, GUA_LED_MODE_ON);
//蜂鸣器响
GUA_Beep_Set(GUA_BEEP_MODE_ON);
//LCD显示
GUA_LCD_WriteString("UP is pressed", GUA_LCD_LINE7);
//串口发送数据
GUA_UART_Send("UP is pressed\r\n", 15);
//启动定时器
Util_startClock(&GUA_periodicClock);
}
//DOWN按键
if(GUA_Keys & GUA_KEY_DOWN_VALUE)
{
//LED2亮
GUA_Led_Set(GUA_LED_NO_2, GUA_LED_MODE_ON);
//蜂鸣器响
GUA_Beep_Set(GUA_BEEP_MODE_ON);
//LCD显示
GUA_LCD_WriteString("DOWN is pressed", GUA_LCD_LINE7);
//串口发送数据
GUA_UART_Send("DOWN is pressed\r\n", 17);
//启动定时器
Util_startClock(&GUA_periodicClock);
}
//LEFT按键
if(GUA_Keys & GUA_KEY_LEFT_VALUE)
{
//LED3亮
GUA_Led_Set(GUA_LED_NO_3, GUA_LED_MODE_ON);
//蜂鸣器响
GUA_Beep_Set(GUA_BEEP_MODE_ON);
//LCD显示
GUA_LCD_WriteString("LEFT is pressed", GUA_LCD_LINE7);
//串口发送数据
GUA_UART_Send("LEFT is pressed\r\n", 17);
//启动定时器
Util_startClock(&GUA_periodicClock);
}
//RIGHT按键
if(GUA_Keys & GUA_KEY_RIGHT_VALUE)
{
//LED4亮
GUA_Led_Set(GUA_LED_NO_4, GUA_LED_MODE_ON);
//蜂鸣器响
GUA_Beep_Set(GUA_BEEP_MODE_ON);
//LCD显示
GUA_LCD_WriteString("RIGHT is pressed", GUA_LCD_LINE7);
//串口发送数据
GUA_UART_Send("RIGHT is pressed\r\n", 18);
//启动定时器
Util_startClock(&GUA_periodicClock);
}
//SELECT按键
if(GUA_Keys & GUA_KEY_SELECT_VALUE)
{
//LED全亮
GUA_Led_Set(GUA_LED_NO_ALL, GUA_LED_MODE_ON);
//蜂鸣器响
GUA_Beep_Set(GUA_BEEP_MODE_ON);
//LCD显示
GUA_LCD_WriteString("SELECT is pressed", GUA_LCD_LINE7);
//串口发送数据
GUA_UART_Send("SELECT is pressed\r\n", 19);
//启动定时器
Util_startClock(&GUA_periodicClock);
}
}
//GUA
每个按键都有对应的串口显示。
4)定义串口处理事件
①修改串口处理事件的宏(simple_peripheral.c中)
将
//GUA
#define SBP_GUA_PERIODIC_EVT Event_Id_02 //香瓜周期事件
#define SBP_GUA_ALL_EVENTS SBP_GUA_PERIODIC_EVT //所有事件的集合
//GUA
修改为
//GUA
#define SBP_GUA_PERIODIC_EVT Event_Id_02 //香瓜周期事件
#define SBP_GUA_UART_EVT Event_Id_03 //香瓜串口处理事件
#define SBP_GUA_ALL_EVENTS SBP_GUA_PERIODIC_EVT | SBP_GUA_UART_EVT //所有事件的集合
//GUA
//GUA
//香瓜串口处理事件
if (events & SBP_GUA_UART_EVT)
{
//再次启动定时器
//Util_startClock(&GUA_periodicClock);
//香瓜串口处理函数
GUA_UART_PerformTask();
}
//GUA
5)定义定时器结构体数据(simple_peripheral.c中)
//GUA
static Clock_Struct GUA_UART_Clock;
//GUA
6)添加串口回调函数和串口事件处理函数
①添加串口回调函数和串口事件处理函数(simple_peripheral.c中)
//GUA
//**********************************************************************
//name: GUA_UART_ReadCallback
//introduce: 香瓜串口的读数据的回调函数
//parameter: nGUA_UART_Handle:句柄
// npGUA_UART_RxBuf:接收缓冲区
// nGUA_UART_Size:接收的数据大小
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
static void GUA_UART_ReadCallback(UART_Handle nGUA_UART_Handle, void *npGUA_UART_RxBuf, size_t nGUA_UART_Size)
{
//保存数据
gGUA_UART_Size = nGUA_UART_Size;
memcpy(gaGUA_UART_RxBuf, npGUA_UART_RxBuf, gGUA_UART_Size);
//启动定时器
Util_startClock(&GUA_UART_Clock);
}
//**********************************************************************
//name: GUA_UART_PerformTask
//introduce: 香瓜串口事件的处理函数
//parameter: none
//return: none
//author: 甜甜的大香瓜
//email: [email protected]
//QQ group: 香瓜BLE之CC2640R2F(557278427)
//shop:
//https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
//changetime: 2017.11.09
//**********************************************************************
static void GUA_UART_PerformTask(void)
{
//发送数据
GUA_UART_Send(gaGUA_UART_RxBuf, gGUA_UART_Size);
//开始新一次的读取等待
GUA_UART_Receive(gaGUA_UART_RxBuf, gGUA_UART_WantedRxBytes);
}
//GUA
串口接收到数据后,会从底层发送数据到应用层的回调函数GUA_UART_ReadCallback中。
在回调函数GUA_UART_ReadCallback中保存数据、启动串口处理事件的定时器。
随后会在GUA_UART_PerformTask函数中做处理。
//GUA
static void GUA_UART_ReadCallback(UART_Handle nGUA_UART_Handle, void *npGUA_UART_RxBuf, size_t nGUA_UART_Size);
static void GUA_UART_PerformTask(void);
//GUA
修改预编译宏为上图红框所示。
注:改动之前协议栈的串口宏是打开的,但与香瓜使用的串口方式是冲突的,因此需要关闭。
八、注意事项
1、实测如果直接在串口回调函数中做处理,会导致“收发一段时间后无法发出数据”的现象。
九、实验结果
用USB数据线将香瓜CC2640R2F开发板与电脑USB接口连接,打开电脑端的串口调试工具。
仿真并全速运行,然后电脑端发送“大家好,我是甜甜的大香瓜。大家好,我是甜甜的大香瓜。”,再分别按下香瓜CC2640R2F开发板上的5个多向按键。串口调试工具显示如下:
其中,红框的为上电后收到,蓝框的为电脑端发出数据后接收到的,黄框为按下按键后接收到的。
因此,实验成功。