Hi all,
I am currently building I2C communication between nrf52832 and a stm32 chip, stm32 as the master and nrf52 as the slave.
The situation is the stm32 couldn't get the data from the nrf52 but I can actually the data flowing through the SDA channel via the oscilloscope.
When I change the slave to another sensor with I2C, the stm32 can receive the data from the sensor so I guess my stm32 code is good and the problem might be in the code of the nrf52.
But another weird thing is, when I use the arduino as the master and nrf52 as the slave, the arduino can receive the data from the nrf52.
I really have no idea what is wrong. Any suggestion would help.
Thanks in advance,
Duncan
Here is code for the nrf52 and the image from the oscilloscope.
#include <stdint.h> #include <stdio.h> #include <string.h> #include "nordic_common.h" #include "nrf_sdh.h" #include "nrf_sdh_ble.h" #include "app_timer.h" #include "bsp_btn_ble.h" #include "ble.h" #include "ble_hci.h" #include "ble_advdata.h" #include "ble_advertising.h" #include "ble_conn_params.h" #include "ble_db_discovery.h" #include "ble_lbs_c.h" #include "ble_conn_state.h" #include "nrf_ble_gatt.h" #include "nrf_pwr_mgmt.h" #include <ble_types.h> #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "nrfx_twis.h" //header file for twis #include "nrf_drv_twis.h" #define APP_BLE_CONN_CFG_TAG 1 /**< A tag that refers to the BLE stack configuration we set with @ref sd_ble_cfg_set. Default tag is @ref APP_BLE_CONN_CFG_TAG. */ #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */ #define SCAN_INTERVAL 0x0100 /**< Determines scan interval in units of 0.625 millisecond. */ #define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */ #define SCAN_DURATION 0x0000 /**< Duration of the scanning in units of 10 milliseconds. If set to 0x0000, scanning will continue until it is explicitly disabled. */ #define target_uuid 0xAA10 // the 16 bit uuid of the target device, or the 12 and 13 octetcs of the 128 bit uuid(be careful to the order) #define NRF_LOG_ENABLED 1 #define NRF_LOG_DEFAULT_LEVEL 3 /* TWI instance ID. */ #define TWIS_INST_ID 0 #define MASTER_ADDR0 0x29 #define MASTER_ADDR1 0 #define NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL 0 #define NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL 0 const uint8_t peer_address[6] = {0x00,0x78,0xB9,0X48,0XB4,0XB0}; static int8_t m_rssi; //the varible used to store the signal strenth from the advertising report of the target device //static char const m_target_periph_name[] = "Beacon"; /**< Name of the device we try to connect to.*/ static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; /**< buffer where advertising reports will be stored by the SoftDevice. */ /**@brief Pointer to the buffer where advertising reports will be stored by the SoftDevice. */ static ble_data_t m_scan_buffer = { m_scan_buffer_data, BLE_GAP_SCAN_BUFFER_MIN }; /**@brief Scan parameters requested for scanning and connection. */ static ble_gap_scan_params_t const m_scan_params = { .active = 0, .interval = SCAN_INTERVAL, .window = SCAN_WINDOW, .timeout = SCAN_DURATION, .scan_phys = BLE_GAP_PHY_1MBPS, .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, }; /* TWIS instance. */ static const nrfx_twis_t m_twis = NRFX_TWIS_INSTANCE(TWIS_INST_ID); /* Buffer for samples would be sent. */ const int8_t *m_data_buffer=&m_rssi; int8_t received_value; /**@brief Function to handle asserts in the SoftDevice. * * @details This function will be called in case of an assert in the SoftDevice. * * @warning This handler is an example only and does not fit a final product. You need to analyze * how your product is supposed to react in case of Assert. * @warning On assert from the SoftDevice, the system can only recover on reset. * * @param[in] line_num Line number of the failing ASSERT call. * @param[in] p_file_name File name of the failing ASSERT call. */ void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) { app_error_handler(0xDEADBEEF, line_num, p_file_name); } /** * @brief TWIS events handler. */ void twis_handler(nrfx_twis_evt_t const * p_event) { switch (p_event->type) { //if get a reading request from the master case NRFX_TWIS_EVT_READ_REQ: if(p_event->data.buf_req) { nrfx_twis_tx_prepare(&m_twis,m_data_buffer, sizeof(m_data_buffer)); NRF_LOG_INFO("TWIS get data transfer request.\n"); } break; //once the reading is succfully done, clear the data buffer case NRFX_TWIS_EVT_READ_DONE: //memset(m_data_buffer, 0x00, sizeof(m_data_buffer)); NRF_LOG_INFO("TWIS data transfer done.\n"); break; case NRFX_TWIS_EVT_WRITE_REQ: if(p_event->data.buf_req) { nrfx_twis_rx_prepare(&m_twis, &received_value, sizeof(&received_value)); } break; case NRFX_TWIS_EVT_WRITE_DONE: break; default: break; } } /** * @brief twis initialization. */ void twis_init (void) { ret_code_t err_code; const nrfx_twis_config_t m_twis_config = { .addr = {MASTER_ADDR0, MASTER_ADDR1}, .scl = 27, .sda = 26, .interrupt_priority = APP_IRQ_PRIORITY_HIGH, }; err_code = nrfx_twis_init(&m_twis, &m_twis_config, twis_handler); APP_ERROR_CHECK(err_code); nrfx_twis_enable(&m_twis); NRF_LOG_INFO("TWIS initiation success.\n"); } /**@brief Function to start scanning. */ static void scan_start(void) { ret_code_t ret; (void) sd_ble_gap_scan_stop(); //NRF_LOG_INFO("Start scanning for device name %s.", (uint32_t)m_target_periph_name); ret = sd_ble_gap_scan_start(&m_scan_params, &m_scan_buffer); APP_ERROR_CHECK(ret); } /**@brief Function for handling the advertising report BLE event. * * @param[in] p_adv_report Advertising report from the SoftDevice. */ static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report) { uint8_t j=0; //variable for printing out the peer address from the advertising report of our target device uint8_t p_peer_address[6]; ret_code_t err_code; //print out the peer address of the target device while (j<6) { p_peer_address[j]=p_adv_report->peer_addr.addr[j]; j++; } // searching the device uuid, only works when the target uuid is specified as the type 0x02 // we can use other feature to do the matching, like device name, manufature specified data, peer address...... if (peer_address[0]==p_peer_address[0]&& peer_address[1]==p_peer_address[1]&& peer_address[2]==p_peer_address[2]&& peer_address[3]==p_peer_address[3]&& peer_address[4]==p_peer_address[4]&& peer_address[5]==p_peer_address[5]) { m_rssi = p_adv_report->rssi;//taking the rssi value NRF_LOG_INFO("my_RSSI: %d",m_rssi); } err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); APP_ERROR_CHECK(err_code); } /**@brief Function for handling BLE events. * * @param[in] p_ble_evt Bluetooth stack event. * @param[in] p_context Unused. */ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) { //ret_code_t err_code; // For readability. ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; switch (p_ble_evt->header.evt_id) { //once receive the advertising report, implement the report handler //potential changed: directly receive RSSI report might be more sensitive case BLE_GAP_EVT_ADV_REPORT: on_adv_report(&p_gap_evt->params.adv_report); break; default: // No implementation needed. break; } } /**@brief Function for initializing the BLE stack. * * @details Initializes the SoftDevice and the BLE event interrupts. */ static void ble_stack_init(void) { ret_code_t err_code; err_code = nrf_sdh_enable_request(); APP_ERROR_CHECK(err_code); // Configure the BLE stack using the default settings. // Fetch the start address of the application RAM. uint32_t ram_start = 0; err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); APP_ERROR_CHECK(err_code); // Enable BLE stack. err_code = nrf_sdh_ble_enable(&ram_start); APP_ERROR_CHECK(err_code); // Register a handler for BLE events. NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); } /**@brief Function for initializing power management. */ static void power_management_init(void) { ret_code_t err_code; err_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(err_code); } /**@brief Function for handling the idle state (main loop). * * @details Handle any pending log operation(s), then sleep until the next event occurs. */ static void idle_state_handle(void) { if (NRF_LOG_PROCESS() == false) { nrf_pwr_mgmt_run(); } } /** @brief Function for initializing the log module. */ static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); } int main(void) { // Initialize. log_init(); power_management_init(); ble_stack_init(); ble_conn_state_init(); twis_init(); // Start execution. NRF_LOG_INFO("BLE and I2C started."); scan_start(); for (;;) { idle_state_handle(); } }
From the oscilloscope, I can see the stm32 sent the start condition, stop condition, the slave address, the write or read command; the nrf52 sent the ACK to appropriate positions and data.