一、HAL和MT层
从下面两幅图幅图我们可以看到Z-stack提供的HAL层里面包含了很多外设的驱动程序,简化了我们开发流程。但是同时我们也发现了项目下面还有一个MT层,它提供的操作比HAL层更加简便和多样(MT层是HAL层的上层)。所以我们就用MT层的函数进行UART的初始化。
二、初始化串口
之前我们提到过用户初始化函数放置的位置,在Zmain.c --> osal_init_system() --> osalInitTasks() --> SampleApp_Init()。
我们的目的是开机打印“Hello Seanoy\n”信息,接下来看一下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;
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
}
似曾相识的感觉,主要配置波特率MT_UART_DEFAULT_BAUDRATE、流控MT_UART_DEFAULT_OVERFLOW,波特率默认为38400,流控默认为打开。注意如果是同时全双工UART的话要关闭流控!
三、登记串口任务号
通过MT层提供的MT_UartRegisterTaskID() 函数传入SampleApp的task_id,可以看到这个函数非常简单,就是将taskID赋值给App_TaskID,后者是byte(uint8_t)变量,用于OSAL任务标识应用程序的ID。
void MT_UartRegisterTaskID( byte taskID )
{
App_TaskID = taskID;
}
四、发送字符串
通过bsp_uart.c源文件下的HalUARTWrite() 函数发送字符串。第一个参数port为0代表使用串口1,为1时使用串口2;第二个参数是要发送的字符串;第三个参数是要发送字符串的长度。默认使用DMA发送(Direct Memory Access),即满足条件HAL_UART_DMA==1下的程序。
uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
{
(void)port;
(void)buf;
(void)len;
#if (HAL_UART_DMA == 1)
if (port == HAL_UART_PORT_0) return HalUARTWriteDMA(buf, len);
#endif
#if (HAL_UART_DMA == 2)
if (port == HAL_UART_PORT_1) return HalUARTWriteDMA(buf, len);
#endif
#if (HAL_UART_ISR == 1)
if (port == HAL_UART_PORT_0) return HalUARTWriteISR(buf, len);
#endif
#if (HAL_UART_ISR == 2)
if (port == HAL_UART_PORT_1) return HalUARTWriteISR(buf, len);
#endif
#if HAL_UART_USB
HalUARTTx(buf, len);
return len;
#else
return 0;
#endif
}
五、额外的配置
如果想要完整使用MT提供的功能的话,则要在Options下C/C++ compiler中的Preprocessor下Defined symbols添加下列预编译宏:
- ZIGBEEPRO
- ZTOOL_P1
- MT_TASK
- MT_SYS_FUNC
- MT_ZDO_FUNC
但是在实际读取串口数据的时候会发现额外的数据,它是紧接着发送数据后面,以0XFE开头的数据段 FE 06 41 80 01 02 00 02 05 01 C2。
如果不想要这段数据的话,就要取消MT的功能了,具体做法是在预编译宏里面的MT开头的宏前面加上x,让它不起作用。
- xMT_TASK
- xMT_SYS_FUNC
- xMT_ZDO_FUNC
这时候我们可以看到发送的数据就是透传数据了。