Dear All
Is there any C code sample to use ADS8688 with AVR MCU?
Thanks
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Dear All
Is there any C code sample to use ADS8688 with AVR MCU?
Thanks
Dear Mr Li
Thank you very much for your help. C code is fine I will be able to port for AVR.
My e-mail is reyah@medcotas.com, or reyahabd@aol.com .
Sorry about the delay in my answer.
Best Regards
Reyah
Hi Jhon,
Can you please let me know your mail address? by the way, what's your project and application? thanks.
Regards
Dale Li
Hello Nam Soo Kim,
The mail to you has been rejected by your e-mail provider. Please provide your new contact information. Thanks.
Best regards
Dale
Hello Reyah,
We only have a simple code with C2000, and it's C language. Thanks.
Best regards
Dale
Hello Reyah,
We only have a simple code with C2000, and it's C language. Thanks
Best regards
Dale
/********************** ads8688.c *************************/ #include <stdio.h> #include <stdlib.h> #include "ads8688.h" /* * 可测试范围: * Vref = 4.096V * +-10V 1LSB = 312.50uV * +-5V 1LSB = 156.25uV * +-2.5V 1LSB = 78.125uV * 0-10V 1LSB = 156.25uV * 0-5V 1LSB = 78.125uV * 0-20mA * 4-20mA * +-20mA */ // power_up -> idle // command transfer // /* ADC 各个通道的配置 */ // 通道,输入范围,电压/电流 CHANNEL_CFG_t g_ch_range_cfg[8] = { {ch:CH0, range : BIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH1, range : BIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH2, range : BIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH3, range : BIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH4, range : UNIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH5, range : UNIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH6, range : UNIPOLAR_VREF_2P5, type:VOLTAGE}, {ch:CH7, range : UNIPOLAR_VREF_2P5, type:VOLTAGE}, }; /* * 5个范围 */ SCALE_RANGE_t g_scale_range[7] = { {range:BIPOLAR_VREF_2P5, positive_full_scale: 10.24, negative_full_scale : -10.24, lsb_cnt1 : 312.50}, {range:BIPOLAR_VREF_1P25, positive_full_scale: 5.12, negative_full_scale : -5.12, lsb_cnt1 : 156.25}, {range:BIPOLAR_VREF_0P625, positive_full_scale: 2.56, negative_full_scale : -2.56, lsb_cnt1 : 78.125}, {},//reserved {},//reserved {range:UNIPOLAR_VREF_2P5, positive_full_scale: 10.24, negative_full_scale : 0, lsb_cnt1 : 156.25}, {range:UNIPOLAR_VREF_1P25, positive_full_scale: 5.12, negative_full_scale : 0, lsb_cnt1 : 78.125}, }; /* * 根据寄存器的值转换为当前的电压 */ float ads8688_reg_to_vtg_cur(uint16_t reg, RANGE_SELC_t range, ADC_SAMPLE_t type) { float tmp; /* register_value * (V/div) / 1000000 (uV/V) */ tmp = reg * g_scale_range[range].lsb_cnt1 / (1000 * 1000) + g_scale_range[range].negative_full_scale; if (type == CURRENT) { /* mA = mV / R */ tmp = tmp * 1000 / 200; } return tmp; } /* set RST/PD pin LOW 40-100nS */ void ads8688_reset(ADS8688_HANDLE_t handle) { ; } /* * function: put the device into <power down> mode; * set RST/PD pin LOW > 400nS to put the device power down- * or send POWER_DOWN command * param: * return: */ uint16_t ads8688_power_down(ADS8688_HANDLE_t handle) { uint16_t half_word; // 发送数据准备,接收数据缓冲 handle->buf[tx][0] = CMD_PWR_DN; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送命令 handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][1]); // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } void ads8688_idle(ADS8688_HANDLE_t handle) { ; } /* * function: put the device into <standby> mode * param: * return: */ uint16_t ads8688_standby (ADS8688_HANDLE_t handle) { uint16_t half_word; // 发送数据准备,接收数据缓冲 handle->buf[tx][0] = CMD_STDBY; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送命令 handle->spiHandle (SPI1, (uint16_t )handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t )handle->buf[tx][1]); // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } /* * function: * param: * return: */ uint16_t ads8688_manual_mode (ADS8688_HANDLE_t handle, CMD_REG_t cmd) { uint16_t i; uint16_t half_word = 0; // 发送数据准备,接收数据缓冲 handle->buf[tx][0] = cmd; handle->buf[tx][2] = CMD_NO_OP; // 数据长度 handle->size_half_word = 2; // cs low handle->gpioHandle (handle->gpio_group, 0); #if 1 for(i = 0; i < handle->size_half_word; i++) { half_word = handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][i]); } #else // 发送命令 handle->spiHandle (SPI1, (uint16_t *)handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t *)handle->buf[tx][1]); #endif // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } /* * function: read 1 channel value from ads8688, no care of manual or auto select mode; * param: * ads8688_handle:spi and gpio handle; * adc_val: current channel register value from adc; */ uint16_t ads8688_read_1ch (ADS8688_HANDLE_t handle) { // todo // cs from H -> L; // first 16 sclk transfer to SDI pin for the next conversion; // next 16 sclk transfer read out the SDO pin; handle->buf[tx][0] = CMD_NO_OP; handle->buf[tx][1] = CMD_BIT_FILL; uint16_t half_word; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送命令 handle->spiHandle (SPI1, (uint16_t) handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t) handle->buf[tx][1]); // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } /* * function: * param: * return: */ uint16_t ads8688_auto_seq_rst_mode (ADS8688_HANDLE_t handle) { uint16_t half_word; // 发送数据准备,接收数据缓冲 handle->buf[tx][0] = CMD_AUTO_RST; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送命令 handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][1]); // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } /* * function: * param: * return: */ void ads8688_auto_ch_scan (ADS8688_HANDLE_t handle) { } /* pull high the CS pin and put the device into idle mode */ void ads8688_frame_abort (ADS8688_HANDLE_t handle) { handle->gpioHandle(handle->gpio_group, 1); } /* * function: reset program register, follow a auto/manual select; * param: * return: */ uint16_t ads8688_rst_prgm_reg (ADS8688_HANDLE_t handle) { uint16_t half_word; // 发送数据准备,接收数据缓冲 handle->buf[tx][0] = CMD_RST; handle->buf[tx][1] = CMD_BIT_FILL; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送命令 handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][0]); // 接收数据 half_word = handle->spiHandle (SPI1, (uint16_t)handle->buf[tx][1]); // cs high handle->gpioHandle (handle->gpio_group, 1); return half_word; } /* * function: * param: * return: */ uint16_t ads8688_auto_scan_seq_ctrl (ADS8688_HANDLE_t handle,CHANNEL_SELC_t ch, bool stat) { uint16_t prgm_reg = 0; uint16_t half_word; prgm_reg = (uint16_t) PGRM_AUTO_SEQ_EN; //address prgm_reg |= (PRGM_WR << 8); //read or write prgm_reg |= (stat << ch); //register value // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送 half_word = handle->spiHandle (SPI1, (uint16_t) prgm_reg); // 保持最少24个clk,这里使用16+16个clk half_word = handle->spiHandle (SPI1, (uint16_t) 0); // cs high handle->gpioHandle (handle->gpio_group, 1); half_word >>= 8; half_word &= 0xff; return half_word; } /* * function: * param: * return: */ uint16_t ads8688_ch_power_down (ADS8688_HANDLE_t handle,CHANNEL_SELC_t ch, bool stat) { uint16_t prgm_reg = 0; uint16_t half_word; prgm_reg = (uint16_t) PGRM_CH_POW_DOWN; //address prgm_reg |= (PRGM_WR << 8); //read or write prgm_reg |= (stat << ch); //register value // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送 half_word = handle->spiHandle (SPI1, (uint16_t) prgm_reg); // 保持最少24个clk,这里使用16+16个clk half_word = handle->spiHandle (SPI1, (uint16_t) 0); // cs high handle->gpioHandle (handle->gpio_group, 1); half_word >>= 8; half_word &= 0xff; return half_word; } /* * function: * param: * return: */ uint16_t ads8688_dev_feature_ctrl (ADS8688_HANDLE_t handle, DEV_ID_t dev, SDO_FORMAT_t sdo) { uint16_t prgm_reg = 0; uint16_t half_word; prgm_reg = (uint16_t) PGRM_FEATURE_SELC; //address prgm_reg |= (PRGM_WR << 8); //read or write prgm_reg |= ( (dev << 5) | sdo ); //dev and sdo // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送 half_word = handle->spiHandle (SPI1, (uint16_t) prgm_reg); // 保持最少24个clk,这里使用16+16个clk half_word = handle->spiHandle (SPI1, (uint16_t) 0); // cs high handle->gpioHandle (handle->gpio_group, 1); half_word >>= 8; half_word &= 0xff; return half_word; } /* * function: * param: * return: */ int8_t ads8688_range_selc (ADS8688_HANDLE_t handle, CHANNEL_SELC_t ch, RANGE_SELC_t range) { uint16_t prgm_reg = 0; uint16_t half_word; int8_t rlt = 0; //address + (read or write) + range prgm_reg = ((uint16_t)PGRM_CH_IN_RANGE_0 + ch) << 9; prgm_reg |= (PRGM_WR << 8); prgm_reg |= (uint8_t) range; // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送 half_word = handle->spiHandle (SPI1, (uint16_t) prgm_reg); // 保持最少24个clk,这里使用16+16个clk half_word = handle->spiHandle (SPI1, (uint16_t) PRGM__BIT_FILL); // cs high handle->gpioHandle (handle->gpio_group, 1); if( ((half_word >> 8) & 0xff) != (uint8_t)range) { rlt = ERR_COMM; trace_printf ("Error:prgm_reg=0x%04x,readback=0x%04x, in %s:%d\n",prgm_reg,half_word,__FILE__, __LINE__); } return rlt; } /* * function: * param: * return: */ uint16_t ads8688_cmd_readback(ADS8688_HANDLE_t handle) { uint16_t prgm_reg = 0; uint16_t half_word; prgm_reg = (uint16_t) PGRM_CMD_RD_BACK; // address prgm_reg |= (PRGM_RD << 8); // read or write // cs low handle->gpioHandle (handle->gpio_group, 0); // 发送 half_word = handle->spiHandle (SPI1, (uint16_t) prgm_reg); // 保持最少24个clk,这里使用 (16+16) 个clk half_word = handle->spiHandle (SPI1, (uint16_t) 0); // cs high handle->gpioHandle (handle->gpio_group, 1); half_word >>= 8; half_word &= 0xff; return half_word; } /* * function: set gpio callback function * param: * return: */ void ads8688_set_gpio_handle (ADS8688_HANDLE_t handle, GPIO_Handle gpio_handle) { ADS8688_OBJ_t *obj = (ADS8688_OBJ_t *) handle; obj->gpioHandle = gpio_handle; } /* * function: set spi callback funcation * param: * return: */ void ads8688_set_spi_handle (ADS8688_HANDLE_t handle, SPI_Handle spi_handle) { ADS8688_OBJ_t *obj = (ADS8688_OBJ_t *) handle; obj->spiHandle = spi_handle; } /********************** ads8688.h *************************/ #ifndef _ADS8688_H_ #define _ADS8688_H_ //#pragma pack(1) // ************************************************************************** // the includes #include <stdbool.h> #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_spi.h" /* 4字节对齐 */ #pragma pack(4) #define NR_CH_ADS8688 8 #define NR_CH_ADS8644 4 #define ADS8688_REG_RANGE 65536 #define ADS8688_REF_VTG 4.096 /* SPI1 最大读写字节数 */ #define MAX_HALF_WORD_SPI1 16 #define NUM_CH NR_CH_ADS8688 /* command register map */ typedef enum { CMD_NO_OP = 0x0000, CMD_STDBY = 0x8200, CMD_PWR_DN = 0x8300, CMD_RST = 0x8500, CMD_AUTO_RST = 0xA000, CMD_MAN_CH_0 = 0xC000, CMD_MAN_CH_1 = 0xC400, CMD_MAN_CH_2 = 0xC800, CMD_MAN_CH_3 = 0xCC00, CMD_MAN_CH_4 = 0xD000, CMD_MAN_CH_5 = 0xD400, CMD_MAN_CH_6 = 0xD800, CMD_MAN_CH_7 = 0xDC00, CMD_MAN_AUX = 0xE000, CMD_BIT_FILL = 0xFFFF, } CMD_REG_t; /* program register map */ typedef enum { PGRM_AUTO_SEQ_EN = 0x01, PGRM_CH_POW_DOWN = 0x02, PGRM_FEATURE_SELC = 0x03, PGRM_CH_IN_RANGE_0 = 0x05, PGRM_CH_IN_RANGE_1 = 0x06, PGRM_CH_IN_RANGE_2 = 0x07, PGRM_CH_IN_RANGE_3 = 0x08, PGRM_CH_IN_RANGE_4 = 0x09, PGRM_CH_IN_RANGE_5 = 0x0A, PGRM_CH_IN_RANGE_6 = 0x0B, PGRM_CH_IN_RANGE_7 = 0x0C, // PGRM_CH_0_HYST = (0x15 << 8), // PGRM_CH_0_HT_MSB = (0x16 << 8), // PGRM_CH_0_HT_LSB = (0x17 << 8), // PGRM_CH_0_LT_MSB = (0x18 << 8), // PGRM_CH_0_LT_LSB = (0x19 << 8), // PGRM_CH_7_HYST = (0x38 << 8), // PGRM_CH_7_HT_MSB = (0x39 << 8), // PGRM_CH_7_HT_LSB = (0x3A << 8), // PGRM_CH_7_LT_MSB = (0x3B << 8), // PGRM_CH_7_LT_LSB = (0x3C << 8), PGRM_CMD_RD_BACK = 0x3F, PRGM__BIT_FILL = 0x00, } PRGM_REG_ADDRESS_t; /* number of channels in current IC */ typedef enum { CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6, CH7, AUX, TOTAL_CH, }CHANNEL_SELC_t; typedef enum { id_0, id_1, id_2, id_3, } DEV_ID_t; /* Program Register Bits for SDO Data Format */ typedef enum { format_0, format_1, format_2, format_4, } SDO_FORMAT_t; /* 各个通道的输入范围选择 */ typedef enum { BIPOLAR_VREF_2P5 = 0, BIPOLAR_VREF_1P25, BIPOLAR_VREF_0P625, UNIPOLAR_VREF_2P5 = 5, UNIPOLAR_VREF_1P25, } RANGE_SELC_t; typedef struct { RANGE_SELC_t range; float positive_full_scale; float negative_full_scale; float lsb_cnt1; } SCALE_RANGE_t; /* program register map */ /* Auto-Scan Sequence Enable Register (address = 01h) */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; bool CH7_EN; bool CH6_EN; bool CH5_EN; bool CH4_EN; bool CH3_EN; bool CH2_EN; bool CH1_EN; bool CH0_EN; } PRGM_REG_AUTO_SEQ_t; /* 电流,电压采样 */ typedef enum { VOLTAGE = 0, // 电压 CURRENT, // 电流 }ADC_SAMPLE_t; typedef struct { CHANNEL_SELC_t ch; RANGE_SELC_t range; ADC_SAMPLE_t type; } CHANNEL_CFG_t; /* Channel Power Down Register (address = 02h) */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; bool CH7_PD; bool CH6_PD; bool CH5_PD; bool CH4_PD; bool CH3_PD; bool CH2_PD; bool CH1_PD; bool CH0_PD; } PRGM_REG_CH_POWER_DOWN_t; /* Device Features Selection Control Register (address = 03h) */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; DEV_ID_t DEV; bool BIT5; bool BIT4; bool BIT3; SDO_FORMAT_t SDO; }PRGM_REG_FEATURE_SELECT_t; /* Range Select Registers (addresses 05h-0Ch) */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; RANGE_SELC_t RANGE_SELC_CH; }PRGM_REG_CH_SELECT_t; /* ch0 -ch7 hysteresis */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; uint16_t CH_HYSTERESIS; uint16_t CH_HT_MSB; uint16_t CH_HT_LSB; uint16_t CH_LT_MSB; uint16_t CH_LT_LSB; } PRGM_REG_CH_HYSTERESIS_t; /* Command Read-Back Register (address = 3Fh) */ typedef struct { PRGM_REG_ADDRESS_t ADDRESS; bool RW; uint8_t CMD_WORD; } PRGM_REG_CMD_READ_BACK_t; typedef struct { GPIO_TypeDef* port_gpio_x; // gpio port number uint16_t gpioNumber; //!< the gpio number that is connected to the drv8305 enable pin } GPIO_GROUP_t; enum { tx, rx, buf_total, }; enum { PRGM_RD, PRGM_WR, }; /* 定义错误类型 */ enum { ERR_COMM = -1, ERR_TIMEOUT = -2, }DEF_ERROR_t; typedef uint16_t (*SPI_Handle) (SPI_TypeDef* SPIx, uint16_t half_word); typedef uint16_t (*GPIO_Handle) (GPIO_GROUP_t gpio, bool BitVal); typedef struct { SPI_Handle spiHandle; //!< the handle for the serial peripheral interface > GPIO_Handle gpioHandle; //!< the gpio handle that is connected to the drv8305 enable pin > GPIO_GROUP_t gpio_group; //!< GPIO port and pin > bool RxTimeOut; //!< the timeout flag for the RX fifo > bool enableTimeOut; //!< the timeout flag for drv8305 enable > uint16_t buf[buf_total][MAX_HALF_WORD_SPI1]; // dma的收发缓冲区 uint16_t size_half_word; // 一次收发spi的数据量大小 } ADS8688_OBJ_t; typedef ADS8688_OBJ_t *ADS8688_HANDLE_t; /* read/write command register */ void ads8688_reset(ADS8688_HANDLE_t handle); void ads8688_idle(ADS8688_HANDLE_t handle); void ads8688_audo_seq_rst(ADS8688_HANDLE_t handle); void ads8688_audo_ch_scan(ADS8688_HANDLE_t handle); void ads8688_frame_abort (ADS8688_HANDLE_t handle); void ads8688_set_gpio_handle (ADS8688_HANDLE_t handle, GPIO_Handle gpio_handle); void ads8688_set_spi_handle (ADS8688_HANDLE_t handle, SPI_Handle spi_handle); uint16_t ads8688_manual_mode (ADS8688_HANDLE_t handle, CMD_REG_t cmd); uint16_t ads8688_power_down(ADS8688_HANDLE_t handle); uint16_t ads8688_standby(ADS8688_HANDLE_t handle); uint16_t ads8688_rst_prgm_reg(ADS8688_HANDLE_t handle); /* read/write program register */ uint16_t ads8688_auto_scan_seq_ctrl (ADS8688_HANDLE_t handle,CHANNEL_SELC_t ch, bool stat); uint16_t ads8688_ch_power_down (ADS8688_HANDLE_t handle,CHANNEL_SELC_t ch, bool stat); uint16_t ads8688_dev_feature_ctrl (ADS8688_HANDLE_t handle, DEV_ID_t dev, SDO_FORMAT_t sdo); int8_t ads8688_range_selc (ADS8688_HANDLE_t handle, CHANNEL_SELC_t ch, RANGE_SELC_t range); uint16_t ads8688_cmd_readback(ADS8688_HANDLE_t handle); uint16_t ads8688_read_1ch (ADS8688_HANDLE_t handle); uint16_t ads8688_auto_seq_rst_mode (ADS8688_HANDLE_t handle); /* 电压电流转换 */ float ads8688_reg_to_vtg_cur(uint16_t reg, RANGE_SELC_t range, ADC_SAMPLE_t type); #endif
Hello Jenny,
My sample code was developed for TI C2000 MCU, but it's C code. Thanks.
Best regards
Dale