2

I'm playing around with reading in analogue inputs from an MCP3208 ADC via SPI. However, reading multiple inputs seems to cause a seg fault unless I reinitialise the SPI on each read/write.

I've attached my 3208 interface code (which is heavily based off Adafruit's 3008 library). I haven't been able to setup a debug environment, so I don't have any insights on what goes on when it crashes. Is there anything I'm missing?

#include "mcp3208.hpp"
#include "hardware/gpio.h"

MCP3208::MCP3208(spi_inst_t *spi, int cs, int sck, int miso, int mosi)
{
    //spi_init(spi, 1000000);

    gpio_set_function(sck, GPIO_FUNC_SPI);
    gpio_set_function(miso, GPIO_FUNC_SPI);
    gpio_set_function(mosi, GPIO_FUNC_SPI);

    gpio_init(cs);
    gpio_set_dir(cs, GPIO_OUT);
    cs_deselect();

    _cs = cs;
    _sck = sck;
    _miso = miso;
    _mosi = mosi;
    _spi = spi;
    _baudrate = 1000000;
}

MCP3208::~MCP3208()
{
    spi_deinit(_spi);
}

void MCP3208::cs_select() 
{
    asm volatile("nop \n nop \n nop");
    gpio_put(_cs, 0);  // Active low
    asm volatile("nop \n nop \n nop");
}

void MCP3208::cs_deselect() 
{
    asm volatile("nop \n nop \n nop");
    gpio_put(_cs, 1);
    asm volatile("nop \n nop \n nop");
}

uint16_t MCP3208::scale(uint16_t scale_in, uint16_t old_min, uint16_t old_max, uint16_t new_min, uint16_t new_max)
{
    //Scales to 16 bit by default
    return (((scale_in - old_min) * (new_max - new_min)) / (old_max - old_min)) + new_min;
}

uint16_t MCP3208::read_adc(int channel)
{
    if (channel < 0 || channel > 7)
    {
        return 0;
    }

    uint8_t command = 0b11 << 6;
    command |= (channel & 0x07) << 3;

    uint8_t write_buff[3] = {command, 0x0, 0x0};
    uint8_t read_buff[3];

    // may need to fix this requirement to init then deinit deinit
    spi_init(_spi, _baudrate); //todo: remove

    cs_select();
    spi_write_read_blocking(_spi, write_buff, read_buff, 3);
    cs_deselect();

    spi_deinit(_spi); //todo: remove

    uint16_t result = (read_buff[0] & 0x01) << 11;
    result |= (read_buff[1] & 0xFF) << 3;
    result |= (read_buff[2] & 0xE0) >> 5;
        
    return result;
}
1
  • I don't see any executable code
    – Milliways
    Commented Jan 5, 2023 at 11:06

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.