Hello everyone,
I'm trying to interface a NiceRF LN610 LoRaWAN chip to nRF52840 via UART. Initially, I tried communicating with the chip using CP2102 USB-to-TTL module and RealTerm in a Windows 10 PC and manually entering the commands there (after configuring the port properly). The LN610 chip responds and I get the required values to operate the LoRaWAN chip (see attached image, manual commands in green, chip response in yellow)

I then connected the LN610 TX & RX pins to nRF52840 GPIO pins P1.13 & P1.14, respectively, and then used the UART, SERIAL, and LIBUARTE peripheral examples in SDK16 to communicate with the LN610 chip but I failed to get any response from LN610 in each of the examples.
1. uart peripheral example files
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif
#define MAX_TEST_DATA_BYTES (15U) /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 1 /**< UART RX buffer size. */
void uart_error_handle(app_uart_evt_t * p_event)
{
switch (p_event->evt_type)
{
case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(p_event->data.error_communication);
break;
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(p_event->data.error_code);
break;
case APP_UART_DATA_READY:
printf("APP_UART_DATA_READY");
break;
case APP_UART_TX_EMPTY:
printf("APP_UART_TX_EMPTY");
printf("An event indicating that UART has completed transmission of all available data in the TX FIFO.");
app_uart_flush();
break;
case APP_UART_DATA:
printf("APP_UART_DATA");
printf("An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured.");
break;
default:
break;
}
}
/* When UART is used for communication with the host do not use flow control.*/
#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED
/**
* @brief Function for main application entry.
*/
int main(void)
{
uint32_t err_code;
uint32_t i = 0;
bsp_board_init(BSP_INIT_LEDS);
const app_uart_comm_params_t comm_params =
{
14, /* UART RX <-> LN610 TX */
13, /* UART TX <-> LN610 RX */
UART_PIN_DISCONNECTED,
UART_PIN_DISCONNECTED,
UART_HWFC,
false,
#if defined (UART_PRESENT)
NRF_UART_BAUDRATE_9600
#else
NRF_UARTE_BAUDRATE_9600
#endif
};
APP_UART_FIFO_INIT(&comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_error_handle,
APP_IRQ_PRIORITY_LOWEST,
err_code);
APP_ERROR_CHECK(err_code);
/* Test */
uint8_t tx_data[4] = { 0x24, 0x01, 0x00, 0x25 };
uint8_t rx_data = 0;
uint8_t buff[255];
// Start sending one byte
for (i = 0; i < 4; i++)
{
app_uart_put(tx_data[i]);
}
// Receive data
i = 0;
while (true)
{
app_uart_get(&rx_data);
buff[i++] = rx_data;
if (i % 255)
break;
}
return 0;
}
2. serial peripheral example files
/**
* Copyright (c) 2016 - 2019, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nrf.h"
#include "nrf_drv_clock.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_drv_power.h"
#include "nrf_serial.h"
#include "app_timer.h"
#include "app_error.h"
#include "app_util.h"
#include "boards.h"
/** @file
* @defgroup nrf_serial_example main.c
* @{
* @ingroup nrf_serial_example
* @brief Example of @ref nrf_serial usage. Simple loopback.
*
*/
#define OP_QUEUES_SIZE 3
#define APP_TIMER_PRESCALER NRF_SERIAL_APP_TIMER_PRESCALER
static void sleep_handler(void)
{
__WFE();
__SEV();
__WFE();
}
NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config,
14, /* UART RX <-> LN610 TX */
13, /* UART TX <-> LN610 RX */
NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED,
NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
NRF_UART_BAUDRATE_9600,
UART_DEFAULT_CONFIG_IRQ_PRIORITY);
#define SERIAL_FIFO_TX_SIZE 32
#define SERIAL_FIFO_RX_SIZE 1
NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);
#define SERIAL_BUFF_TX_SIZE 32
#define SERIAL_BUFF_RX_SIZE 1
NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);
NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_DMA,
&serial_queues, &serial_buffs, NULL, sleep_handler);
NRF_SERIAL_UART_DEF(serial_uart, 0);
int main(void)
{
ret_code_t ret;
ret = nrf_drv_clock_init();
APP_ERROR_CHECK(ret);
ret = nrf_drv_power_init(NULL);
APP_ERROR_CHECK(ret);
nrf_drv_clock_lfclk_request(NULL);
ret = app_timer_init();
APP_ERROR_CHECK(ret);
// Initialize LEDs and buttons.
bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);
ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
APP_ERROR_CHECK(ret);
static uint8_t tx_message[] = { 0x24, 0x01, 0x00, 0x25 };
uint8_t response = 0;
uint8_t buff[255] = {0};
size_t bytes_read;
ret = nrf_serial_write(&serial_uart, tx_message, 4, NULL, 500);
APP_ERROR_CHECK(ret);
(void)nrf_serial_flush(&serial_uart, 0);
/*
nrf_serial_uninit(&serial_uart);
nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
nrf_delay_us(1000);
*/
uint32_t i = 0;
while (true)
{
uint8_t c;
nrf_serial_read(&serial_uart, &c, sizeof(c), &bytes_read, 1000);
if (bytes_read)
{
buff[i++] = c;
if ((i % 255) == 0)
break;
}
}
return 0;
}
/** @} */
3. libuarte example files
/**
* Copyright (c) 2018 - 2019, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
* @defgroup libuarte_example_main main.c
* @{
* @ingroup libuarte_example
* @brief Libuarte Example Application main file.
*
* This file contains the source code for a sample application using libuarte.
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "nrf_libuarte_async.h"
#include "nrf_drv_clock.h"
#include <bsp.h>
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"
NRF_LIBUARTE_ASYNC_DEFINE(libuarte0, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);
static volatile bool m_loopback_phase;
typedef struct {
uint8_t * p_data;
uint32_t length;
} buffer_t;
NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);
void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
ret_code_t ret;
switch (p_evt->type)
{
case NRF_LIBUARTE_ASYNC_EVT_ERROR:
bsp_board_led_invert(0);
break;
case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
/*ret = nrf_libuarte_async_tx(p_libuarte,p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
if (ret == NRF_ERROR_BUSY)
{
buffer_t buf = {
.p_data = p_evt->data.rxtx.p_data,
.length = p_evt->data.rxtx.length,
};
ret = nrf_queue_push(&m_buf_queue, &buf);
APP_ERROR_CHECK(ret);
}
else
{
APP_ERROR_CHECK(ret);
}*/
bsp_board_led_invert(1);
m_loopback_phase = true;
break;
case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
if (m_loopback_phase)
{
nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
if (!nrf_queue_is_empty(&m_buf_queue))
{
buffer_t buf;
ret = nrf_queue_pop(&m_buf_queue, &buf);
APP_ERROR_CHECK(ret);
UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
}
}
bsp_board_led_invert(2);
break;
default:
break;
}
}
/**
* @brief Function for main application entry.
*/
int main(void)
{
bsp_board_init(BSP_INIT_LEDS);
ret_code_t ret = nrf_drv_clock_init();
APP_ERROR_CHECK(ret);
nrf_drv_clock_lfclk_request(NULL);
ret_code_t err_code /*= NRF_LOG_INIT(app_timer_cnt_get);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT()*/;
/* UARTE 0 */
static uint8_t text[] = { 0x24, 0x01, 0x00, 0x25 };
static uint8_t text_size = sizeof(text);
nrf_libuarte_async_config_t nrf_libuarte_async_config0 = {
.tx_pin = 13, /* UART TX <-> LN610 RX */
.rx_pin = 14, /* UART RX <-> LN610 TX */
.baudrate = NRF_UARTE_BAUDRATE_9600,
.parity = NRF_UARTE_PARITY_EXCLUDED,
.hwfc = NRF_UARTE_HWFC_DISABLED,
.timeout_us = 100,
.int_prio = APP_IRQ_PRIORITY_LOW
};
err_code = nrf_libuarte_async_init(&libuarte0, &nrf_libuarte_async_config0, uart_event_handler, (void *)&libuarte0);
APP_ERROR_CHECK(err_code);
nrf_libuarte_async_enable(&libuarte0);
err_code = nrf_libuarte_async_tx(&libuarte0, text, text_size);
APP_ERROR_CHECK(err_code);
while (true)
{
NRF_LOG_FLUSH();
}
}
/** @} */
Also tried using UARTE directly from this instruction from Hung Buihttps://devzone.nordicsemi.com/f/nordic-q-a/58740/data-throughput-between-nrf52810-ble-uart
https://github.com/andenore/NordicSnippets/blob/master/examples/uart/main.c
#include <nrf.h>
#define PIN_TXD (13)
#define PIN_RXD (14)
int main(void)
{
uint8_t hello_world[] = /*"Hello World!\n"*/ { 0x24, 0x01, 0x00, 0x25 };
uint8_t hi_there = 0 /*[255] = { 0 }*/;
// 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_Excluded << UART_CONFIG_PARITY_Pos);
NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud4800 << UARTE_BAUDRATE_BAUDRATE_Pos;
// Select TX and RX pins
NRF_UARTE0->PSEL.TXD = PIN_TXD;
NRF_UARTE0->PSEL.RXD = PIN_RXD;
/*TX*/
// 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[0];
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;
/*RX*/
// Enable the UART (starts using the TX/RX pins)
//NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos;
// Enable the UART RXDRDY interrupt
NRF_UARTE0->INTENSET = UARTE_INTENSET_RXDRDY_Enabled << UARTE_INTENSET_RXDRDY_Pos;
// Enable the UART RXTO interrupt
NRF_UARTE0->INTENSET = UARTE_INTENSET_RXTO_Enabled << UARTE_INTENSET_RXTO_Pos;
// Configure receive buffer and start receiving
NRF_UARTE0->RXD.MAXCNT = /*sizeof(hi_there)*/ 1;
NRF_UARTE0->RXD.PTR = (uint32_t)&hi_there/*[0]*/;
NRF_UARTE0->TASKS_STARTRX = 1;
// Wait until the receive is started
while (NRF_UARTE0->EVENTS_RXSTARTED == UARTE_EVENTS_RXSTARTED_EVENTS_RXSTARTED_NotGenerated)
{
}
// Wait until a data is received
while ( (NRF_UARTE0->EVENTS_RXDRDY == UARTE_EVENTS_RXDRDY_EVENTS_RXDRDY_NotGenerated)
|| (NRF_UARTE0->EVENTS_ENDRX == UARTE_EVENTS_ENDRX_EVENTS_ENDRX_NotGenerated))
{
if (NRF_UART0->EVENTS_RXTO == UARTE_EVENTS_RXTO_EVENTS_RXTO_Generated)
break;
}
// Stop the UART TX
NRF_UARTE0->TASKS_STOPRX = 1;
// Wait until we receive the stopped event
while (NRF_UARTE0->EVENTS_RXTO == 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();
}
}
Would appreciate if someone could point me on what could possibly be wrong with my UART usage?
Thank you,
Carlos