UART在嵌入式软件开发中的重要性不言而喻;我之前有调通过TI BLE协议栈的串口,而且我记得当时有做过一个简单的文档记录,表明需要注意的地方。可遗憾的是换了个硬盘,源码也找不到,记录文档也丢了;直接导致我又花了好几个小时重新调试BLE协议栈的串口应用。废话不多说,赶紧记录要点。
首先贴出源码:SerialPortApp.h
/**************************************************************************************************
Filename: SiralPortApp.h
**************************************************************************************************/
#ifndef SiralPortApp_H
#define SiralPortApp_H
#include <stdio.h>
#include <string.h>
#include "hal_uart.h"
#define SPA_UART_PORT HAL_UART_PORT_0
#define SPA_UART_FlowCtl FALSE
#define SPA_UART_FC_THRESHOLD 48
#define SPA_UART_RX_BUF_SIZE 128
#define SPA_UART_TX_BUF_SIZE 128
#define SPA_UART_IDLE_TIMEOUT 6
void serialPortApp_Init( uint8 task_id );
//void serialPortAPP_PrintString(char* str);
void serialPortApp_Callback(uint8 port, uint8 event);
#endif
SerialPortApp.c
#include "SerialPortApp.h"
/*********************************************************************
* @fn serialPortApp_Init
*
* @brief 串口应用初始化
*
* @return none
*/
void serialPortApp_Init( uint8 task_id )
{
/*串口参数配置*/
halUARTCfg_t config;
config.configured = TRUE;
config.baudRate = HAL_UART_BR_115200;
config.flowControl = SPA_UART_FlowCtl;
config.flowControlThreshold = SPA_UART_FC_THRESHOLD;
config.rx.maxBufSize = SPA_UART_RX_BUF_SIZE;
config.tx.maxBufSize = SPA_UART_TX_BUF_SIZE;
config.idleTimeout = SPA_UART_IDLE_TIMEOUT;
config.intEnable = TRUE;
config.callBackFunc = serialPortApp_Callback;//uart接收回调函数
HalUARTOpen(SPA_UART_PORT, &config);//打开串口
}
/*********************************************************************
* @fn serialPortApp_Callback
*
* @brief 串口接收数据回调函数
*
* @return none
*/
void serialPortApp_Callback(uint8 port, uint8 event)
{
uint8 rxBuf[SPA_UART_RX_BUF_SIZE];
while(Hal_UART_RxBufLen(port))//uart接收缓冲区有数据
{
HalUARTRead(port,rxBuf,1);
}
}
/*********************************************************************
* @fn serialPortAPP_PrintString
*
* @brief 串口打印字符串
*
* @param str 需要打印的字符串
*
* @return none
*/
//void serialPortAPP_PrintString(char* str)
//{
// HalUARTWrite(SPA_UART_PORT, (uint8*)str, strlen(str));
//}
/*********************************************************************
* @fn putchar
*
* @brief 将printf函数重定向至单片机串口
*
*/
__near_func int putchar(int c)
{
uint8 str[] = {c};
HalUARTWrite(SPA_UART_PORT, str, 1);
return (c);
}
备注:上述代码在串口发送数据时,是成功的;数据接收部分还待调试!
UART应用代码完成后,接下来就是调用了。我在上次创建的BLE新应用IAR中创建BLE/Zigbee新项目中实现串口打印功能!
将文件添加如上述SerialPortAppPeripheral中后,只需要修改SiralPortAppPeripheral.c 三个地方就能实现UART输出应用:
1、#include “SerialPortApp.h”//添加串口应用头文件
2、在void SiralPortAppPeripheral_Init( uint8 task_id )
函数中初始化串口应用:
void SerialPortAppPeripheral_Init( uint8 task_id )
{
SerialPortAppPeripheral_TaskID = task_id;
//初始化串口应用
serialPortApp_Init(SiralPortAppPeripheral_TaskID);
// Setup the GAP
VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL );
3、在应用事件处理函数中调用printf()打印输出:
uint16 SerialPortAppPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{
VOID task_id; // OSAL required parameter that isn't used in this function
static int cnt = 0;
if ( events & SYS_EVENT_MSG )
{
uint8 *pMsg;
if ( (pMsg = osal_msg_receive( SerialPortAppPeripheral_TaskID )) != NULL )
{
SerialPortAppPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );
// Release the OSAL message
VOID osal_msg_deallocate( pMsg );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if ( events & SBP_START_DEVICE_EVT )
{
// Start the Device
VOID GAPRole_StartDevice( &SerialPortAppPeripheral_PeripheralCBs );
// Start Bond Manager
VOID GAPBondMgr_Register( &SerialPortAppPeripheral_BondMgrCBs );
// Set timer for first periodic event
osal_start_timerEx( SerialPortAppPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
return ( events ^ SBP_START_DEVICE_EVT );
}
if ( events & SBP_PERIODIC_EVT )
{
// Restart timer
if ( SBP_PERIODIC_EVT_PERIOD )
{
osal_start_timerEx( SerialPortAppPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
}
/*
串口成功打印!!
需要注意:
1、在Options预处理器中添加 HAL_UART=TRUE
2、将Options预处理器中原有的POWER_SAVING改为xPOWER_SAVING
(如果不关闭该选项串口不能使用!!!)
*/
//serialPortAPP_PrintString("start periodic event ...\r\n");
printf("periodic times: %d\n",cnt++);
// Perform periodic application task
performPeriodicTask();
return (events ^ SBP_PERIODIC_EVT);
}
// Discard unknown events
return 0;
}
注意:
1、在Options预处理器中添加 HAL_UART=TRUE
2、将Options预处理器中原有的POWER_SAVING改为xPOWER_SAVING(如果不关闭该选项串口不能使用!!!)
这里还有一点比较有意思:在IAR中实现printf()函数重定向至单片机的UART。只需要理解
__near_func int putchar(int c)
{
uint8 str[] = {c};
HalUARTWrite(SPA_UART_PORT, str, 1);
return (c);
}
|