UARTE.h

I was at 1st trying to use libuarte and it worked. However, talking to Edvin has convinced me to use something else as it is very resource heavy and I do not particularly need libuarte. So, I moved to uarte. I found no coding example of uarte online or in the SDK file. However, I found a description of it in the datasheet and I analyzed the uarte.h file and understood the library as much as I could. 

UARTE description that I used can be found here: infocenter.nordicsemi.com/index.jsp

Things I need to achieve: 

1) Send ASCII transmission of "0GYTP/r" to a motion controller

2) Recieve the corresponding response of the transmission from a motion controller

Here is the code, I feel I covered everything and still it does not work. I do not get the output which is "MCDC3002-RS/r/n". I know the error is not in my device setup because I receive a response with libuarte. 

Here is my code please help. 

#include <app_error.h>
#include <app_util_platform.h>
#include <nrf.h>
#include <nrf_gpio.h>
#include <nrf_gpiote.h>
#include <nrf_log.h>
#include <nrf_log_ctrl.h>
#include <nrf_log_default_backends.h>
#include <nrf_nvic.h>
#include <nrf_rtc.h>
#include <nrf_soc.h>
#include <nrf_uarte.h>
#include <nrfx.h>
#include <nrfx_gpiote.h>
#include <nrfx_ppi.h>
#include <nrfx_pwm.h>
#include <nrfx_saadc.h>
#include <nrfx_spim.h>
#include <nrfx_twi.h>

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#define MCDC_comms NRF_UARTE0
#define RX_BUF_LEN 32
#define Tx_pin 30
#define Rx_pin 31

void memory_barrier() {}

static void uart_validate_MCDC() {
    assert(!nrf_uarte_event_check(MCDC_comms, NRF_UARTE_EVENT_ERROR));
}

void uart_init_MCDC() {
    nrf_uarte_event_clear(MCDC_comms, NRF_UARTE_EVENT_ERROR);
    nrf_uarte_baudrate_set(MCDC_comms, NRF_UARTE_BAUDRATE_9600);
    nrf_uarte_configure(MCDC_comms, NRF_UARTE_PARITY_EXCLUDED, NRF_UARTE_HWFC_DISABLED);
    nrf_uarte_disable(MCDC_comms);
    uart_validate_MCDC();
}

static bool active_rx_has_cr(const char *rx_buf, size_t rx_len) {
    memory_barrier();
    for (size_t i = 0; i < rx_len; ++i) {
        if (rx_buf[i] == '\n') { 
            return true;
        }
    }
    return false;
}

size_t uart_MCDC_txrx(const void *tx_buf, size_t tx_len,void *rx_buf, size_t rx_len) {
    assert(tx_len < 256);
    assert(rx_len < 256);
    
    nrf_uarte_txrx_pins_set(MCDC_comms, Tx_pin, Rx_pin);
    uart_validate_MCDC();
    nrf_uarte_enable(MCDC_comms);
    
    memset(rx_buf, 0, rx_len);
    
    nrf_uarte_tx_buffer_set(MCDC_comms, tx_buf, tx_len);
    nrf_uarte_event_clear(MCDC_comms, NRF_UARTE_EVENT_ENDTX);
    nrf_uarte_rx_buffer_set(MCDC_comms, rx_buf, rx_len);
    nrf_uarte_event_clear(MCDC_comms, NRF_UARTE_EVENT_ENDRX);
    nrf_uarte_task_trigger(MCDC_comms, NRF_UARTE_TASK_STARTTX);
    nrf_uarte_task_trigger(MCDC_comms, NRF_UARTE_TASK_STARTRX);
    uart_validate_MCDC();

    while (!nrf_uarte_event_check(MCDC_comms, NRF_UARTE_EVENT_ENDTX));
    while (!active_rx_has_cr(rx_buf, rx_len));


    nrf_uarte_task_trigger(MCDC_comms, NRF_UARTE_TASK_STOPRX);    
    while (!nrf_uarte_event_check(MCDC_comms, NRF_UARTE_EVENT_ENDRX));

    size_t n_rx = nrf_uarte_rx_amount_get(MCDC_comms);
    nrf_uarte_disable(MCDC_comms);
    return n_rx;
}

int main() {

    char tx_buf[] = "0GTYP\r";
    char rx_buf[RX_BUF_LEN] = {};

    uart_init_MCDC();
    uart_MCDC_txrx(tx_buf, strlen(tx_buf), rx_buf, RX_BUF_LEN);
    while(1) {
      break;
    }
    return 0;
}

Parents Reply Children
  • Hello,

    It doesn't really look like there is any sensitive information in the code, but you should be able to edit the original post. 

    What I was thinking of when I mentioned that the libuarte was a bit resource heavy is that it requires both a timer and an RTC to operate, while for most applications this is a bit overkill.

    I suggest that you look into the ble_app_uart example found in SDK\examples\ble_peripheral\ble_app_uart. Look at how it sets up the uart in uart_init() from main.c, and how the event handler, uart_event_handle() is handling the incoming bytes. Note that this interrupt will trigger on every byte, but the byte will be added to the data_array[] parameter, and it checks whether the last byte is an \n or an \r (or if the buffer is filled). If it is, then it will trigger some action, which in this case is sending the array via ble_nus_data_send(..., data_array, ...).

    You can also see how it writes data on the uart using app_uart_put() inside the nus_data_handler() in main.c. You can do something similar to send the command that you need to send. Alternatively, you can see that it uses printf() in the main() function to send "\r\nUart started.\r\n" when the application is starting. This printf() function is enabled by adding the retarget.c, but if you struggle to get this working in your own custom application, I would suggest that you just use app_uart_put. 

    Best regards,

    Edvin

  • Hello, I found out that adding the following line solves the issue:

    nrf_gpio_cfg_output(14);
    nrf_gpio_pin_write(14, false);

    could you please explain why adding these two lines at the beginning main() function allows for successful communication? Without these 2 lines, I do not get any response. Why pin 14 exactly? I do not see anything that is connected to pin 14.

Related