第四篇 串口通信

来源:互联网 发布:mdac数据库访问控件 编辑:程序博客网 时间:2024/06/06 07:10
在单片机程序开发中除了单步调试外,最有效的调试方法算是打印调试了,所以这里先把串口功能调试好,也方便以后的调试开发。

nRF51822带有一个UART接口,但是没有固定的TX、RX引脚,是可以任意配置到不同的IO引脚上,这也为硬件上连线提供了方便。

Ok,我们在蓝牙样板程序中增加UART功能。

首先是串口初始化,串口初始化可以使用simple_uart.c提供的simple_uart_config()函数,但这是不带中断的,还需要自己编写一个UART0_IRQHandler()中断处理函数并做相应的配置。

如果只是简单的打印调试信息的话可以使用这种方式,这种方式也是单片机常见的写法。

但这里我们不打算使用这个接口,而使用app_uart_fifo.c中的app_uart_init()函数来做初始化,这里也可以使用宏APP_UART_FIFO_INIT。

uart部分代码如下:
#include <stdio.h>#include <nrf51.h>#include <app_uart.h>#include <nrf51_bitfields.h>#include <boards.h>#include "uart.h"#define UART_RX_BUF_SIZE 256#define UART_TX_BUF_SIZE 256void uart_event_handler(app_uart_evt_t *event){uint8_t tmp;switch (event->evt_type) {case APP_UART_DATA_READY:app_uart_get(&tmp);printf("%c", tmp);break;case APP_UART_FIFO_ERROR:break;case APP_UART_COMMUNICATION_ERROR:break;default:break;}}void uart_init(void){uint32_t err_code;app_uart_comm_params_t comm_params = {RX_PIN_NUMBER,TX_PIN_NUMBER,0,0,APP_UART_FLOW_CONTROL_DISABLED,false,UART_BAUDRATE_BAUDRATE_Baud115200};APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_event_handler,APP_IRQ_PRIORITY_HIGH,err_code);APP_ERROR_CHECK(err_code);}int fputc(int c, FILE *stream){return app_uart_put((uint8_t)c);}

这部分代码主要有两部分:一是串口初始化部分,二是串口事件回调函数部分。

大家也可以去看一下app_uart_fifo.c中的代码,根据名字来看串口的发送和接收都有一个fifo,我们只需要配置这个fifo的大小就可以了。在app_uart_fifo.c中也有一个中断处理函数UART0_IRQHandler(),发送和接收都使用的中断方式,当接收到一个数据的时候会调用这里的uart_event_handler()这个事件回调函数,并发送事件消息APP_UART_DATA_READY。

在uart_event_handler()函数中,我们为了验证接收到的数据是否正确,在接收到数据的同时也把这个数据给打印出来了。

再来说printf函数,这是一个系统库函数,要使用这个函数,首先得实现fputc()函数,然后还需要在Keil中勾选Use MicroLIB库,配置如下:

好了,在main()函数中我们只需要调用uart_init()函数做初始化,然后就可以使用printf()来打印调试信息了,main()函数部分如下:

int main(void){    // Initialize    uart_init();    leds_init();    timers_init();    gpiote_init();    buttons_init();    ble_stack_init();    scheduler_init();        gap_params_init();    advertising_init();    services_init();    conn_params_init();    sec_params_init();    printf("Initialize end\r\n");    // Start execution    timers_start();    advertising_start();    // Enter main loop    for (;;)    {        app_sched_execute();        power_manage();    }}