蓝牙芯片nRF51822开发系列(二):UART及内置温度传感器详解与使用

蓝牙芯片nRF51822开发系列(二):UART及内置温度传感器详解与使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

蓝牙芯片nRF51822开发系列(二):UART及内置温度传感器详解与使用前言(文章末尾获取工程源码)一、UART详解1.UART结构2.寄存器二、使用步骤(在上一篇文章的工程基础下)1.初始化2.发送和接收数据3.测试4.使用printf打印三、内置温度传感器四、获取工程源码

前言(文章末尾获取工程源码)通用异步收发传输器(UART),是SoC重要的通信方式。不仅能用来开发调试,甚至还可以做成透传功能。本次结合nRF51822内置的温度传感器进行实验。

一、UART详解1.UART结构

上图为nRF51822的UART结构图。nRF51822没有固定的引脚,故使用时需要指定4个物理管脚,包括TXD,RXD,CTS,RTS。RXD接收端有6个字节的FIFO缓存,CTS和RTS用于流量控制,当RXD的FIFO即将溢出时,防止因为溢出造成数据丢失,RTS会输出相应的电平信号通知发送方。CTS作用同理,由于在实际应用中很少使用,故将CTS和RTS置0xFFFFFFFF,使其失能。

2.寄存器寄存器详解:

STARTTX(STARTRX):开始发送(接收)任务;STOPTX(STOPRX):停止发送(接收)任务;PSELRTS(PSELRTS):置0xFFFFFFFF,失能;PSELTXD(PSELRXD):取值[0…31],指定物理管脚;TXDRDY、RXDRDY:TXD每写入一字节数据,就会产生TXDRDY事件;有数据进入到RXD,就会产生RXDRDY事件。二、使用步骤(在上一篇文章的工程基础下)1.初始化初始化需要设置管脚的GPIO方向和相关寄存器,如下图。

无中断方式:

void uart_init(){

nrf_gpio_cfg_input(UART_RX, NRF_GPIO_PIN_NOPULL);

nrf_gpio_cfg_output(UART_TX); //设置管脚方向

NRF_UART0->PSELRXD = UART_RX;

NRF_UART0->PSELTXD = UART_TX;

NRF_UART0->PSELRTS = 0XFFFFFFFF;

NRF_UART0->PSELCTS = 0XFFFFFFFF; //指定物理管脚

NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; //设置波特率

NRF_UART0->CONFIG = 0; //无流量控制

NRF_UART0->EVENTS_RXDRDY = 0;

NRF_UART0->EVENTS_TXDRDY = 0; //清除事件

NRF_UART0->ENABLE = 4; //使能UART

NRF_UART0->TASKS_STARTRX = 1;

NRF_UART0->TASKS_STARTTX = 1; //开始任务

}

中断方式:

void uart_irq_init(){

nrf_gpio_cfg_input(UART_RX, NRF_GPIO_PIN_NOPULL);

nrf_gpio_cfg_output(UART_TX);

NRF_UART0->PSELRXD = UART_RX;

NRF_UART0->PSELTXD = UART_TX;

NRF_UART0->PSELRTS = 0XFFFFFFFF;

NRF_UART0->PSELCTS = 0XFFFFFFFF;

NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;

NRF_UART0->CONFIG = 0;

NRF_UART0->EVENTS_RXDRDY = 0;

NRF_UART0->EVENTS_TXDRDY = 0;

NRF_UART0->INTENSET = 1 << 2; //开启接收中断

NRF_UART0->ENABLE = 4;

NRF_UART0->TASKS_STARTRX = 1;

NRF_UART0->TASKS_STARTTX = 1;

NVIC_SetPriority(UART0_IRQn, 1);

NVIC_ClearPendingIRQ(UART0_IRQn);

NVIC_EnableIRQ(UART0_IRQn); //系统开启中断

}

2.发送和接收数据需要注意的是,无论发送和接收,都要把TXDRDY或RXDRDY事件清除。

void uart_send_byte(uint8_t data ){

NRF_UART0->EVENTS_TXDRDY = 0;

NRF_UART0->TXD = data;

while(NRF_UART0->EVENTS_TXDRDY == 0);

}

uint8_t uart_recive_byte(uint8_t *data)

{

if(NRF_UART0->EVENTS_RXDRDY != 0){

NRF_UART0->EVENTS_RXDRDY = 0;

*data = (uint8_t)NRF_UART0->RXD;

return 1;

}

return 0;

}

3.测试无中断方式:

int main(){

uart_init();

char data[] = "程序猿Aki";

while(1){

for(int i = 0; data[i]!='\0';i++)

uart_send_byte(data[i]);

nrf_delay_ms(1000);

}

}

中断方式:以接收为中断,接收到一个数据就发送这个数据。

int main(){

uart_irq_init();

while(1){

nrf_delay_ms(1000);

}

}

//中断处理函数

void UART0_IRQHandler(){

uint8_t str;

if(uart_recive_byte(&str))

uart_send_byte(str);

}

4.使用printf打印重定向fputc函数,串口发送更方便。

int fputc(int ch, FILE *f)

{

uart_send_byte((unsigned char) ch);

return (ch);

}

三、内置温度传感器 启动START任务开始测量,STOP任务停止测量。测量完成后,产生DATARDY事件,表明数据已经在TEMP寄存器准备好。使用HFCLK为时钟源时测量更加精确。测量完成后,传感器模拟电路自动关闭节省功耗。所以开始一次START任务,只会测量一次,测量完成后自动关闭。下次测量需要重新开启START任务。 精度为0.25摄氏度,最后结果需要乘以 0.25。

void temp_read(){

int32_t temp;

NRF_TEMP->TASKS_START = 1;

while(NRF_TEMP->EVENTS_DATARDY == 0);

temp = NRF_TEMP->TEMP;

printf("temp = %d °C",temp/4);

}

四、获取工程源码关注下方公众号,查看相关文章底部获取源码;若有疑问,请在公众号回复“交流群”,进群一起讨论分享!

参考资料:nrf51822裸机教程-UART http://blog.chinaunix.net/uid-28852942-id-5705447.html谭晖. 低功耗蓝牙技术快速入门[M]. 北京航空航天大学出版社, 2016.

相关推荐