UART Sample Code for Receiving Transmission

Hello, I currently have UART code that can transmit a character. However, I am wondering if there's any sample code for receiving a UART transmission? Thank you!

#include <nrf.h>

#define PIN_TXD        (6)
#define PIN_RXD        (8)

int main(void)
{
  uint8_t hello_world[] = "Hello World!\n";
  
  // Configure the UARTE with no flow control, one parity bit and 115200 baud rate
  NRF_UARTE0->CONFIG = (UART_CONFIG_HWFC_Disabled   << UART_CONFIG_HWFC_Pos) |
                       (UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos); 
  
  NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud115200 << UARTE_BAUDRATE_BAUDRATE_Pos;
  
  // Select TX and RX pins
  NRF_UARTE0->PSEL.TXD = PIN_TXD;
  NRF_UARTE0->PSEL.RXD = PIN_RXD;
  
  // Enable the UART (starts using the TX/RX pins)
  NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos;
  
  // Configure transmit buffer and start the transfer
  NRF_UARTE0->TXD.MAXCNT = sizeof(hello_world);
  NRF_UARTE0->TXD.PTR = (uint32_t)&hello_world;
  NRF_UARTE0->TASKS_STARTTX = 1;
  
  // Wait until the transfer is complete
  while (NRF_UARTE0->EVENTS_ENDTX == 0)
  {
  }
  
  // Stop the UART TX
  NRF_UARTE0->TASKS_STOPTX = 1;
  // Wait until we receive the stopped event
  while (NRF_UARTE0->EVENTS_TXSTOPPED == 0);
  
  // Disable the UARTE (pins are now available for other use)
  NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos;
  
  while (1)
  {
    __WFE();
  }
}

I also noticed that my UART code for transmission only transmits 1 byte and not the entire string. In this case, it only transmits "H". Is there a way to have it transmit more than 8 bits? 

