BASIC4MCU | 질문게시판 | spi로 센서 값 읽어오기 해보신분 계신가요?
페이지 정보
작성자 라칸 작성일2022-11-14 16:57 조회807회 댓글1건본문
spi로 센서값 읽어오기를 하고 있는데
spi 1개에 센서 여러개가 연결되어있어서 어려움을 겪고 있는데
간신히 예제를 찾아서 일단 해보려고 했는데
값이 이상하게 나와서요 42'xxx, 60'xxx, 0 이런값이 반복만 되고 있는데 이거 보면 그냥 측정 값 자체를 못가져온거 같은데
일단 센서로 측정하는게 다르더라도(전압, 온도, 습도 등등) 주소가 맞으면 센서의 값을 읽어오는게 아닌가요?
심지어 센서는 2~3개 연결했고 연결 안한곳도 있는데 다 똑같이 증상이라서요
뭐가 문제인지 알려주실수 있으신가요?
SPI_CHN_RANGE하고 SPI_CHANNEL 바꾸거나 다 똑같이 반응하더군요
그냥 채널 설정이 문제인지 아니면 read가 문제인지 진짜 모르겠습니다
참고 주소: https://github.com/obatsis/ADS8688-STM32
코드
[code]
#define SPI_CONT 0x00
#define SPI_STBY 0x82
#define SPI_PWDN 0x83
#define SPI_RST 0x85
#define SPI_AUTO_RST 0xA0
#define SPI_CHANNEL_0 0xC0
#define SPI_CHANNEL_1 0xC4
#define SPI_CHANNEL_2 0xC8
#define SPI_CHANNEL_3 0xCC
#define SPI_CHANNEL_4 0xD0
#define SPI_CHANNEL_5 0xD4
#define SPI_CHANNEL_6 0xD8
#define SPI_CHANNEL_7 0xDC
// Register addresses
#define SPI_AUTO_SEQ_EN 0x01
#define SPI_CHN_PWRDN 0x02
#define SPI_FEATURE_SELECT 0x03
#define SPI_CHN_RANGE_0 0x05
#define SPI_CHN_RANGE_1 0x06
#define SPI_CHN_RANGE_2 0x07
#define SPI_CHN_RANGE_3 0x08
#define SPI_CHN_RANGE_4 0x09
#define SPI_CHN_RANGE_5 0x0A
#define SPI_CHN_RANGE_6 0x0B
#define SPI_CHN_RANGE_7 0x0C
#define CMD_RD_BCK 0x3f
// --------------------------------------------------------------------------- //
#define CHNS_NUM_READ 8
uint8_t SPI_ADS_Init(SPI_ADS *ads, SPI_HandleTypeDef *spiHandle, GPIO_TypeDef *csPinBank, uint16_t csPin) {
/* Store interface parameters in struct */
ads->spiHandle = spiHandle;
ads->csPinBank = csPinBank;
ads->csPin = csPin;
uint8_t ads_data[2] = {0};
uint8_t state = 0;
// reset all registers to default
state += SPI_Cmd_Write(ads, SPI_RST, ads_data);
HAL_Delay(100);
// send a no_op message to the ADS to enter IDLE mode
state += SPI_Cmd_Write(ads, SPI_CONT, ads_data);
HAL_Delay(10);
// enable auto transmit for all inputs(datasheet page 54) or as many as you want
// if you want only some of the inputs enabled, make sure to power down the unused ones
ads_data[0] = 0xff;
state += SPI_Prog_Write(ads, SPI_AUTO_SEQ_EN, ads_data);
HAL_Delay(10);
// set the desired features such as device id (if multiple devices are used), alarm enable/disable and output format
ads_data[0] = 0x00; // here i chose id = 0, alarm = disabled and SDO_format = 3 (datasheet page 56)
state += SPI_Prog_Write(ads, SPI_FEATURE_SELECT, ads_data);
HAL_Delay(10);
ads_data[0] = 0x06;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_0, ads_data);
HAL_Delay(10);
ads_data[0] = 0x06;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_1, ads_data);
HAL_Delay(10);
ads_data[0] = 0x05;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_2, ads_data);
HAL_Delay(10);
ads_data[0] = 0x05;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_3, ads_data);
HAL_Delay(10);
ads_data[0] = 0x05;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_4, ads_data);
HAL_Delay(10);
ads_data[0] = 0x05;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_5, ads_data);
HAL_Delay(10);
ads_data[0] = 0x06;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_6, ads_data);
HAL_Delay(10);
ads_data[0] = 0x06;
state += SPI_Prog_Write(ads, SPI_CHN_RANGE_7, ads_data);
HAL_Delay(10);
// start the auto transmission by entering the appropriate state
state += SPI_Cmd_Write(ads, SPI_AUTO_RST, ads_data);
return state;
}
HAL_StatusTypeDef SPI_Prog_Read(SPI_ADS *ads, uint8_t addr, uint8_t *data) {
HAL_StatusTypeDef ret;
uint8_t txbuf[2] = {0x00, (addr<<1 & 0xfe)}; // [15:9]->address, [8]->0, [7:0]->don't care (0x00) (stm32 uses little endian so reverse it)
uint8_t rxbuf[4];
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_RESET);
ret = HAL_SPI_TransmitReceive(ads->spiHandle, txbuf, rxbuf, 2, 10);
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_SET);
data[0] = rxbuf[2];
data[1] = rxbuf[3];
return ret;
}
// after the write, data should contain the data (byte) written to the addressed register (check equality for evaluation)
HAL_StatusTypeDef SPI_Prog_Write(SPI_ADS *ads, uint8_t addr, uint8_t *data) {
HAL_StatusTypeDef ret;
uint8_t txbuf[2] = {data[0], (addr << 1 | 0x01)}; // [15:9]->address[6:0], [8]->1, [7:0]->data[7:0] (stm32 uses little endian so reverse it)
uint8_t rxbuf[4];
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_RESET);
ret = HAL_SPI_TransmitReceive(ads->spiHandle, txbuf, rxbuf, 2, 10);
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_SET);
data[0] = rxbuf[3];
data[1] = 0x00;
return ret;
}
HAL_StatusTypeDef SPI_Cmd_Write(SPI_ADS *ads, uint8_t cmd, uint8_t *data) {
HAL_StatusTypeDef ret;
uint8_t txbuf[2] = {0x00,cmd}; // [15:9]->address[6:0], [8]->1, [7:0]->data[7:0] (stm32 uses little endian so reverse it)
uint8_t rxbuf[4];
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_RESET);
ret = HAL_SPI_TransmitReceive(ads->spiHandle, txbuf, rxbuf, 2, 10);
HAL_GPIO_WritePin(ads->csPinBank, ads->csPin, GPIO_PIN_SET);
data[0] = rxbuf[2];
data[1] = rxbuf[3];
return ret;
}
HAL_StatusTypeDef SPI_Read_All_Raw(SPI_ADS *ads, uint16_t *data) {
HAL_StatusTypeDef ret;
uint8_t ads_raw[2];
for(int i=0; i < CHNS_NUM_READ; i++) {
ret = SPI_Cmd_Write(ads, SPI_CONT, ads_raw);
data[i] = (int)((uint16_t)(ads_raw[1]<<8 | ads_raw[0]) >> 4);
printf("%04X\n\r", data[i]);
}
printf("\n\r");
return ret;
}
void Uart7_Task(void const * argument){
SPI_ADS_Init(&ads, &hspi2, GPIOB, 9);
/* Infinite loop */
for(;;)
{
SPI_Read_All_Raw(&ads, ads_data);
}
}
[/code]
댓글 1
조회수 807master님의 댓글
master 작성일
https://electronics.stackexchange.com/questions/616353/how-to-use-dma-to-sample-external-adc-16bit-ads8688-using-spi-with-both-single
위 사이트처럼 daisy chain 방식일까요?
저는 해당 칩의 경험이 없어서 도움을 드리지 못합니다.