CC2540/CC2541/CC254x之可变参数串口打印配置

来源:互联网 发布:htc手机数据连接不上 编辑:程序博客网 时间:2024/06/08 14:17

测试环境:


协议栈版本:BLE-CC254x-1.4.0

开发环境IAR版本:IAR 8.20

硬件设备:CC2540/CC2541开发板

测试Demo工程:simpleBLEPeripheral工程

串口工具:SecureCRT




可变参数函数的使用技巧


在C语言中,使用 printf() 进行格式化输出非常方便,例如,使用 printf(“%d\n”,a) 可将a的值以十进制格式输出,然后换行。printf() 的函数原型为:

int printf(const char *format, ...);

函数参数中的...表示可变参数,即参数的个数是可变的,例如函数printf(“%d %d”,a,b)中有两个参数a和b,这种参数个数不确定的函数就称为可变参数函数。可变参数函数示例如下:

Void Printf(const char* fmt,...){va_list ap;char string[50];va_start(ap,fmt);vsprintf(string,fmt,ap);va_end(ap);Uart_Print(string,strlen(string));}

第3行,定义了一个指向可变参数列表的指针。

第4行,自定义一个数组,用来存放格式化后的数据。

第5行,将第一个可变参数的地址赋给ap指针,即ap指针指向可变参数列表的开始。fmt是最后一个固定参数。例如,若函数声明是void va_test(char a,char b,char c,...),则它的固定参数依次为a,b,c,最后一个固定参数为c,此时,就要写为va_start(ap,c);

第6行,vsprintf()的函数原型:

int vsprintf(char *string, char *format, va_list param);
其作用是将param 按格式format写入字符串string中。

第7行,清空参数列表,将参数指针ap置为无效。该的作用是结束可变参数的获取。

第8行,将string数组中的数据输出到串口。不同的系统该接口可能不一样,要调用系统串口输出函数才行。


上述函数的基本流程是:

1.开辟一块存储区域用来存储可变参数。

2.调用vsprintf函数将可变参数按照指定的格式复制到一个数组中。

3.调用系统串口输出函数Uart_Printf(),将该数组中的数据输出到串口。




配置可变参数打印函数


下面我们在TI的CC2540/CC2541的simpleBLEPeripheral工程中配置可变参数的打印函数:


1.关闭串口流控制

Projects\ble\common\npi\npi_np\npi.h文件中做如下修改:

#if !defined( NPI_UART_FC )#define NPI_UART_FC                    FALSE//TRUE#endif // !NPI_UART_FC

另外,该文件也定义了串口初始化接口中的其他一些宏,如果需要修改成其他值,可以在这个文件中直接修改。


2.修改配置,使能串口功能

TI协议栈中的示例虽然提供了串口uart封装的文件,但是默认情况下是没有使能的,所以需要修改配置文件,打开串口使能。

 

右键工程名,选择Options..--->C/C++ Compiler--->PreprocessorDefined symbols中添加宏定义:

HAL_UART=TRUE

我们的硬件设计上采用的是uart1,所以还需要定义切换到uart1上。继续添加如下宏定义:

ZAPP_P2=TRUE

当然如果采用的是uart0,只需要将上面的宏定义改为ZAPP_P1=TRUE即可。


3.添加可变参数打印接口

Projects\ble\common\npi\npi_np\npi.c文件的最前面添加如下头文件引用:

#include "OSAL.h"#include <stdarg.h>#include <stdio.h>

接口源码如下:

