【CC2640R2F】香瓜CC2640R2F之串口

本文最后修改时间: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】香瓜CC2640R2F之串口_第1张图片

【CC2640R2F】香瓜CC2640R2F之串口_第2张图片

上图可知:

串口引脚 香瓜CC2640R2F开发板引脚
TXD DIO_2
RXD DIO_3

2、开发板对应位置

【CC2640R2F】香瓜CC2640R2F之串口_第3张图片

需将拨码开关的右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);
}

“启动串口局部返回功能”是为了能在串口接收到数据时及时进回调函数。如果没有这条语句,将会在缓冲区满时才进入。


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:        [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文件夹下

【CC2640R2F】香瓜CC2640R2F之串口_第4张图片

添加文件过程中,选项选择如下

【CC2640R2F】香瓜CC2640R2F之串口_第5张图片

【CC2640R2F】香瓜CC2640R2F之串口_第6张图片


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

②添加串口处理事件的处理(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:        [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函数中做处理。


添加串口回调函数的声明和串口处理函数的声明(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、配置中的预编译修改

【CC2640R2F】香瓜CC2640R2F之串口_第7张图片

修改预编译宏为上图红框所示。

注:改动之前协议栈的串口宏是打开的,但与香瓜使用的串口方式是冲突的,因此需要关闭。


八、注意事项

1、实测如果直接在串口回调函数中做处理,会导致“收发一段时间后无法发出数据”的现象。


九、实验结果

用USB数据线将香瓜CC2640R2F开发板与电脑USB接口连接,打开电脑端的串口调试工具。

仿真并全速运行,然后电脑端发送“大家好,我是甜甜的大香瓜。大家好,我是甜甜的大香瓜。”,再分别按下香瓜CC2640R2F开发板上的5个多向按键。串口调试工具显示如下:

【CC2640R2F】香瓜CC2640R2F之串口_第8张图片

其中,红框的为上电后收到,蓝框的为电脑端发出数据后接收到的,黄框为按下按键后接收到的。

因此,实验成功。




你可能感兴趣的:(BLE-CC2640R2F)