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;
}

  • Also is there a way for me to delete this code once I get an answer?

  • 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 am 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.

  • 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.

  • I don't know why setting pin14 to low works. Actually I wanted you to have a look at the ble_app_uart example, but if this is working, I guess it is fine. 

    Regarding pin 14, I suggest you try to debug to see why it is not working. Is the main() function reached? If yes, you should check the return values for the functions that returns something, such as nrf_uarte_configure(). What do they return? (not only nrf_uarte_configure, but pretty much all your uart related functions). 

    I also see that you don't have a while loop in your main function:

        while(1) {
          break;
        }

    This will break out of the while loop on entry, and then skip to "return 0;", and at that point your application is "done". It is not defined what the chip should do then. Perhaps you added some more code to the while loop when you also added the pin 14 part, which made it work?

Related