Parents Reply Children
  • Try this; I wrote this code to test different baud rates but it does what you are looking for I think, just choose a single baud rate; note you can use the Tx pin as the Rx pin for loopback testing without another device such as a PC (I set Loopback mode in this snippet):

    static void SetupUART(const uint32_t BaudRate);
    static void StartUART_Transmit(const uint8_t * const pMsg, const uint16_t MsgLength);
    static void DisableUART(void);
    static uint16_t SetupUART_Receive(uint8_t * const pMsg, const uint16_t MaxMsgLength);
    static uint16_t WaitUART_Receive(void);
    
    static NRF_UARTE_Type *pUART = NRF_UARTE0;
    
    #define PIN_UART_TX         PIN_FEATHER_TXD
    #define PIN_UART_RX         PIN_FEATHER_RXD
    #define MAX_TX_PACKET_SIZE  256 //2048
    
    static uint8_t TxMsg[MAX_TX_PACKET_SIZE] = "Baudrate generator for the UART is the top 20 bits of a 32-bit field; add in rounding 0.5 ls bit";
    #define TX_PACKET_SIZE sizeof(TxMsg)
    #define RX_PACKET_SIZE (TX_PACKET_SIZE - 1)
    static uint8_t RxMsg[RX_PACKET_SIZE] = "";
    uint32_t RequiredBaudRate = 1000000UL;
    uint32_t MaxOkdBaudRate = 0UL;
    uint32_t CalculatedRegisterValue;
    uint32_t RegisterValueAtMaxBaud = 0;
    uint64_t SystemClock = 16000000ULL;    // Typically 16MHz
    uint64_t MagicScaler = 32;             // Preserves bits on divisions, shift 32 bits
    
    void UART_BaudTest(void)
    {
       // Enable crystal osc for 3rd party serial devices, don't care for Loopback testing
       //for (RequiredBaudRate = 1000000; RequiredBaudRate < 2000000; )
       {
          //  Baudrate generator for the UART is the top 20 bits of a 32-bit field; add in rounding 0.5 ls bit
          CalculatedRegisterValue = (uint32_t)(((((uint64_t)RequiredBaudRate << MagicScaler) + (SystemClock >> 1)) / SystemClock) + 0x800) & 0xFFFFF000;
          // Setup UART from scratch for each baud rate test
          SetupUART(CalculatedRegisterValue); // NRF_UART_BAUDRATE_230400);
          SetupUART_Receive(RxMsg, sizeof(RxMsg));
          StartUART_Transmit(TxMsg, TX_PACKET_SIZE);
          WaitUART_Receive();
          DisableUART();
          if ((memcmp(TxMsg, RxMsg, RX_PACKET_SIZE) == 0) && (pUART->EVENTS_ERROR == 0) && (pUART->ERRORSRC == 0x0000))
          {
             MaxOkdBaudRate = RequiredBaudRate;
             RegisterValueAtMaxBaud = CalculatedRegisterValue;
             //break;
          }
          RequiredBaudRate += 20;
       }
       while (1)
          ;
    }
    
    static void SetupUART(const uint32_t BaudRate)
    {
       // Disable the UARTE
       pUART->ENABLE = 0;
       // Configure UARTE with no flow control, no parity bit and selected baud rate
       pUART->CONFIG = 0;
       pUART->BAUDRATE = BaudRate;
       // Select TX and RX pin default disconnected mode to avoid sending break indication on disabling uart
       nrf_gpio_cfg(PIN_UART_RX, NRF_GPIO_PIN_DIR_INPUT,  NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);
       nrf_gpio_cfg(PIN_UART_TX, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
       // Select TX and RX pins; note for Loopback testing or 1-wire or RS485 a single pin can be used for both Rx and Tx
       pUART->PSEL.TXD = PIN_UART_TX;
       pUART->PSEL.RXD = PIN_UART_TX;  // For single pin loopback use PIN_UART_TX here, normal uart use PIN_UART_RX
       // Disable all interrupts and clear events
       pUART->INTENCLR = 0xFFFFFFFFUL;
       pUART->EVENTS_TXSTARTED = 0;
       pUART->EVENTS_TXSTOPPED = 0;
       pUART->EVENTS_RXSTARTED = 0;
       pUART->EVENTS_ERROR = 0;
       pUART->ERRORSRC = 0x000F;    // Write '1's to clear any errors left set
       pUART->EVENTS_ENDTX = 0;
       pUART->EVENTS_ENDRX = 0;
       // Enable the UART, note 0x04 for UART and 0x08 for UARTE with DMA
       pUART->ENABLE = 0x08;
    }
    STATIC_ASSERT (UARTE_ENABLE_ENABLE_Enabled == 0x08, "UARTE_ENABLE_ENABLE_Enabled == 0x08 Failed");
    
    static void StartUART_Transmit(const uint8_t * const pMsg, const uint16_t MsgLength)
    {
       // Configure transmit buffer and start the transfer
       pUART->TXD.MAXCNT = MsgLength;
       pUART->TXD.PTR    = (uint32_t)pMsg;
       pUART->TASKS_STARTTX = 1;
       __DSB();
       // Wait until the transfer start event is indicated
       while (pUART->EVENTS_TXSTARTED == 0) ;
       // Wait until the transfer is complete
       while (pUART->EVENTS_ENDTX == 0) ;
       // Stop the UART TX
       pUART->TASKS_STOPTX = 1;
       __DSB();
       // Wait until we receive the stopped event
       while (pUART->EVENTS_TXSTOPPED == 0) ;
    }
    
    static void DisableUART(void)
    {
       // Disable the UARTE
       pUART->ENABLE = 0;
       // De-Select TX and RX pins
       pUART->PSEL.TXD = 0x80000000;
       pUART->PSEL.RXD = 0x80000000;
    }
    
    static uint16_t SetupUART_Receive(uint8_t * const pMsg, const uint16_t MaxMsgLength)
    {
       volatile uint32_t Timeout;
       // Clear receive buffer
       memcpy(pMsg, "-----------------", MaxMsgLength);
       // Configure receive buffer and start reception
       pUART->RXD.MAXCNT = MaxMsgLength;
       pUART->RXD.PTR    = (uint32_t)pMsg;
       pUART->EVENTS_ENDRX = 0;
       pUART->TASKS_STARTRX = 1;
       __DSB();
       // Wait until the transfer start event is indicated
       while (pUART->EVENTS_RXSTARTED == 0) ;
       return 0;
    }
    
    static uint16_t WaitUART_Receive(void)
    {
       // Wait until the transfer is complete
       //while (pUART->EVENTS_ENDRX == 0) ; //add timeout here also add LEDs blinking during tests
       // or just delay a bit ..
       nrf_delay_ms(1);
       // Stop the UART RX
       pUART->TASKS_STOPRX = 1;
       __DSB();
       // Wait until we receive the stopped event
       //while (pUART->EVENTS_ENDRX == 0) ;
       return 0;
    }

Related