Z-Stack串口操作:
CC2530共有两个串口,UART0和UART1,两个串口可以通过设置寄存器PERCFG的值映射到不同的引脚上,对应的映射关系如下:
端口 串口0 位置1 位置2 串口1 位置1 位置2 P0 5 RT RX P1 4 3 2 7 CT TX RX TX RT CT RX 6 TX 5 TX RT 4 RX CT 3 RT 2 CT
PERCFG寄存器相关位的描述如下: 位 名称 复位 1 U1CFG 0 0 U0CFG 0 读/写 读/写 读/写 描述 串口1端口映射。0:位置1;1:位置2 串口0端口映射。0:位置1;1:位置2 在CC2530中提供了两种方式来操作串口,即直接存取访问(DMA)和中断(ISR)方式,两种操作方式的区别在这里不再叙述,想了解的请自行查阅相关资料。
在z-stack中默认的使用DMA方式来操作串口,默认配置的串口为UART0,UART0默认使用位置1,即P02为UART的RX,P03为UART的TX。接下来将详细介一下Z-STACK串口默认的配置流程,并介绍如何配置同时使用两个串口。
一、 串口默认配置的流程
从main函数开始,串口的初始化化函数在调用HalDriverInit()函数时被调用,在HalDriverInit函数中调用了函数HalUARTInit()函数,函数原型如下:
void HalUARTInit(void) {
#if HAL_UART_DMA HalUARTInitDMA(); #endif
#if HAL_UART_ISR HalUARTInitISR(); #endif
#if HAL_UART_USB HalUARTInitUSB(); #endif }
可以看出,协议栈通过判断宏定义的方法来判断以何种方式来初始化串口,有关的宏可以在hal_board_cfg.h中找到,先将与串口有关的宏列出以便分析:
* Set to TRUE enable UART usage, FALSE disable it */
#ifndef HAL_UART //如果未定义HAL_UART
/*如果定义了defined ZAPP_P1、defined ZAPP_P2、defined ZTOOL_P1、defined ZTOOL_P2中的一个,就定义HAL_UART为1,协议栈默认地定义了ZTOOL_P1,可以点击project->options->c/c++complier->preprocess->defined symbols来查看预编译的宏*/
#if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2) #define HAL_UART TRUE
#else //否则的话在进行下面的
#define HAL_UART FALSE //将HAL_UART定义为0,即不使用串口 #endif #endif
#if HAL_UART //如果HAL_UART为1
// Always prefer to use DMA over ISR.总是优先地使用DMA方式 #if HAL_DMA
#ifndef HAL_UART_DMA
#if (defined ZAPP_P1) || (defined ZTOOL_P1) #define HAL_UART_DMA 1
#elif (defined ZAPP_P2) || (defined ZTOOL_P2) #define HAL_UART_DMA 2 #else
#define HAL_UART_DMA 1 #endif #endif
/*执行完上面的一部分代码后,HAL_UART_DMA的值就为1了,具体自行分析 #define HAL_UART_ISR 0 //默认不实用ISR方式来处理中断
/*在这里已经定义了HAL_UART_ISR,所以就不会进入下面的#ifndef HAL_UART_ISR 判断了*/ #else
#ifndef HAL_UART_ISR
#if (defined ZAPP_P1) || (defined ZTOOL_P1) #define HAL_UART_ISR 1
#elif (defined ZAPP_P2) || (defined ZTOOL_P2) #define HAL_UART_ISR 2 #else
#define HAL_UART_ISR 1 #endif #endif
#define HAL_UART_DMA 0 #endif
/*执行完上面的代码后,HAL_UART_ISR就被定义为0了*/
// Used to set P2 priority - USART0 over USART1 if both are defined. #if ((HAL_UART_DMA == 1) || (HAL_UART_ISR == 1)) #define HAL_UART_PRIPO 0x00 #else
#define HAL_UART_PRIPO 0x40 #endif
/*上述代码设置了两个串口的优先级,串口0大于串口1*/
/*这里的#else对应的是#if HAL_UART,意思就是如果串口使用,就将两种方式的宏都定义为0*/ #else
#define HAL_UART_DMA 0 #define HAL_UART_ISR 0 #endif
/* USB is not used for CC2530 configuration */ #define HAL_UART_USB 0
上述代码的if和else对应的关系可能很难看出,可以用notepad打开源文件来查看对应关系。
总结一下,上述代码完成的功能就是将HAL_UART_DMA宏设置为1,将HAL_UART_ISR宏设置为0。
然后我们再回到HalUARTInit(void)函数,可以看出在这里调用的串口初始化函数是HalUARTInitDMA()函数,函数原型如下(省略了部分不必要的代码): static void HalUARTInitDMA(void) {
halDMADesc_t *ch; //定义了一个DMA通道 /*设置串口优先级*/ P2DIR &= ~P2DIR_PRIPO; P2DIR |= HAL_UART_PRIPO;
#if (HAL_UART_DMA == 1) //默认配置会执行这里的语句 /*设置UART0在位置1,P0口*/
PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0. #else
/*否则的话UART0在位置2,P1口*/
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1. #endif
/*设置P0口的P02、P03为外设功能,P02为RX、P03为TX*/ PxSEL |= HAL_UART_Px_RX_TX; // Enable Tx and Rx on P1.
/*禁用P02和P03的ADC功能,以防止对串口通信产生干扰。TI的工程师是挺细心的,其实我们在使用的时候也不会傻到把这两个端口硬件连接为ADC吧*/
ADCCFG &= ~HAL_UART_Px_RX_TX; // Make sure ADC doesnt use this. /*设置为UART模式,还可配置为SPI模式*/
UxCSR = CSR_MODE; // Mode is UART Mode. /**清除单元/
UxUCR = UCR_FLUSH; // Flush it. /*未列出DMA初始化的一些代码*/ ……………………. }
上面的函数执行完成以后就基本上完成了串口的初始化,包括串口处理方式、串口对应的引脚等,进一步的串口初始化设置在HalUARTOpenDMA(halUARTCfg_t *config)函数中被完成,该函数的原型如下,在看懂这个函数之前我们需要先了解一下结构体halUARTCfg_t这个结构
体的定义在hal_uart.h文件中,原型如下: typedef struct {
bool configured; //是否注册串口
uint8 baudRate; //串口通信波特率设置 bool flowControl; //硬件流控制
uint16 flowControlThreshold; //don’t care uint8 idleTimeout; //don’t care halUARTBufControl_t rx; //don’t care halUARTBufControl_t tx; //don’t care
bool intEnable; //don’t care uint32 rxChRvdTime; //don’t care halUARTCBack_t callBackFunc; //串口回调函数 }halUARTCfg_t;
可以看出上述结构体完成了串口初始化所需要的各项参数,包括在OSAL中注册串口,通信波特率的设置等,同时HalUARTOpenDMA函数的形参也是这个结构体,也就是说这些初始化将在这个函数中被完成,下面来通过注释来分析这个函数。 static void HalUARTOpenDMA(halUARTCfg_t *config) {
/*注册串口回调函数,串口收到数据后会调用回调函数*/ dmaCfg.uartCB = config->callBackFunc; /
// Only supporting subset of baudrate for code size - other is possible. HAL_UART_ASSERT((config->baudRate == HAL_UART_BR_9600) || (config->baudRate == HAL_UART_BR_19200) || (config->baudRate == HAL_UART_BR_38400) || (config->baudRate == HAL_UART_BR_57600) || (config->baudRate == HAL_UART_BR_115200));
if (config->baudRate == HAL_UART_BR_57600 || config->baudRate == HAL_UART_BR_115200) {
UxBAUD = 216; } else {
UxBAUD = 59; }
switch (config->baudRate) {
case HAL_UART_BR_9600: UxGCR = 8;
dmaCfg.txTick = 35; // (32768Hz / (9600bps / 10 bits))
// 10 bits include start and stop bits.
break;
case HAL_UART_BR_19200: UxGCR = 9;
dmaCfg.txTick = 18; break;
case HAL_UART_BR_38400: UxGCR = 10;
dmaCfg.txTick = 9; break;
case HAL_UART_BR_57600: UxGCR = 10;
dmaCfg.txTick = 6; break; default:
// HAL_UART_BR_115200 UxGCR = 11;
dmaCfg.txTick = 3; break; }
/*上面的部分代码通过switch判断完成了对串口波特率的设置,具体的寄存器值可以参考下面的波特率寄存器设置表*/
// 8 bits/char; no parity; 1 stop bit; stop bit hi. if (config->flowControl) {
UxUCR = UCR_FLOW | UCR_STOP; PxSEL |= HAL_UART_Px_CTS;
// DMA Rx is always on (self-resetting). So flow must be controlled by the S/W polling the Rx
// buffer level. Start by allowing flow. PxOUT &= ~HAL_UART_Px_RTS; PxDIR |= HAL_UART_Px_RTS; } else {
UxUCR = UCR_STOP; //停止位为高电平 }
/*don’t care*/
dmaCfg.rxBuf[0] = *(volatile uint8 *)DMA_UDBUF; // Clear the DMA Rx trigger. HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX); HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
osal_memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*2);
UxCSR |= CSR_RE;
搜索“diyifanwen.net”或“第一范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,第一范文网,提供最新教学研究z-stack协议栈串口驱动详解与同时使用两个串口的配置方法 全文阅读和word下载服务。
相关推荐: