大家好,又见面了,我是你们的朋友全栈君。
一.串口问题
有问题发送邮件至468078841@qq.com
关于串口的一些常识欢迎点击进入串口中断
二.协议栈串口需用函数解读
这部分主要讲述串口发送问题在协议栈中
#include "hal_uart.h"
#include "MT_UART.h"
这两个文件中封装着关于串口的API函数
关于串口的日常收发问题我们主要使用以下的几个函数
(一)在#include "MT_UART.h"
函数中
函数名:MT_UartInit
函数作用:MT层初始化串口
函数原型:
void MT_UartInit ()
{
halUARTCfg_t uartConfig;
/* Initialize APP ID */
App_TaskID = 0;
/* UART Configuration */
uartConfig.configured = TRUE;//确定配置
uartConfig.baudRate = MT_UART_DEFAULT_BAUDRATE; //这里是波特率
uartConfig.flowControl = MT_UART_DEFAULT_OVERFLOW;//流控
uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;//在RX缓存达到maxRxBufSize之前还有多少字节空余。当到达maxRxBufSize –flowControlThreshold时并且流控制打开时,会触发相应的应用事件:MT_UART_DEFAULT_THRESHOLD
uartConfig.rx.maxBufSize = MT_UART_DEFAULT_MAX_RX_BUFF;//最大接受字节
uartConfig.tx.maxBufSize = MT_UART_DEFAULT_MAX_TX_BUFF;//最大发送字节
uartConfig.idleTimeout = MT_UART_DEFAULT_IDLE_TIMEOUT;//接受数据时间
uartConfig.intEnable = TRUE; //使能
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc = MT_UartProcessZToolData;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
uartConfig.callBackFunc = MT_UartProcessZAppData;
#else
uartConfig.callBackFunc = NULL; //回调函数 这个很有用
#endif
/* Start UART */
#if defined (MT_UART_DEFAULT_PORT)
HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig); //串口初始化
#else
/* Silence IAR compiler warning */
(void)uartConfig;
#endif
/* Initialize for ZApp */
#if defined (ZAPP_P1) || defined (ZAPP_P2)
/* Default max bytes that ZAPP can take */
MT_UartMaxZAppBufLen = 1;
MT_UartZAppRxStatus = MT_UART_ZAPP_RX_READY;
#endif
}
(二)函数名:extern void MT_UartRegisterTaskID( uint8 taskID );
函数作用:注册串口任务
函数原型:
void MT_UartRegisterTaskID( byte taskID )
{
App_TaskID = taskID;
}
(三)在#include "hal_uart.h"
文件中
函数名:extern uint16 HalUARTRead ( uint8 port, uint8 *pBuffer, uint16 length );
函数作用:读取 port 串口 将 length 字节内容读取到 pBuffer
函数原型:
uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
{
(void)port;
(void)buf;
(void)len;
#if (HAL_UART_DMA == 1)
if (port == HAL_UART_PORT_0) return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_DMA == 2)
if (port == HAL_UART_PORT_1) return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_ISR == 1)
if (port == HAL_UART_PORT_0) return HalUARTReadISR(buf, len);
#endif
#if (HAL_UART_ISR == 2)
if (port == HAL_UART_PORT_1) return HalUARTReadISR(buf, len);
#endif
#if HAL_UART_USB
return HalUARTRx(buf, len);
#else
return 0;
#endif
}
(四)函数名:extern uint16 HalUARTWrite ( uint8 port, uint8 *pBuffer, uint16 length );
函数作用:将 length 字节长度的 pBuffer 发送到串口 port
函数原型:
uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
{
(void)port;
(void)buf;
(void)len;
,
,
,
#if (HAL_UART_ISR == 2)
if (port == HAL_UART_PORT_1) return HalUARTWriteISR(buf, len);
HalUARTTx(buf, len);
return len;
#else
return 0;
#endif
}
(五)在OSAL.h
文件中
函数名:uint8 osal_set_event( uint8 task_id, uint16 event_flag )
函数作用:将 task_id 事件 event_flag 标志位置1这时候就处于待处理事件
函数原型:
uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
if ( task_id < tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)
HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts
return ( SUCCESS );
}
else
{
return ( INVALID_TASK );
}
}
三.在协议栈中发送
(1):添加头文件 :
#include "hal_uart.h"
#include "MT_UART.h"
在系统事件初始化函数SampleApp_Init
中加上串口初始化函数
MT_UartInit();
HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));
关于串口0 串口1的问题可以看这里串口中断
这时将代码烧写进入2530中,每次重启,设备都会发送UART_OPEN_SUFFCESS到上位机,关于串口初始化杂乱消息解决方向会在后续出教程解决。
四.将PC端发送的消息回传PC端.事件监控
在前面一节我们知道了协议栈对于消息的处理是基于事件轮询模式,但是在初始自带中只有按键和RF等并没有串口事件,那我们如何添加自己的事件,让接收到的消息回传呢
(一).添加头文件:
#include "hal_uart.h"
#include "MT_UART.h"
(二)自己定义串口事件
在uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
函数里自带了一个SAMPLEAPP_SEND_PERIODIC_MSG_EVT
事件,我们goto一下,可以看到事件定义为
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001
我们仿照自带的类型仿写 在这里我们要介绍一下这里的事件大小是二进制移位然后转16进制进行表示那我我们的接着就是0x0002 0x0004 等等
,在这里我们添加自己的串口事件
#define UART_EVT 0x0002
(三).添加自己的初始化函数
在系统事件初始化函数SampleApp_Init
中加上串口初始化函数
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
.
.
.
.
.
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
Samp
#endif
HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
MT_UartInit(); //
HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));
MT_UartRegisterTaskID(task_id);//注册串口事件
osal_set_event(task_id,UART_EVT);//调用此函数来设置任务的事件标志为1 UART_EVT我们已经绑定在串口了 并且在这里启动第一个串口。
}
(四)事件仿写
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
。
。
。
。
。
。
// Send a message out - This event is generated by a timer
// (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();
// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
if ( events & UART_EVT )//如果UART_EVT被触发 我们就进入这里
{
UART_len = Hal_UART_RxBufLen(0); //先读取串口0 监测是否有消息
if(UART_len) //有消息进入这里
{
osal_memset(UART_RX,'\0',128); //将UART_RX内容清空
HalUARTRead(0,UART_RX,UART_len); //读取消息
HalUARTWrite(0,UART_RX,UART_len);//发送消息
UART_len = 0; //清空这次的消息
}
//定时器执行
osal_set_event(task_id,UART_EVT);//再次置1 进行消息监控
// return unprocessed events
return (events ^ UART_EVT); //将这次消息事件清空
}
// Discard unknown events
return 0;
}
通过上述的操作我们就可以完成常见的串口收发,不过这样写有点麻烦,用这种写过GPRS登录的云端服务器的操作,很麻烦,要考虑很多东西,还容易被优化了。
五.将PC端发送的消息回传PC端.串口回调函数
(一).添加头文件:
#include "hal_uart.h"
#include "MT_UART.h"
(二)自己仿写串口初始化函数,这里可以去MT_UartInit();
直接复制到void SampleApp_Init( uint8 task_id )
改写
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
.
.
.
.
.
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
Samp
#endif
HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
halUARTCfg_t uartConfig;//定义个串口结构体
uartConfig.configured =TRUE;//串口配置为真
uartConfig.baudRate =HAL_UART_BR_115200;//波特率为9600
uartConfig.flowControl =FALSE;//流控制为假
uartConfig.callBackFunc = Uart_Callback_Function ;//串口回调函数,当接受检测到串口消息,我们就调用这个函数
HalUARTOpen(HAL_UART_PORT_0,&uartConfig);// 打开串口0
HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));
}
不要忘记声明函数static void Uart_Callback_Function();
(三)实现串口回调函数
在串口初始化的作用域下,自己随便找个地方写
static void Uart_Callback_Function ()
{
UART_len = Hal_UART_RxBufLen(0); //先读取串口0 长度
if(UART_len) //有消息进入这里
{
osal_memset(UART_RX,'\0',128); //将UART_RX内容清空
HalUARTRead(0,UART_RX,UART_len); //读取消息
HalUARTWrite(0,UART_RX,UART_len);//发送消息
UART_len = 0; //清空这次的消息
}
}
通过上述步骤步骤,算是基本掌握了协议栈的串口问题,在后续将会写一些关于双串口调试的问题,有问题也欢迎大家一起讨论,后续忙完会陆续出一些其他的内容,欢迎提要求哈!
有问题请发邮件至468078841@qq.com
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/141967.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...