为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。
nRF51822 没有固定的串口引脚 RX 和 TX,与UART相关的信号RXD、CTS、RTS和TXD可根据寄存器:PSELRXD、PSELCTS、PSELRTS和PSELTXD独立配置映射到相应的物理引脚。
RTS (Require ToSend,发送请求:为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。
CTS (Clear ToSend,发送允许:为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。
在 nrf51.h中已有相关定义:
typedef struct { /*!< UART Structure */
__O uint32_t TASKS_STARTRX; /*!< Start UART receiver. */
__O uint32_t TASKS_STOPRX; /*!< Stop UART receiver. */
__O uint32_t TASKS_STARTTX; /*!< Start UART transmitter. */
__O uint32_t TASKS_STOPTX; /*!< Stop UART transmitter. */
__I uint32_t RESERVED0[3];
__O uint32_t TASKS_SUSPEND; /*!< Suspend UART. */
__I uint32_t RESERVED1[56];
__IO uint32_t EVENTS_CTS; /*!< CTS activated. */
__IO uint32_t EVENTS_NCTS; /*!< CTS deactivated. */
__IO uint32_t EVENTS_RXDRDY; /*!< Data received in RXD. */
__I uint32_t RESERVED2[4];
__IO uint32_t EVENTS_TXDRDY; /*!< Data sent from TXD. */
__I uint32_t RESERVED3;
__IO uint32_t EVENTS_ERROR; /*!< Error detected. */
__I uint32_t RESERVED4[7];
__IO uint32_t EVENTS_RXTO; /*!< Receiver timeout. */
__I uint32_t RESERVED5[46];
__IO uint32_t SHORTS; /*!< Shortcuts for UART. */
__I uint32_t RESERVED6[64];
__IO uint32_t INTENSET; /*!< Interrupt enable set register. */
__IO uint32_t INTENCLR; /*!< Interrupt enable clear register. */
__I uint32_t RESERVED7[93];
__IO uint32_t ERRORSRC; /*!< Error source. Write error field to 1 to clear error. */
__I uint32_t RESERVED8[31];
__IO uint32_t ENABLE; /*!< Enable UART and acquire IOs. */
__I uint32_t RESERVED9;
__IO uint32_t PSELRTS; /*!< Pin select for RTS. */
__IO uint32_t PSELTXD; /*!< Pin select for TXD. */
__IO uint32_t PSELCTS; /*!< Pin select for CTS. */
__IO uint32_t PSELRXD; /*!< Pin select for RXD. */
__I uint32_t RXD; /*!< RXD register. On read action the buffer pointer is displaced.
Once read the character is consumed. If read when no character
available, the UART will stop working. */
__O uint32_t TXD; /*!< TXD register. */
__I uint32_t RESERVED10;
__IO uint32_t BAUDRATE; /*!< UART Baudrate. */
__I uint32_t RESERVED11[17];
__IO uint32_t CONFIG; /*!< Configuration of parity and hardware flow control register. */
__I uint32_t RESERVED12[675];
__IO uint32_t POWER; /*!< Peripheral power control. */
} NRF_UART_Type;
波特率 | 对应参数 | 备注 |
---|---|---|
Baud1200 | 0x0004F000 | 1200 baud |
Baud2400 | 0x0009D000 | 2400 baud |
Baud4800 | 0x0013B000 | 4800 baud |
Baud9600 | 0x00275000 | 9600 baud |
Baud14400 | 0x003B0000 | 14400 baud |
Baud19200 | 0x004EA000 | 19200 baud |
Baud28800 | 0x0075F000 | 28800 baud |
Baud38400 | 0x009D5000 | 38400 baud |
Baud57600 | 0x00EBF000 | 57600 baud |
Baud76800 | 0x013A9000 | 76800 baud |
Baud115200 | 0x01D7E000 | 115200 baud |
Baud230400 | 0x03AFB000 | 230400 baud |
Baud250000 | 0x04000000 | 250000 baud |
Baud460800 | 0x075F7000 | 460800 baud |
Baud921600 | 0x0EBEDFA4 | 921600 baud |
Baud1M | 0x10000000 | 1Mega baud |
开启串口发送:
当触发STARTTX任务时,UART传输时序启动。通过写TXD寄存器可以实现字节的发送。当一个字节成功发送的候,UART会产生一个TXDRDY事件,于是新的字节也可以写到TXD寄存器。通过触发STOPTX任务,UART传输时序将会关闭。
开启串口接收:
当触发STARTRX任务时,UART接收时序启动。接收到的字节会被移动到CPU能够提取的RXD寄存器中。RXD寄存器时双缓冲的,当第一个字节被CPU从RXD寄存器中提取走的同时第二个字节可以被接收。每当一个新字节被移入RXD寄存器时UART会产生一个RXDRDY事件。当第一个字节被从RXD寄存器中提取走的时候,第二个字节会被从RXD-1移到RXD寄存器。通过触发STOPRX任务,UART接收时序将会关闭。
**在程序最后,通过触发STARTTX任务和STARTRX任务,开启UART发送和接收。**为了避免因为以前接收到数据而产生的RXDRDY事件导致接收到错误的数据,在最后也需要对EVENTS_RXDRDY清零。但是由于是在字节发送成功之后自动产生TXDRDY事件,对其清不清零并不影响将来的数据发送。
//初始化
void Usart_Init(uint32_t bound)
{
nrf_gpio_cfg_input(USART_RX, NRF_GPIO_PIN_NOPULL);
nrf_gpio_cfg_output( USART_TX);
NRF_UART0->PSELRXD = USART_RX;
NRF_UART0->PSELTXD = USART_TX;
NRF_UART0->PSELRTS = 0XFFFFFFFF;//关闭流控
NRF_UART0->PSELCTS = 0XFFFFFFFF;
NRF_UART0->BAUDRATE = bound;
NRF_UART0->CONFIG = 0; //不使用流控,不校验
NRF_UART0->EVENTS_RXDRDY = 0;
NRF_UART0->EVENTS_TXDRDY = 0;
NRF_UART0->ENABLE = 4; //使能串口
NRF_UART0->TASKS_STARTRX = 1;
NRF_UART0->TASKS_STARTTX = 1;
}
//发送数据
void Usart_Send_Byte(uint8_t dat)
{
NRF_UART0->EVENTS_TXDRDY = 0;
NRF_UART0->TXD = dat;
while(NRF_UART0->EVENTS_TXDRDY == 0);
}
//接收数据
uint8_t Usart_Recive_Byte(void)
{
while(NRF_UART0->EVENTS_RXDRDY == 0);
NRF_UART0->EVENTS_RXDRDY = 0; //清零事件
return (uint8_t)NRF_UART0->RXD;
}
//发送字符串
void Usart_Send_String(uint8_t *str)
{
uint8_t i=0;
while(str[i]!= '\0')
{
Usart_Send_Byte(str[i]);
i++;
}
}
测试现象:
需在初始化中加入中断初始化:
//中断方式
NVIC_SetPriority(UART0_IRQn, 1);
NVIC_ClearPendingIRQ(UART0_IRQn);
NVIC_EnableIRQ(UART0_IRQn);
中断服务程序:
void UART0_IRQHandler(void)
{
//接收
if(NRF_UART0->EVENTS_RXDRDY != 0)
{
NRF_UART0->EVENTS_RXDRDY = 0;
uart_buf[rx_index++] = (uint8_t)NRF_UART0->RXD;
}
//发送
if(NRF_UART0->EVENTS_TXDRDY != 0)
{
NRF_UART0->EVENTS_TXDRDY = 0;
if(tx_index != 0)
{
NRF_UART0->TXD = uart_buf[tx_index++];
}
}
}
参考:
1.nrf51822裸机教程-UART
2.nRF51822 UART引脚配置