nrf52840 gpiote如何配置中断输入_(4)nRF52840配置串口数据收发

点击上方蓝字,关注微联智控工作室

可点击右上角的 …,分享这篇文章

Nordic nRF52840芯片内部集成了一个UART外设模块,用于双向异步串口通信。这个外设模块主要有以下特性:全双工,自动硬件流控、奇偶校验、1位停止位。

nRF52840芯片的UART模块在引脚管理上比很多单片机灵活,可以通过引脚配置寄存器,把TXD,RXD,CTS,RTS这四个控制信号映射到48个引脚中的任何一个物理引脚。由于nRF52840芯片只有一个UART模块,因此,不能把同一个引脚都映射为不同的信号,例如,不能同时把P0.06引脚同时映射为TXD和RXD。

nRF52840芯片内部除了集成UART串口模块,还有UARTE模块,UARTE模块和UART模块这两者的区别是,UARTE模块是通过EasyDMA进行数据收发的,使用DMA技术进行数据收发,可以有效降低CPU的负担,因此,后续的例程都是使用UARTE模块进行开发。

nRF52840的UARTE模块的工作原理:不管是发送数据还是接收数据,都是由EasyDMA负责数据在内存RAM和物理线路之间的传输。发送数据的时候,EasyDMA把数据从内存RAM中读出并传输到物理线路中。接收数据的时候,EasyDMA把接收到的数据从物理线路写入到内存RAM中,因此,使用UARTE收发数据时,需要在内存RAM中指定接收和发送缓冲区。

在Nordic提供的SDK里面,有专门针对UART和UARTE操作的库函数,这两者共用一个程序函数库,称为APP_UART,在这个APP_UART中,封装了对UART和UARTE的操作函数,并且通过配置sdk_config.h里面的宏定义来进行条件编译。

软件开发前准备:

开发板:Nordic官方开发板nRF52840-DK(PCA10056)。

编译器:SEGGEREmbedded Studio v4.22

SDK版本:nRF5_SDK_15.2.0_9412b96

1、我们基于前面构建的“003_gpio_test”工程来进行软件开发。先复制一份工程,并重命名为“004_uart_test”,并且把GPIOTE相关的驱动模块添加到工程,完成后打开工程,如下图所示。

9273a29d0b8501047c97668e32dcf227.png

509933d32ad345e7ba5b0e7dd1bf00eb.png

以上添加的文件,具体目录如下表所示:

源文件

SDK中的路径

描述说明

nrf_drv_uart.c

integration/nrfx/legacy

旧的UART驱动程序

nrfx_uart.c

modules/nrfx/drivers/src

新的UART驱动程序

nrfx_uarte.c

modules/nrfx/drivers/src

新的UARTE驱动程序

app_fifo.c

components/libraries/fifo

FIFO程序模块

app_uart_fifo.c

components/libraries/uart

串口FIFO库文件

nrfx_prs.c

modules/nrfx/drivers/src/prs

外设资源共享文件

retarget.c

components/libraries/uart

串口重定向文件

2、为了便于工程管理,我们新建两个文件uarte.c和uarte.h,用来编写串口相关的操作函数,头文件uarte.h的内容如下图所示。

#ifndef _UARTE_H_
#define _UARTE_H_

#include "nrf_gpio.h"
#include "nordic_common.h"

#define RX_PIN_NUMBER NRF_GPIO_PIN_MAP(0,8)
#define TX_PIN_NUMBER NRF_GPIO_PIN_MAP(0,6)
#define CTS_PIN_NUMBER NRF_GPIO_PIN_MAP(0,7)
#define RTS_PIN_NUMBER NRF_GPIO_PIN_MAP(0,5)

#define UART_TX_BUF_SIZE 256
#define UART_RX_BUF_SIZE 256

#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED

extern void my_uart_init(void);

#endif

从上述代码可知,头文件根据开发板的原理图,定义了RXD,TXD,CTS,RTS这几个通信引脚的具体物理引脚编号,还有发送和接收缓冲区的大小,定义是否启动硬件流控。

3、再来看看uarte.c文件的内容,如下图所示。

#include 
#include 
#include 
#include "nrf_uart.h"
#include "nrf_uarte.h"
#include "app_uart.h"
#include "app_error.h"
#include "uarte.h"

static void uart_event_handler(app_uart_evt_t * p_event){
    switch(p_event->evt_type){
        /*An event indicating that UART data has been received. The data is available in the FIFO and can be fetched using @ref app_uart_get*/
        case APP_UART_DATA_READY:{
            uint8_t cr;
            while (app_uart_get(&cr) != NRF_SUCCESS);while (app_uart_put(cr) != NRF_SUCCESS);
        }break;
        /*An error in the FIFO module used by the app_uart module has occured. The FIFO error code is stored in app_uart_evt_t.data.error_code field*/
        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
        break;
        /*An communication error has occured during reception. The error is stored in app_uart_evt_t.data.error_communication field */
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
        break;
        /*An event indicating that UART has completed transmission of all available data in the TX FIFO */
        case APP_UART_TX_EMPTY:
        break;
        /*An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured */
        case APP_UART_DATA:
        break;   
        default:break;
    }
}
void my_uart_init(void){
    uint32_t err_code;
    const app_uart_comm_params_t comm_params = {
          RX_PIN_NUMBER,TX_PIN_NUMBER,
          RTS_PIN_NUMBER,CTS_PIN_NUMBER,
          UART_HWFC,false,NRF_UARTE_BAUDRATE_115200
      };
    APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_event_handler,APP_IRQ_PRIORITY_LOWEST,err_code);
    APP_ERROR_CHECK(err_code);
}

