zoukankan      html  css  js  c++  java
  • CC2540-BLE4.0 学历笔记1之串口体验

      PS:这篇文章记录笔者TI ble协议栈的学习串口的笔记。欢迎各位评论讨论,也希望有大牛解答文末的问题。

      前些日子CC2540模块没到,就捣鼓CC2530。深深的感受到,ZigBee就是个坑啊。然后果断玩BLE了。BLE,TI的栈给的文档,project这回看起来好点,然后找了其他一些资料。这里介绍《蓝牙4.0BLE开发完全手册-物联网开发技术实战》。看起来还行吧。不过我照着他的串口例子做,没看到效果(可能是协议栈版本问题)。于是,一怒之下,自己啃。

      最后再说一下,CC2530和CC2540除了RF不同外,51内核是一样的。因为栈中使用的HAL是一样的。

      说下自己的装备。如下图。手焊跳线o(∩_∩)o。主要可以用的IO有串口0,定时器1的通道0~3,定时器的IO映射到了位置2。和两个按键。

      先来看看HAL都给了啥。我个人认为key、led、lcd就是多余的。这个硬件相关性实在是太强了。所以先从串口开始看起,我想各位看官的串口也都在位置1吧。

    HAL里面默认串口使用的DMA。这个就不管它了。我建议先简单的看下APP Group下面的几个c文件。和OSAL.C中的osal_init_system和osal_run_system两个函数,其它最好也浏览一下。在开始写我们自己的串口函数前先看看项目的配置情况。请注意下,函数中用很多预编译,看的时候仔细点。

    左上角,选择CC2540,关掉POWER_SAVING,在defined symbols中的POWER_SAVING前面加个x就可以了。关于POWER_SAVING,在函数osal_run_system中可以看到,这里我们x掉,不然编译会出现一个警告,说什么串口和key的中断被重复的啥啥啥的。至于LCD,因为我的板是没用LCD的干脆也x了。

      现在开始来看看怎么来串口打印出信息来。找到SimpleBLEPeripheral.c中的SimpleBLEPeripheral_Init函数,添加如下代码,注意{}中才是我添加的。另外要添加hal_uart.h这个头文件。

     1 void SimpleBLEPeripheral_Init( uint8 task_id )
     2 {
     3   simpleBLEPeripheral_TaskID = task_id;
     4 
     5     {    //add
     6         halUARTCfg_t halUARTCfg;
     7         halUARTCfg.configured            =    TRUE;
     8         halUARTCfg.baudRate                = HAL_UART_BR_115200;
     9         halUARTCfg.flowControl        =    HAL_UART_FLOW_OFF;
    10         
    11         HalUARTOpen(HAL_UART_PORT_0, &halUARTCfg);
    12         HalUARTWrite(HAL_UART_PORT_0, "Hello CC2540!
    ", 14);
    13     }
    添加串口

    来看看串口配置这个结构体。注意到,这个结构体是没有关于配置停止位,校验位的。也就是全是默认。其他没用到的先不理会是用来干嘛的。

     1 typedef struct
     2 {
     3   bool                configured;
     4   uint8               baudRate;
     5   bool                flowControl;
     6   uint16              flowControlThreshold;
     7   uint8               idleTimeout;
     8   halUARTBufControl_t rx;
     9   halUARTBufControl_t tx;
    10   bool                intEnable;
    11   uint32              rxChRvdTime;
    12   halUARTCBack_t      callBackFunc;    //回调函数
    13 }halUARTCfg_t;
    halUARTCfg_t

    顺便吐槽一下,TI给的HAL api文档里面关于串口的宏定义有错,所以还是看源码靠谱点。

    到这里,编译烧录,应该就可以看到串口出来的信息了。附图,注意一下右边的配置情况。


    华丽的分割线


       上面讲了一下,如何使用Hal给的API来调用串口。也实现了串口信息打印功能。但这并不具有实际意义。在OSAL中,会对系统中的各种事件进行扫描,若事件发生,则会回调相应的函数去执行对应的功能。比如串口接收到信息。笔者尝试着halUARTCfg_t结构体中的callBackFunc成员赋予回调函数。并使用HAL的串口API来实现这个函数——发送串口接收到的内容。

     1 //类似于这样子
     2 
     3 halUARTCfg_t a
     4 
     5 a.callBackFunc = funcA
     6 
     7 
     8 static void funcA (uint8 port, uint8 event)
     9 {
    10     HalUARTRead(, , );
    11     HalUARTWrite(, ,);
    12 }

    上面是省略了的形式,但有个很怪的问题。就是串口接收一次数据后,这个回调函数就一直被调用,一直打印数据出来。经过各种尝试之后也没找出个所以然。可能是对整个协议栈的了解太少了。折腾了一个下午后,使用了npi.c提供的API函数。npi是Network Processor Interface的简称。

      来看看npi里面到底都是些什么

     1 //初始化串口配置
     2 void NPI_InitTransport( npiCBack_t npiCBack )
     3 {
     4   halUARTCfg_t uartConfig;
     5 
     6   // configure UART
     7   uartConfig.configured           = TRUE;
     8   uartConfig.baudRate             = NPI_UART_BR;
     9   uartConfig.flowControl          = NPI_UART_FC;
    10   uartConfig.flowControlThreshold = NPI_UART_FC_THRESHOLD;
    11   uartConfig.rx.maxBufSize        = NPI_UART_RX_BUF_SIZE;
    12   uartConfig.tx.maxBufSize        = NPI_UART_TX_BUF_SIZE;
    13   uartConfig.idleTimeout          = NPI_UART_IDLE_TIMEOUT;
    14   uartConfig.intEnable            = NPI_UART_INT_ENABLE;
    15   uartConfig.callBackFunc         = (halUARTCBack_t)npiCBack;
    16 
    17   // start UART
    18   // Note: Assumes no issue opening UART port.
    19   (void)HalUARTOpen( NPI_UART_PORT, &uartConfig );
    20 
    21   return;
    22 }
    23 
    24 //读数据
    25 uint16 NPI_ReadTransport( uint8 *buf, uint16 len )
    26 {
    27   return( HalUARTRead( NPI_UART_PORT, buf, len ) );
    28 }
    29 
    30 //写数据
    31 uint16 NPI_WriteTransport( uint8 *buf, uint16 len )
    32 {
    33   return( HalUARTWrite( NPI_UART_PORT, buf, len ) );
    34 }
    35 
    36 //长度R
    37 uint16 NPI_RxBufLen( void )
    38 {
    39   return( Hal_UART_RxBufLen( NPI_UART_PORT ) );
    40 }
    41 
    42 //R缓冲区大小
    43 uint16 NPI_GetMaxRxBufSize( void )
    44 {
    45   return( NPI_UART_RX_BUF_SIZE );
    46 }
    47 
    48 //T缓冲区大小
    49 uint16 NPI_GetMaxTxBufSize( void )
    50 {
    51   return( NPI_UART_TX_BUF_SIZE );
    52 }
     1 #ifndef NPI_H
     2 #define NPI_H
     3 
     4 #ifdef __cplusplus
     5 extern "C"
     6 {
     7 #endif
     8 
     9 /*******************************************************************************
    10  * INCLUDES
    11  */
    12 
    13 #include "hal_types.h"
    14 #include "hal_board.h"
    15 #include "hal_uart.h"
    16 
    17 /*******************************************************************************
    18  * MACROS
    19  */
    20 
    21 /*******************************************************************************
    22  * CONSTANTS
    23  */
    24 
    25 /* UART port */
    26 #if !defined NPI_UART_PORT
    27 #if ((defined HAL_UART_SPI) && (HAL_UART_SPI != 0))
    28 #define NPI_UART_PORT                  HAL_UART_PORT_1
    29 #else
    30 #define NPI_UART_PORT                  HAL_UART_PORT_0
    31 #endif
    32 #endif
    33 
    34 #if !defined( NPI_UART_FC )
    35 #define NPI_UART_FC                    FALSE    //add ->true
    36 #endif // !NPI_UART_FC
    37 
    38 #define NPI_UART_FC_THRESHOLD          48
    39 #define NPI_UART_RX_BUF_SIZE           128
    40 #define NPI_UART_TX_BUF_SIZE           128
    41 #define NPI_UART_IDLE_TIMEOUT          6
    42 #define NPI_UART_INT_ENABLE            TRUE
    43 
    44 #if !defined( NPI_UART_BR )
    45 #define NPI_UART_BR                    HAL_UART_BR_115200
    46 #endif // !NPI_UART_BR
    47 
    48 /*******************************************************************************
    49  * TYPEDEFS
    50  */
    51 
    52 typedef void (*npiCBack_t) ( uint8 port, uint8 event );
    53 
    54 //
    55 // Network Processor Interface APIs
    56 //
    57 
    58 extern void   NPI_InitTransport( npiCBack_t npiCBack );
    59 extern uint16 NPI_ReadTransport( uint8 *buf, uint16 len );
    60 extern uint16 NPI_WriteTransport( uint8 *, uint16 );
    61 extern uint16 NPI_RxBufLen( void );
    62 extern uint16 NPI_GetMaxRxBufSize( void );
    63 extern uint16 NPI_GetMaxTxBufSize( void );
    64 
    65 /*******************************************************************************
    66 */
    67 
    68 #ifdef __cplusplus
    69 }
    70 #endif
    71 
    72 #endif /* NPI_H */

    可以看出来,npi就是对Hal中的串口API做了一层封装。

    之后SimpleBLEPeripheral_Init函数

    1 void SimpleBLEPeripheral_Init( uint8 task_id )
    2 {
    3   simpleBLEPeripheral_TaskID = task_id;
    4 
    5     {    //add
    6         NPI_InitTransport(UartEventChange);    //Network Processor Interface 初始化
    7     }
    8 ………… //省略
    9

    添加UartEventChange回调函数

     1 static void UartEventChange(uint8 port, uint8 event)    //add
     2 {
     3     VOID    port;
     4     uint8 temp;
     5 
     6     if(event & HAL_UART_RX_TIMEOUT)    //接收完成事件
     7     {
     8         temp = NPI_RxBufLen();
     9         if(temp)
    10         {
    11             NPI_ReadTransport(uartbuf, temp);
    12             NPI_WriteTransport(uartbuf, temp);
    13             osal_memset(uartbuf, 0, sizeof(uartbuf));
    14         }
    15     }
    16 }

    对SimpleBLEPeripheral.c文件做上面的修改,然后编译、烧录,就可以看到想要的现象了。CC2540在接收完串口信息后,返回接收到的内容。仅返回一次。而不像使用Hal的串口API那样,接收到之后就一直发送不停。

      注意要关闭串口的流控制和power saving

      尽管通过npi实现了串口的收发。但还是有些问题没搞懂。

     1 /*
     2  *
     3  *1、为何使用Hal中的串口api就无法产生上述效果。是我那些地方没有注意
     4  *到了吗??
     5  *
     6  *2、系统是如何知道串口接收完毕的。在调试过程中发现,串口事件有是有
     7  *定时器的。真的吗?
     8  *
     9  *3、默认使用了DMA,那这个缓冲区在那里,文件中并没有声明出来这个数
    10  *组,只声明了DMA的大小。东西到底存哪里去了。
    11  *
    12  *4、系统的事件到底是怎么运作的?
    13  *
    14  *……
    15  *
    16  */

    先记录下这些问题。等熟悉了BLE栈之后在慢慢找答案。一开始就纠结这些问题的话,可能到头来就啥都没搞懂了。

  • 相关阅读:
    转:孙振耀谈人生(推荐)
    自绘按钮的实现
    数据结构知识
    Direct Show采集图像实例
    视觉跟踪
    改变对话框控件的颜色
    笔试题
    CBitmapButton的使用
    Rotor (SSCLI) 2.0 登场!
    Under the hood: 从Win32 SEH到CLI异常处理模型
  • 原文地址:https://www.cnblogs.com/xiemm/p/3902942.html
Copyright © 2011-2022 走看看