This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52832 SPI tagging for multi-channel ADC?

Hi,

I have successfully connected an MCP3004 to the nRF52832 and can assign the ADC channel 0 output to a characteristic value. Works beautifully.

However, there are three other channels I want to use on the ADC for other sensors and the method to query the ADC over the SPI bus uses a bitmap to select the channel in the initial query.

The problem is the SPI event that occurs.

I presently will not know which channel is being returned in a given event.

Is there a method to tag the initial transfer with some indicator of which channel is being requested? Perhaps some other clever way?

Maybe having different rx buffers and a map of which buffer pertains to which channel?

Thanks!

Parents
  • Thanks for the response. I was able to get a solution that I will put below for others to maybe use if they have a similar problem.

    I am using SPIM and Easy-DMA. I have some instability in the read ADC values and I am not sure if that's my poor electronics or something else. I was, however, able to use an oscilloscope on the four SPI channels and witness proper SPI correspondence between master and slave. Thus, this is fabulous.

    image description

    I am using SDK 11, not sure why actually, but it's working for me, so I'll stick to it.

    The design I am using makes an array of uint8_t elements that is the (number of channels being used * length of channels). I have two functions (rx_adc_buffer_channel and rx_adc_buffer_address) that can give the array offset given a channel number and its inverse function: given an address return the channel number. This allows me to pass the proper channel rx_buffer to the timer event for the SPI MOSI event and then get the channel after the SPI transfer event or MOSI data.

    I found I couldn't make two writes back-to-back in one timer interval, but this could just be confusion on my part and I should revisit it. However, I don't require an aggressive sample rate so I interleave the channels during ADC read events and this is working.

    I'm just going to paste the code fragments here: (Formatting is terrible; sorry)

    #define ADC_CHANNEL_COUNT               2
    #define ADC_RX_BUFFER_LENGTH            3
    
    static uint8_t*                         rx_adc_channels;
    static uint8_t                          m_channel_toggle;
    static uint16_t                         adc_char_handle_arr[ADC_CHANNEL_COUNT];
    
    
    static uint8_t* rx_adc_buffer_address(uint8_t channel_id) {
        int offset;
        uint8_t* return_addr;
    
        offset = sizeof(uint8_t);
        offset *= ADC_RX_BUFFER_LENGTH;
        offset *= channel_id;
    
        return_addr = rx_adc_channels + offset;
    
        return return_addr;
    }
    
    
    static uint8_t rx_adc_buffer_channel(uint8_t* address) {
        uint8_t channel;
    
        channel = (address - rx_adc_channels) / ADC_RX_BUFFER_LENGTH;
    
        return channel;
    }
    
    
    /* ADC MCP3004 */
    
    static void read_adc(uint8_t* counter) {
        uint8_t tx_length = 3;
        uint8_t rx_length = ADC_RX_BUFFER_LENGTH;
        uint8_t channel;
        uint8_t channel_bitmap;
    
        m_channel_toggle++;
    
        channel = m_channel_toggle % ADC_CHANNEL_COUNT;
       /* Sorry I don't know the escape characters for less than so bitshift left is two lt signs.*/
        channel_bitmap = 128 | (channel (bitshift left) 4);
    
        /* Set SPI Channel */
        m_tx_buf[0] = 1;
        m_tx_buf[1] = channel_bitmap;
        m_tx_buf[2] = 0;
    
        APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, tx_length,
            rx_adc_buffer_address(channel), rx_length));
    }
    
    
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    {
        int _size;
        uint8_t _channel;
        uint16_t _handle;
    
        if (p_event->data.done.rx_length >= 3 ) {
    
            _channel = rx_adc_buffer_channel(p_event->data.done.p_rx_buffer);
            _handle = adc_char_handle_arr[_channel];
    
            rx_adc_buffer_channel(p_event->data.done.p_rx_buffer);
            m_adc_channel0 = (*(p_event->data.done.p_rx_buffer + 2) * 256 ) +
                *(p_event->data.done.p_rx_buffer + 1);
    
            if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
                counter_attr_value.len = 0x02;
                counter_attr_value.offset = 0x00;
                counter_attr_value.p_value = (uint8_t*)&m_adc_channel0;
                sd_ble_gatts_value_set(m_conn_handle, _handle, &counter_attr_value);
             }
        }
    }
    
    
    static void rx_adc_channels_init(void) {
        int size;
    
        size = sizeof(uint8_t) * ADC_CHANNEL_COUNT * ADC_RX_BUFFER_LENGTH;
        rx_adc_channels = (uint8_t*)malloc(size);
        memset(rx_adc_channels, 0, size);
    }
    
Reply Children
No Data
Related