一、简介
在项目开发过程中,经常会用到串口输出调试信息,例如用于查看程序运行到哪,或者输出某一个变量的参数。
图1.0 FX3 原理图
二、程序
串口初始化函数
extern CyU3PReturnStatus_t
CyU3PUartInit (
void);
串口配置函数
extern CyU3PReturnStatus_t
CyU3PUartSetConfig (
CyU3PUartConfig_t *config, /**< Pointer to structure containing config information. */
CyU3PUartIntrCb_t cb /**< UART callback function to be registered. */
);
设置串口发送大小函数
extern CyU3PReturnStatus_t
CyU3PUartTxSetBlockXfer (
uint32_t txSize /**< Desired transfer size. */
);
是否输出日记(8字节)前导函数
extern void
CyU3PDebugPreamble (
CyBool_t sendPreamble /**< CyFalse: Do not send preamble; CyTrue: Send preamble. */
);
初始化日记功能
extern CyU3PReturnStatus_t
CyU3PDebugInit (
CyU3PDmaSocketId_t destSckId, /**< Socket through which the logs are to be output. */
uint8_t traceLevel /**< Priority level beyond which logs should be output. */
);
设置日志输出优先级
extern void
CyU3PDebugSetTraceLevel (
uint8_t level /**< Lowest debug trace priority level that is enabled. */
);
日记信息输出函数(只支持整数,字符,字符串 ,十六进制)
extern CyU3PReturnStatus_t
CyU3PDebugPrint (
uint8_t priority, /**< Priority level for this message. */
char *message, /**< Format specifier string. */
... /**< Variable argument list. */
);
由于FX3的固件与编译环境不支持小数(sprintf也不支持),所以自己写了一个函数
void CyFx3_LOGI_Float(char *tag,float value,int decimalDigits)
{
int i = 1;
int IntPart;
int FractPart;for(;decimalDigits != 0;i *= 10,decimalDigits--);
IntPart = (int)value;
FractPart = (int)((value - (float)(int)value) * i);
if(FractPart < 0)
{
FractPart *= -1;
}
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:%d.%d\r\n",tag,IntPart,FractPart);
}
日记信息源文件
#include "cyfx3_log.h"
#include "cyu3uart.h"
#include "cyu3error.h"
CyU3PReturnStatus_t CyFx3LogInit(void)
{
CyU3PReturnStatus_t CyFx3Status;
//初始化uart设备
CyFx3Status = CyU3PUartInit();
if(CyFx3Status != CY_U3P_SUCCESS)
{
return CyFx3Status;
}
//配置uart
CyU3PUartConfig_t UartConfig = {
.txEnable = CyTrue,
.rxEnable = CyTrue,
.flowCtrl = CyFalse,
.isDma = CyTrue,
.baudRate = CY_U3P_UART_BAUDRATE_115200,
.stopBit = CY_U3P_UART_ONE_STOP_BIT,
.parity = CY_U3P_UART_NO_PARITY,
};
CyFx3Status = CyU3PUartSetConfig(&UartConfig,NULL);
if(CyFx3Status != CY_U3P_SUCCESS)
{
return CyFx3Status;
}
//设置发送字节大小
CyFx3Status = CyU3PUartTxSetBlockXfer(0xFFFFFFFF);
if (CyFx3Status != CY_U3P_SUCCESS)
{
return CyFx3Status;
}
//不输出8字节前导数据
CyU3PDebugPreamble(CyFalse);
//初始化串口日志功能
CyFx3Status = CyU3PDebugInit(CY_U3P_LPP_SOCKET_UART_CONS,CYFX3_LOG_DEBUG);
if(CyFx3Status != CY_U3P_SUCCESS)
{
return CyFx3Status;
}
return CY_U3P_SUCCESS;
}
void CyFx3LogLevelSet(CyFx3LogLevel_t traceLevel)
{
CyU3PDebugSetTraceLevel(traceLevel);
}
void CyFx3_LOGI_Float(char *tag,float value,int decimalDigits)
{
int i = 1;
int IntPart;
int FractPart;
for(;decimalDigits != 0;i *= 10,decimalDigits--);
IntPart = (int)value;
FractPart = (int)((value - (float)(int)value) * i);
if(FractPart < 0)
{
FractPart *= -1;
}
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:%d.%d\r\n",tag,IntPart,FractPart);
}
日记信息头文件
#ifndef CYFX3_LOG_H_
#define CYFX3_LOG_H_
#include "cyu3system.h"
#include "cyu3error.h"
typedef enum {
CYFX3_LOG_NONE,
CYFX3_LOG_ERROR,
CYFX3_LOG_WARN,
CYFX3_LOG_INFO,
CYFX3_LOG_DEBUG,
CYFX3_LOG_VERBOSE
}CyFx3LogLevel_t;
#define CyFx3_LOGE(tag,format,arg...) \
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:"format"",tag,##arg)
#define CyFx3_LOGW(tag,format,arg...) \
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:"format"",tag,##arg)
#define CyFx3_LOGI(tag,format,arg...) \
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:"format"",tag,##arg)
#define CyFx3_LOGD(tag,format,arg...) \
CyU3PDebugPrint(CYFX3_LOG_INFO,"%s:"format"",tag,##arg)
#define CyFx3CPU_LOGI(tag,thread_p)\
do{\
CyU3PDebugPrint(CYFX3_LOG_INFO,"CPU LOAD:%d\r\n",\
CyU3PDeviceGetCpuLoad());\
CyU3PDebugPrint(CYFX3_LOG_INFO,"DRIVER LOAD:%d\r\n",\
CyU3PDeviceGetDriverLoad());\
if(tag != NULL && thread_p != NULL)\
CyU3PDebugPrint(CYFX3_LOG_INFO," %s:THREAD LOAD:%d\r\n",\
tag,CyU3PDeviceGetThreadLoad(thread_p));\
}while(0)
#define CHECK_ERROR(CyFx3Status)\
if(CyFx3Status != CY_U3P_SUCCESS)\
CyU3PDebugPrint(CYFX3_LOG_INFO,"CheckError:Line[%d] ErrorCode:%#x\n",__LINE__,CyFx3Status)
CyU3PReturnStatus_t CyFx3LogInit(void);
void CyFx3LogLevelSet(CyFx3LogLevel_t traceLevel);
void CyFx3_LOGI_Float(char *tag,float value,int decimalDigits);
#endif /* CYFX3_LOG_H_ */
主函数
#include "cyfx3_log.h"
#include "cyu3usb.h"
#include "cyu3os.h"
#include "stdio.h"
#include "stdarg.h"
static const char *TAG = "APP";
CyU3PThread LogThreadHandler;
#define LOG_THREAD_PRIORITY 8
#define LOG_THREAD_STACK_SIZE 512
void LogThread(uint32_t arg)
{
float value = 5.2099;
CyFx3LogInit();
while(1)
{
CyFx3_LOGI_Float("value",value,3);
CyFx3_LOGI(TAG,"LogThread\r\n");
CyU3PThreadSleep(1000);
}
}
void CyFxApplicationDefine(void)
{
void *LogStackStart = CyU3PMemAlloc(LOG_THREAD_STACK_SIZE);
if(LogStackStart != NULL)
{
CyU3PThreadCreate((CyU3PThread* ) &LogThreadHandler,
(char* ) "21:Log Thread 1",
(CyU3PThreadEntry_t) LogThread,
(uint32_t ) 0,
(void* ) LogStackStart,
(uint32_t ) LOG_THREAD_STACK_SIZE,
(uint32_t ) LOG_THREAD_PRIORITY,
(uint32_t ) LOG_THREAD_PRIORITY,
(uint32_t ) CYU3P_NO_TIME_SLICE,
(uint32_t ) CYU3P_AUTO_START);
}
}
int main(void)
{
CyU3PReturnStatus_t CyFx3Status;
//初始化FX3设备
CyFx3Status = CyU3PDeviceInit(NULL);
if(CyFx3Status != CY_U3P_SUCCESS)
{
goto HandleFatalError;
}
//初始化FX3内核缓存
CyFx3Status = CyU3PDeviceCacheControl(CyTrue,CyTrue,CyTrue);
if(CyFx3Status != CY_U3P_SUCCESS)
{
goto HandleFatalError;
}
//配置IO矩阵(16位数据总线 + UART + GPIO)
CyU3PIoMatrixConfig_t MatrixcConfig = {
.isDQ32Bit = CyFalse,
.s0Mode = CY_U3P_SPORT_INACTIVE,
.s1Mode = CY_U3P_SPORT_INACTIVE,
.useUart = CyTrue,
.useI2C = CyFalse,
.useI2S = CyFalse,
.useSpi = CyFalse,
.lppMode = CY_U3P_IO_MATRIX_LPP_UART_ONLY,
.gpioSimpleEn[0] = 0,
.gpioSimpleEn[1] = 0,
.gpioComplexEn[0] = 0,
.gpioComplexEn[1] = 0,
};
CyFx3Status = CyU3PDeviceConfigureIOMatrix(&MatrixcConfig);
if (CyFx3Status != CY_U3P_SUCCESS)
{
goto HandleFatalError;
}
//初始化RTOS内核
CyU3PKernelEntry();
HandleFatalError:
//复位
三、验证
烧录验证如下