本文最后修改时间:2021年09月09日 10:36
一、本节简介
本节以simple_peripheral工程为例,介绍如何使用串口。
二、实验平台
1)CC2640R2F平台
①协议栈版本:CC2640R2 SDK v1.40.00.45
②编译软件:CCS7.3.0.00019
③硬件平台:香瓜CC2640R2F开发板
④仿真器:香瓜XDS100V3下载器
2)PC端平台
①串口调试工具:SSCOM3.2
三、版权声明
1)作者:甜甜的大香瓜
2)声明:喝水不忘挖井人,转载请注明出处。
3)纠错/业务合作:897503845@qq.com
4)香瓜BLE之CC2640R2F群:557278427
5)本文出处:原创连载资料《简单粗暴学蓝牙5》
6)完整开源资料下载地址(电脑端打开):
7)香瓜CC2640R2F开发板购买链接:
https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4023-16963296339.8.21bfc58419sWKt&id=558653143169
四、实验前提
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》。
3)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之自定义按键》。
4)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之自定义周期事件(从机)》。
5)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之有源蜂鸣器》。
6)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之LCD》。
五、基础知识
暂无
六、硬件原理
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: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: //shop: opengua.taobao.com //changetime: 2021.09.09 //********************************************************************** #include <xdc/runtime/Assert.h> #include <xdc/runtime/Types.h> #include <xdc/runtime/Log.h> #include <ti/sysbios/BIOS.h> #include "board.h" #include <ti/drivers/power/PowerCC26XX.h> #include <ti/drivers/UART.h> #include <ti/drivers/uart/UARTCC26XX.h> #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: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: opengua.taobao.com //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: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: opengua.taobao.com //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: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: opengua.taobao.com //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_Hex_To_Str //introduce: 香瓜十六进制转字符串,默认最多25字节转50个字符串数据 //parameter: pGUA_Hex:十六进制数据首地址; // nGUA_Len:十六进制数据长度 //return: 转换好的字符串数据,默认最多50个字符 //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: opengua.taobao.com //changetime: 2021.09.09 //********************************************************************** char *GUA_Hex_To_Str(GUA_U8 *pGUA_Hex, GUA_U8 nGUA_Len) { char nGUA_Hex[] = "0123456789ABCDEF"; static char aGUA_str[50]; char *pGUA_Str = aGUA_str; for (GUA_U8 i = 0; i < nGUA_Len; i++) { *pGUA_Str++ = nGUA_Hex[*pGUA_Hex >> 4]; *pGUA_Str++ = nGUA_Hex[*pGUA_Hex++ & 0x0F]; } return aGUA_str; } |
“启动串口局部返回功能”是为了能在串口接收到数据时及时进回调函数。如果没有这条语句,将会在缓冲区满时才进入。
2)写一个串口驱动头文件GUA_UART.h(存放在“……
\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA“路径下)
//********************************************************************** //name: GUA_UART.h //introduce: 香瓜的串口驱动头的文件 //author: 甜甜的大香瓜 //email: 897503845@qq.com //QQ group: 香瓜BLE之CC2640R2F(557278427) //shop: opengua.taobao.com //changetime: 2021.09.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); extern char *GUA_Hex_To_Str(GUA_U8 *pGUA_Hex, GUA_U8 nGUA_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); //串口十六进制转字符串示例 uint8 nGUA_Temp = 0x31; GUA_UART_Send("GUA Age:", 8); GUA_UART_Send((uint8 *)(GUA_Hex_To_Str(&nGUA_Temp, 1)), 2); GUA_UART_Send("\r\n", 2); uint8 aGUA_Buf[6] = {0x12, 0x34, 0x56, 0x78, 0x90, 0x12}; GUA_UART_Send("GUA Tel:", 8); GUA_UART_Send((uint8 *)(GUA_Hex_To_Str(&aGUA_Buf, 6)), 11); GUA_UART_Send("\r\n", 2); //串口处理定时器初始化 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: 897503845@qq.com //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 |
②添加串口处理事件的处理(simple_peripheral.c的SimpleBLEPeripheral_taskFxn中)
//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: 897503845@qq.com //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: 897503845@qq.com //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函数中做处理。
②添加串口回调函数的声明和串口处理函数的声明(simple_peripheral.c中)
//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 |
4、配置中的预编译修改
修改预编译宏为上图红框所示(要一样)。
注:改动之前协议栈的串口宏是打开的,但与香瓜使用的串口方式是冲突的,因此需要关闭。
八、注意事项
1、实测如果直接在串口回调函数中做处理,会导致“收发一段时间后无法发出数据”的现象。
2、主机端添加串口时,下图红框处略有不同。
九、实验结果
用USB数据线将香瓜CC2640R2F开发板与电脑USB接口连接,打开电脑端的串口调试工具。
仿真并全速运行,然后电脑端发送“大家好,我是甜甜的大香瓜。大家好,我是甜甜的大香瓜。”,再分别按下香瓜CC2640R2F开发板上的5个多向按键。串口调试工具显示如下:
其中,红框的为上电后收到,蓝框的为电脑端发出数据后接收到的,黄框为按下按键后接收到的。
因此,实验成功。
标签:GUA,UART,CC2640R2F,nGUA,香瓜,串口 From: https://blog.csdn.net/feilusia/article/details/145170687