一、简介
本文介绍如何在SimpleBLEPeripheral工程中,使用串口。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF(主芯片CC2541)
三、版权声明
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://write.blog.csdn.net/postedit
联系方式:495527583@qq.com
四轴开源群:84342712
四、基础知识
1、协议栈的串口默认使用的是查询方式,还是中断方式?
答:默认使用的是DMA的查询方式。
2、PC端为什么收不到2541的串口数据?
答:最常见原因有两个:
1)没有关闭流控。(关闭步骤见下文)
2)开了低功耗。快速解决办法如下
3、低功耗下是否能使用串口?
答:不能。进低功耗前要关闭串口,唤醒后要再使能串口。
4、如何关闭串口?(未实践,提供思路)
答:有群友指出一种方法:
使用dma方式、isr方式的串口,将串口引脚映射为普通IO口,即为关闭。
5、低功耗唤醒后串口没用了?(未实践,提供思路)
答:由于低功耗与正常模式的切换,会导致晶振的32k与32M的切换。而串口等外设使用的是32M的外部晶振,因此低功耗唤醒后需要做两件事:
1)适当延时等待32M晶振稳定。
2)再次初始化一次串口。
五、修改代码
1、IAR设置中添加宏定义
2、修改串口驱动
1)添加头文件(npi.c中)
2)新增两个串口发送函数(npi.c中)
3)函数声明(npi.h中)
3、包含头文件(simpleBLEPeripheral.c中)
4、新增初始化代码(simpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)
5、定义并声明一个串口回调函数
1)定义串口回调函数(simpleBLEPeripheral.c中)
2)声明串口回调函数(simpleBLEPeripheral.c中)
6、关流控(npi.h中)
流控是用于防止串口阻塞的,需要多两根线用于流控。
通常使用中都是关闭的,因此我们这里关闭之。
注意!!如果这里不关闭,会导致串口通信不了。
六、实验结果
初始化时打印了4条语句,最后一条是通过PC端的串口工具发给2541、2541再原样返回的值。
七、串口相关问题
1、上电时串口接收缓冲区会有一个字节,暂不明该数据哪里来的。暂时用接收处理将该无用字节过滤掉。
答:经检查,是P0_2(RX)使用内部上拉电阻,但电压仅为0.6V。上电时电压不稳定导致接收缓冲区会有一个字节的数据“0x00”。
因此解决方法是:外接1个10K上拉电阻到3.3V,将P0_2(RX)的电压拉高至3.3V。
注:TX引脚最好也外接上拉电阻。
2、串口什么时候进回调函数?
答:
1)正常串口端无发送、无接收时,是不会进回调函数的。如果这种情况会进回调函数,TX、RX端外接上拉电阻稳定电平。
2)如果接收端有数据,立马就会进回调。事件是“接收超时事件”。
3)2541发送端发送完数据,会进回调函数。事件是“发送缓冲区空事件”。
3、没开广播时串口正常使用,开了广播后串口出现乱码、丢包?
答:
1)在SimpleBLEPeripheral的应用层初始化中注释掉:
HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT );
PS:这条语句会让空闲的CPU自动进入低频以此降低功耗,注释掉代表不自动切换频率。
2)在SimpleBLEPeripheral的应用层初始化中添加:
HCI_EXT_HaltDuringRfCmd(HCI_EXT_HALT_DURING_RF_DISABLE);
PS:默认是ENABLE的,ENABLE会让RF期间停止MCU。因此需要添加本条语句,关闭它。
4、编译时出现警告“Warning[w52]: More than one definition for the byte at address 0x6b in common segment INTVEC. It is defined in module "hal_uart" as well as in module "hal_key"”?
答:原因是IAR中包含了POWER_SAVING的宏之后,串口唤醒就需要用到IO中断,而协议栈中串口唤醒的默认IO口是P04脚。因此在_hal_uart_dma.c中包含了的P0中断服务函数就与Hal_key.c中包含的P0中断服务函数相冲突。
详情代码如下:
1)当IAR中包含了POWER_SAVING的宏之后,会定义一个DMA_PM的宏(_hal_uart_dma.c中)
2)一旦有了DMA_PM这个宏,_hal_uart_dma.c中就会包含P0的中断服务函数
3)IAR设置中包含HAL_KEY=TRUE时,Hal_key.c中就会包含P0的中断服务函数
所以,解决办法如下:
方法一(治标不治本):IAR设置中将HAL_UART、HAL_KEY其中一个设置为FALSE。
方法二(治标不治本):不使用低功耗。
方法三(治本但改动了协议栈代码):将两个P0的中断服务函数合二为一。
//(待测)方法四(非强迫症人群使用):任其冲突,反正只是警告。
5、串口接收多少个字节能进入回调函数?
1)测试代码如下:
2)测试结果
3)测试结论
2541串口接收端的数据是由DMA去接收的,2541会通过轮询的方式定期查询DMA的缓冲区是否有数据,一旦有数据即会进入回调函数(协议栈默认不开超时等待)。
上图说明了第一次进回调函数时DMA接收到了7个字节数据,它的长度与“主轮询时间”、“串口数据来的时机”有关系。
而第二次、第三次的接收数据之所以会比第一次多,是因为还加上了串口处理时接收到的数据。