4、先来看看my_uart_init()函数,这个函数主要是调用了串口初始化宏APP_UART_FIFO_INIT,跟踪这个宏定义,展开后的函数原型如下图所示。

30f5f55b94506de4a5d00f42c50d3be8.png

这个宏定义主要有5个输入参数和1个输出参数。最后主要是调用了app_uart_init()函数来进行实际的串口初始化。这个宏一开始定义了一个app_uart_buffers_t类型的变量,这个结构体类型是用来指定接收和发送缓存的地址和大小的。对于这个宏的输入参数描述,如下所示。

(1)P_COMM_PARAMS:指向串口通信配置参数的结构体。

(2)RX_BUF_SIZE:数据接收缓冲区的大小,需要2的整数倍。

(3)TX_BUF_SIZE:数据发送缓冲区的大小,需要2的整数倍。

(4)EVT_HANDLER:串口数据事件处理的回调函数。

(5)IRQ_PRIO:串口中断优先级。

(6)ERR_CODE:错误代码。属于输出参数。

5、宏APP_UART_FIFO_INIT最终是调用了app_uart_init()函数来进行串口初始化的,这个函数的声明如下图所示。

c0627ebd7e177371c95aa46ca397b809.png

这个函数主要有4个输入参数,输入参数描述如下所示。

(1)p_comm_params:串口配置参数结构体。应用程序一开始需要定义一个结构体变量,类型为app_uart_comm_params_t,用来配置串口工作的各种参数。

(2)p_buffers:接收和发送缓冲区,NULL表示不使用缓冲区。

(3)error_handler:串口事件处理的回调函数。

(4)irq_priority:串口中断优先级。

6、在使用APP_UART_FIFO_INIT宏初始化串口时,需要定义串口事件处理的回调函数,当串口有各种事件产生的时候,这个函数就会被调用,在这个函数里面就可以处理各种串口事件。APP_UART这个库函数定义了5种串口事件,定义在app_uart_evt_type_t这个枚举中,如下图所示。

a5fa2b931332cf77a3b86daf309675e5.png

枚举里面定义的串口事件,具体如下:

APP_UART_DATA_READY:串口接收到数据并已存入缓冲区,可通过app_uart_get()函数来读取数据。

APP_UART_FIFO_ERROR:表示串口的FIFO缓冲区发生错误,错误的代码可以通过app_uart_evt_t.data.error_code这个变量查看。

APP_UART_COMMUNICATION_ERROR:串口通信发生错误,错误的代码可以通过app_uart_evt_t.data.error_communication这个变量查看。

APP_UART_TX_EMPTY:表示发送缓冲区的数据以及全部发送完成。

APP_UART_DATA:表示串口收到数据。这个事件仅限在不使用缓冲区的情况下使用。

7、串口事件处理的回调函数,如下图所示。

d4628e76123ec01518c175768173712a.png

这个回调函数处理了串口所有的事件,用户可以在这个函数里面处理串口接收到的数据,上述代码是把串口接收到的数据,原包发送出去,实现一个串口收发回环。

8、SDK里面提供两个函数来处理串口数据收发,app_uart_put()函数用来发送数据,app_uart_get()函数用来接收数据。这两个函数都是单字节操作函数。需要注意的是,这两个函数操作的时候,都是非阻塞的。也就是说,当使用app_uart_put()函数发送一个数据的时候,发送成功是表示写入发送缓存成功,不表示数据已经通过物理线路发送成功。当使用app_uart_get()函数来接收数据的时候,如果缓冲区为空,将返回错误代码。

9、最后配置sdk_config.h文件,勾选NRFX_UARTE_ENABLED宏和UART_ENABLED宏,不勾选NRF_UARTE_ENABLED宏,使能UARTE模块的相关代码,如下图所示。

419040836404b5ec6e968e389968441e.png

10、连接好开发板,点击“Debug->Go”或按F5,即可编译程序并且把程序下载到开发板运行,使用串口收发工具,不断向开发板串口发送数据。程序的运行情况如以下图所示。

bf23f98e4a798262853b411d78e926fe.png

11、源码下载链接:

https://github.com/embediot/bluetooth_low_energy

感谢阅读!

-- END --


欢迎关注 --- 微联智控工作室

8c5781035eb8fabcca1f562ad89f7f1c.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值