/*************************************************格式化输出函数,可变参数***********************************************************/void NPI_PrintValue(const char* fmt,...){#ifdef DEBUG_PRINTva_list ap;uint8 buffer[100];uint16 len;va_start(ap,fmt);len = vsprintf((char *)buffer,fmt,ap);va_end(ap);NPI_WriteTransport(buffer,len);//NPI_WriteTransport("\r\n",osal_strlen("\r\n"));#elsereturn;//屏蔽串口打印输出#endif}

上面我们自定义了DEBUG_PRINT宏进行控制,所以相应的,配置文件中需要定义此宏:

右键工程名,选择Options..--->C/C++ Compiler--->PreprocessorDefined symbols中添加宏定义:

DEBUG_PRINT=TRUE

这样,我们就可以通过配置该宏为TRUE或者FALSE来打开或者关闭打印。


4.头文件中声明打印接口,便于使用

Projects\ble\common\npi\npi_np\npi.h文件中添加如下声明和重定义:

/*************************************************格式化输出函数,可变参数*************************************************/extern void NPI_PrintValue(const char* fmt,...);#define tx_printf NPI_PrintValue

这样,我们就可以在引用了Npi.h头文件的文件中使用tx_printf来进行串口可变参数打印输出了。


5.应用初始化函数中对串口进行初始化

引用相应的头文件:

#include "Npi.h"

Projects\ble\SimpleBLEPeripheral\Source\simpleBLEPeripheral.c应用文件中的SimpleBLEPeripheral_Init初始化方法里调用串口初始化接口:

// 串口初始化NPI_InitTransport(NULL);

接下来,我们顺便来看看这个串口初始化的具体操作,源码及注释如下:

/******************************************************************************** @fn          NPI_InitTransport** @brief       This routine initializes the transport layer and opens the port*              of the device. Note that based on project defines, either the*              UART, USB (CDC), or SPI driver can be used.** input parameters** @param       npiCback - User callback function when data is available.** output parameters** @param       None.** @return      None.*/void NPI_InitTransport( npiCBack_t npiCBack ){    halUARTCfg_t uartConfig;    // configure UART    uartConfig.configured           = TRUE;      //波特率,此处设置115200    uartConfig.baudRate             = NPI_UART_BR;    //流控制    uartConfig.flowControl          = NPI_UART_FC;    //流控制阀值,当开启flowControl时,该值有效    uartConfig.flowControlThreshold = NPI_UART_FC_THRESHOLD;    //uart接收缓冲区大小    uartConfig.rx.maxBufSize        = NPI_UART_RX_BUF_SIZE;    //uart发送缓冲区大小    uartConfig.tx.maxBufSize        = NPI_UART_TX_BUF_SIZE;    //空闲时间    uartConfig.idleTimeout          = NPI_UART_IDLE_TIMEOUT;    //是否开启中断    uartConfig.intEnable            = NPI_UART_INT_ENABLE;    //uart接收回调函数,该函数中读取可用数据    uartConfig.callBackFunc         = (halUARTCBack_t)npiCBack;    // start UART    // Note: Assumes no issue opening UART port.    // 打开相应uart端口,并将配置信息传进去    (void)HalUARTOpen( NPI_UART_PORT, &uartConfig );    return;}

注释非常详细了,我们就不再说明了。

 

通过上述配置之后,我们来实际测试一下我们配置的接口,在测试过程中,可能出现问题,接下来说明一下我在配置之后碰到的问题以及解决方法:

 

1.打印的时候偶尔出现丢数据或者乱码的问题

右键工程名,选择Options..--->C/C++ Compiler--->PreprocessorDefined symbolsPOWER_SAVING宏关闭,操作如下:

xPOWER_SAVING

此宏涉及低功耗控制,如果要开启睡眠模式,还是要打开此宏,开启睡眠模式之后,串口将无法正常使用。


2.打印的时候在输出的字符串前面出现横杠

调用我们配置的打印函数的源码如下:

tx_printf("SimpleBLEPeripheral_Init");

现象截图:



正常情况下应该只打印出SimpleBLEPeripheral_Init”,但是前面多出来一部分,此问题的修改方法:

不使用LCD的时候,不能用如下截图中的方法去掉相应的宏,必须将宏定义成FALSE,即:



上面截图的修改就会导致问题,因为在hal_board_cfg.h文件中有如下代码:

/* Set to TRUE enable LCD usage, FALSE disable it */#ifndef HAL_LCD#define HAL_LCD TRUE#endif

也就是你在配置中没有定义HAL_LCD宏的时候将该宏在代码中定义为TRUE。所以如果直接删掉或者前面加x就意味着HAL_LCD的宏没有定义,程序编译的时候会在上述文件中进行定义,所以此宏如果要屏掉,必须用下面的方式:



HAL_LCD=FALSE这样配置。如果你的项目需要LCD,那就要查找另外的解决方法了。





0 0
原创粉丝点击