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