完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
开发一款蓝牙应用,其实不仅仅是蓝牙,其他的程序也是如此,串口在整个项目中都会占据重要的地位,串口能完成人与芯片的交互。所以在开发项目中首先完成串口部分就显得很重要(当然如果只是开发一个流水灯那大可不必)。
CC2640R2F的串口使用还是很方便的,这得益于TI 的生态做的好,TI 将串口、ADC、SPI、I2C等底层硬件驱动做成库,直接供用户使用,减少了很多的繁琐的事,但是CC2640R2F的串口有一个明显的缺点就是不支持串口DMA,着对于高波特率有需求的项目可能会产生较大影响。 在硬件上来说CC2640R2F的引脚是可以任意映射的,你可以根据需要将它们映射到对应的位置。在软件上来说串口的操作都是基于一个handle句柄值来进行读、写、控制等操作的。 串口使用流程大致包扩这几个过程:1、初始化硬件;2、设置参数;3、获得串口handle;4、基于handle进行读、写、控制等操作。如果想要提升串口的性能,那么还需要使用队列或者RingBuf机制,本文基于TI-RTOS系统和RingBuf来演示。 先上图: 说明: 1、初始化硬件:CC2640R2F的串口已经在SDK配置好了,如果不更改引脚映射建议保持默认。 2、设置参数:根据自己的需要设置波特率、数据位、停止位、校验位。本文是基于回调的方式处理串口数据,回调函数接收串口数据的好处是可以与TI-RTOS任务系统配合,更好的处理数据流。 3、在设置好参数之后,调用open函数获取一个串口handle,后续的串口操作就是基于这个handle进行。 4、读写操作,这是核心,尤其是当对数据的速率以及连续性有要求的时候,运用RingBuf机制和任务事件来处理就要稳定很多。(PS:尤其是当数据量过大、速率过快的时候,可能会导致协议栈处理不过来而丢包或者死机。原因:协议栈的缓存有一定的大小,当串口过来的数据量过打速率过快时协议栈缓存很快就满了,这个缓存大小大概就是:最大连接数 x (MAX_PDU_SIZE - 4),也就是4 x 251)。 代码部分: 1)、配置串口,主要就是两个回调函数的设置,CC2640R2F的串口有一个很好的功能叫部分返回,它会自动的判断超时,并读取串口数据。 定义串口参数,为什么把 UART_MAX_READ_SIZE 定义为251个字节呢? #define UART_MAX_READ_SIZE 251 typedef struct { size_t size; uint8_t buf[UART_MAX_READ_SIZE]; }recv_T; /*uart */ static UART_Handle uartHandle = NULL; recv_T uartRead; bool wtEnable; /*ringbuff*/ static uint8_t RingBufferData[2000]; RingBuf_Object RinfBuferObj; uint8_t writebuf[UART_MAX_READ_SIZE]; 配置串口 1 /*init uart*/ static void ecoInitUart(void) { // Initialize UART UART_Params uartParams; UART_init(); // Open UART in callback mode for both read and write UART_Params_init(&uartParams); uartParams.writeDataMode = UART_DATA_BINARY; uartParams.readDataMode = UART_DATA_BINARY; uartParams.readReturnMode = UART_RETURN_FULL; uartParams.readMode = UART_MODE_CALLBACK; uartParams.writeMode = UART_MODE_CALLBACK; uartParams.readCallback = uartReadCallback; uartParams.writeCallback = uartWriteCallback; uartParams.readEcho = UART_ECHO_OFF; uartParams.baudRate = 115200; uartParams.stopBits = UART_STOP_ONE; uartParams.parityType = UART_PAR_NONE; uartParams.dataLength = UART_LEN_8; //open Board_UART0 ,get handle uartHandle = UART_open(Board_UART0, &uartParams); if (uartHandle == NULL) { // UART_open() failed while (1); } // Enable partial return UART_control(uartHandle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL); //start receive data from RX UART_read(uartHandle, uartRead.buf, sizeof(uartRead.buf)); } /*set uart receive callback*/ static void uartReadCallback(UART_Handle handle, void *rxBuf, size_t size) { uartRead.size = size; Event_post(ecoEventHd,ECO_UART_RECV_EVT); } /*set uart write callback*/ static void uartWriteCallback(UART_Handle handle, void *writeBuf, size_t size) { if(wtEnable) { size_t size = RingBuf_getCount(&RinfBuferObj); if(size > 0) { Event_post(ecoEventHd,ECO_MOVE_DATA_EVT); } else { wtEnable = false; } } } /**/ void ecoWriteData(unsigned char *buf,unsigned short size) { UART_write(uartHandle,buf,size); } 2)、TI-RTOS任务创建。TI-RTOS任务的核心是事件,通过pend、wait、post就能处理一个任务中的不同事件。 首先创建任务参数: /*event cfg*/ #define ECO_UART_RECV_EVT Event_Id_29 #define ECO_UART_WRITE_EVT Event_Id_28 #define ECO_MOVE_DATA_EVT Event_Id_27 #define ET_ALL_EVENTS (ECO_UART_RECV_EVT | ECO_UART_WRITE_EVT | ECO_MOVE_DATA_EVT) /*task cfg*/ #ifndef ET_TASK_STACK_SIZE #define ET_TASK_STACK_SIZE 1024 //根据自己的需要更改任务堆栈大小 #endif #ifndef ET_TASK_PRIORITY #define ET_TASK_PRIORITY 2 //设置任务等级的时候需要注意不要和别的任务重复 #endif /*event variables*/ Event_Struct ecoEvent; static Event_Handle ecoEventHd; /*task variables*/ uint8_t ecoTaskStack[ET_TASK_STACK_SIZE]; Task_Struct ecoTask; 初始化任务: static void ecoTaskInit(void) { /*event init*/ Event_Params ecoEvtParam; Event_Params_init(&ecoEvtParam); Event_construct(&ecoEvent,&ecoEvtParam); ecoEventHd = Event_handle(&ecoEvent); ecoInitUart(); RingBuf_construct(&RinfBuferObj,&RingBufferData[0],sizeof(RingBufferData)); } 创建任务函数: static void ecoTaskFunc(UArg arg0, UArg arg1) { ecoTaskInit(); // Application main loop for(;;) { uint32_t events; events = Event_pend(ecoEventHd, Event_Id_NONE, ET_ALL_EVENTS, ICALL_TIMEOUT_FOREVER); if(events & ECO_UART_RECV_EVT) { handleRecvEvt(); } if(events & ECO_MOVE_DATA_EVT) { handleMoveEvt(); } } } 创建任务: void ecoTaskCreat(void) { Task_Params taskParams; // Configure task Task_Params_init(&taskParams); taskParams.stack = ecoTaskStack; taskParams.stackSize = ET_TASK_STACK_SIZE; taskParams.priority = ET_TASK_PRIORITY; Task_construct(&ecoTask, ecoTaskFunc, &taskParams, NULL); } 处理事件: static void handleRecvEvt(void) { size_t i; for( i=0;i if(RingBuf_put(&RinfBuferObj,uartRead.buf) < 0) { break; } } if(wtEnable == false) { wtEnable = true; Event_post(ecoEventHd,ECO_MOVE_DATA_EVT); } UART_read(uartHandle, uartRead.buf, sizeof(uartRead.buf)); } static void handleMoveEvt(void) { size_t size = RingBuf_getCount(&RinfBuferObj); size_t i; if(size > 0) { for(i=0;i if(RingBuf_get(&RinfBuferObj,writebuf+i) < 0) { break; } } ecoWriteData(writebuf,i); } } 由于本文并没有涉及到数据流向BLE的部分,所以就仅仅将串口RX接收到的数据通过串口TX再打印出来。 实测40K数据连传效果: |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2956 浏览 16 评论
3456 浏览 1 评论
8988 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 12:01 , Processed in 1.173650 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号