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”--->“Preprocessor”在“Defined 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”--->“Preprocessor”在“Defined 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”--->“Preprocessor”在“Defined symbols”将“POWER_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,那就要查找另外的解决方法了。
- CC2540/CC2541/CC254x之可变参数串口打印配置
- CC2540/CC2541/CC254x之OSAL消息队列
- CC2540/CC2541/CC254x之硬件抽象层
- CC254x简介-CC2541/CC2540
- CC254x简介-CC2541/CC2540
- CC2540/CC2541/CC254x之OSAL操作系统抽象层
- CC2540/CC2541/CC254x之OSAL应用程序接口API介绍
- CC2540/CC2541/CC254x之OSAL应用程序接口API介绍
- CC2640之配置串口打印及可变参数打印
- CC2640之配置串口打印及可变参数打印
- CC254x/CC2540/CC2541库函数速查
- CC254x/CC2540/CC2541库函数速查
- CC254X 添加串口打印
- CC254x(cc2540/cc2541)的微信AirSync调试笔记
- CC2541 CC2540 之自定义MAC地址读取
- 【BLE】CC2541之串口收发
- 【BLE】CC2541之串口收发
- CC2541之串口传输数据
- CodeForces - 567B Berland National Library
- Android调试命令小结
- 【HDU 5720】Wool(排序+排序/扫描线。。。)
- 错误票据
- 杭电ACM 1048
- CC2540/CC2541/CC254x之可变参数串口打印配置
- jQuery学习<五> — — 选择器(下)
- HDU - 4730 We Love MOE Girls
- 关于eclipsetomcat部署项目路径修改
- 371. Sum of Two Integers
- 关于分块算法and莫队算法
- java中特殊的流程控制语句(break,continue,return)
- 开发者MAC电脑里的十八般兵器
- Android通知栏