第十八节 协议栈UART实验
来源:互联网 发布:自己有产品怎么上淘宝 编辑:程序博客网 时间:2024/05/16 04:03
第十八节 协议栈UART实验
用使用串口,第一步,需要打开使能串口功能,通过配置工程来实现,这里注意,我们现在不使用USB的CDC类来实现串口,所以HAL_UART_USB=FALSE。
HAL_UART=TRUE
HAL_UART_USB=FALSE
要使用串口必须先初始化相应的串口,那该如何初始化呢?在Hal_uart.h文件中我们可以看到如下函数。
uint8 HalUARTOpen(uint8 port, halUARTCfg_t *config);
这个函数就是用来初始化串口的,这个函数有两个参数,第一个指定串口号,第二个是串口的配置参数。我们来看看这个结构体的定义:
typedef struct{ bool configured; // 配置与否 uint8 baudRate; // 波特率 bool flowControl; // 流控制 uint16 flowControlThreshold; uint8 idleTimeout; // 空闲时间 halUARTBufControl_t rx; // 接收 halUARTBufControl_t tx; // 发送 bool intEnable; // 中断使能 uint32 rxChRvdTime; // 接收数据时间 halUARTCBack_t callBackFunc; // 回调函数 }halUARTCfg_t;
这个结构体成员很多,但是我们在使用串口的时候并不需要使用所有的成员。
void Serial_Init(void){ halUARTCfg_t SerialCfg = {0}; SerialCfg.baudRate = HAL_UART_BR_115200; // 波特率 SerialCfg.flowControl = HAL_UART_FLOW_OFF; // 流控制 SerialCfg.callBackFunc = SerialCb; // 回调函数 SerialCfg.intEnable = TRUE; SerialCfg.configured = TRUE; HalLcdWriteString( "Open Uart0", HAL_LCD_LINE_5 ); // 在第5行显示启动信息 HalUARTOpen(HAL_UART_PORT_0, &SerialCfg); HalUARTWrite(HAL_UART_PORT_0, "Hello MT254xBoard\r\n", osal_strlen("Hello MT254xBoard\r\n"));}
在串口回调函数中我们只做一件事,将串口接收到的数据显示到LCD中并且原样的从串口输出。回调函数的实现如下:
static void SerialCb( uint8 port, uint8 events ){ uint8 RxBuf[64]={0}; if((events & HAL_UART_TX_EMPTY)||( events & HAL_UART_TX_FULL )) // 发送区满或者空 { return; } uint16 usRxBufLen = Hal_UART_RxBufLen(HAL_UART_PORT_0); // 读取接收据量 usRxBufLen = MIN(64,usRxBufLen); uint16 readLen = HalUARTRead(HAL_UART_PORT_0, RxBuf, usRxBufLen); HalUARTWrite(HAL_UART_PORT_0, RxBuf, usRxBufLen);}
实验现象,从实验现象中可以看到,一开始在串口中输出了一个标志字符串,然后我们通过串口发送了0123456789,然后数据原样的从串口输出了,这和我们预期的结果是一样的。
但是我们发现LCD上的显示和我们预期的不一样,LCD上只显示了6789,前面的数据并没有显示,这是怎么一回事呢?进行单步调试可以发现,我们发送一次数据,回调函数被回调了两次,第一次回调只接受到了012345,第二次回调接收到了6789,而在LCD上的显示第二次覆盖了第一次的显示,所以我们会看到这种现象,解决的办法,我们需要定义一个数据帧的时间间隔,当接收数据的间隔超过了此间隔就认为接收结束。
下面我们改写接收处理,我们在接收到数据后开启定时器,定时5ms这样,当接收间隔大于5ms后,我们就可以在定时事件中处理串口接收到的数据。
static void SerialCb( uint8 port, uint8 events ){ if((events & HAL_UART_TX_EMPTY)||( events & HAL_UART_TX_FULL )) // 发送区满或者空 { return; } uint16 usRxBufLen = Hal_UART_RxBufLen(HAL_UART_PORT_0); // 读取接收据量 if(usRxBufLen) { usRxBufLen = MIN(128,usRxBufLen); uint16 readLen = HalUARTRead(HAL_UART_PORT_0, &SerialRxBuf[RxIndex], usRxBufLen); // 读取数据到缓冲区 RxIndex += readLen; readLen %= 128; osal_start_timerEx(simpleBLEPeripheral_TaskID, UART_EVENT, 5); // 启动定时器 }}
事件处理代码:
if ( events & UART_EVENT ) { HalLcdWriteString( (char*)SerialRxBuf, HAL_LCD_LINE_6 ); // 在第5行显示启动信息 HalUARTWrite(HAL_UART_PORT_0, SerialRxBuf, osal_strlen(SerialRxBuf)); osal_memset(SerialRxBuf, 0, 128); return (events ^ UART_EVENT); }
事件处理代码:经过这样的处理后,可以发现我们刚刚的问题已经解决了。
到这里串口已经可以正常使用了,为了更加方便的使用串口,我在这里添加一个函数实现标准C中printf,这样更有利于我们输出。
int SerialPrintf(const char*fmt, ...){ uint32 ulLen; va_list ap; char *pBuf = (char*)osal_mem_alloc(PRINT_BUF_LEN); // 开辟缓冲区 va_start(ap, fmt); ulLen = vsprintf(pBuf, fmt, ap); // 用虚拟打印函数实现 va_end(ap); HalUARTWrite(HAL_UART_PORT_0, (uint8*)pBuf, ulLen); // 从串口0输出 osal_mem_free(pBuf); // 释放内存空间 return ulLen;}
我们可以像使用C标准中的printf来使用这个函数,例如我们将LCD的输出全部导向串口的输出,在HalLcdWriteString的实现中添加串口输出代码,如下图:
重新编译并且烧录后可以看到LCD的输出和串口的输出是一样的了。
本文章转载自
http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/69222.aspx
请勿用于商业
0 0
- 第十八节 协议栈UART实验
- Cc2540 协议栈UART实验
- Cc2540 协议栈UART实验
- ble学习笔记十二---------------协议栈之UART实验
- 低功耗蓝牙cc2541学习笔记之UART-3-协议栈uart发送 实验
- 低功耗蓝牙cc2541学习笔记之UART-4-协议栈uart接受数据实验
- php学习 第十八节
- 第十八节,修饰器
- 第十八节网络编程
- 第十八节 java学习 数组
- Java基础部分第十八节
- UART协议
- UART协议
- UART协议
- linux 协议栈学习 第八节 链路层GRO的处理
- TI BLE协议栈中使用UART
- 第十八节 数据结构之单向链表
- Uart串口实验--TQ2440
- dubbo-admin在jdk 1.8上出错问题
- Fucking sad
- 本周。实验和网球
- ubuntu默认root密码
- Python篇----面向对象程序设计(二)(属性和方法篇)
- 第十八节 协议栈UART实验
- 关于TOAD使用instantclient的设置
- AndroidArticle
- Android开发优化之——使用软引用和弱引用
- 关于华为系列手机 EMUI3.0-EMUI4.0 锁屏控制音乐播放代码 之 添加
- 介绍NSURLSESSION网络请求套件
- Ceph分布式存储系统介绍
- 《剑指Offer》读书笔记08:跳台阶
- 控件拖动