#include "ad7124.h" /* Error codes */ #define INVALID_VAL -1 /* Invalid argument */ #define COMM_ERR -2 /* Communication error on receive */ #define AD7124_TIMEOUT -3 /* A timeout has occured */ // 配置ad7124寄存器的值,根据实际项目需求配置 static ad7124_st_reg_t ad7124_regs[AD7124_REG_NO] = { {AD7124_STATUS, 0x00, AD7124_SIZE_1, AD7124_R}, /* AD7124_Status */ {AD7124_ADC_CONTROL, 0x0280, AD7124_SIZE_2, AD7124_RW}, /* AD7124_ADC_Control */ {AD7124_DATA, 0x000000, AD7124_SIZE_3, AD7124_R}, /* AD7124_Data */ {AD7124_IOCON1, 0x000000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_IOCon1 */ {AD7124_IOCON2, 0x0000, AD7124_SIZE_2, AD7124_RW}, /* AD7124_IOCon2 */ {AD7124_ID, 0x02, AD7124_SIZE_1, AD7124_R}, /* AD7124_ID */ {AD7124_ERROR, 0x000000, AD7124_SIZE_3, AD7124_R}, /* AD7124_Error */ {AD7124_ERROR_EN, 0x000040, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Error_En */ {AD7124_MCLK_COUNT, 0x00, AD7124_SIZE_1, AD7124_R}, /* AD7124_Mclk_Count */ {AD7124_CHANNEL_0, 0x0051, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_0 */ {AD7124_CHANNEL_1, 0x0071, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_1 */ {AD7124_CHANNEL_2, 0x0091, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_2 */ {AD7124_CHANNEL_3, 0x00B1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_3 */ {AD7124_CHANNEL_4, 0x00D1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_4 */ {AD7124_CHANNEL_5, 0x00F1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_5 */ {AD7124_CHANNEL_6, 0x0111, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_6 */ {AD7124_CHANNEL_7, 0x0131, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_7 */ {AD7124_CHANNEL_8, 0x0151, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_8 */ {AD7124_CHANNEL_9, 0x0171, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_9 */ {AD7124_CHANNEL_10, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_10 */ {AD7124_CHANNEL_11, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_11 */ {AD7124_CHANNEL_12, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_12 */ {AD7124_CHANNEL_13, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_13 */ {AD7124_CHANNEL_14, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_14 */ {AD7124_CHANNEL_15, 0x0001, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_15 */ {AD7124_CONFIG_0, 0x01E0, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_0 */ {AD7124_CONFIG_1, 0x0040, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_1 */ {AD7124_CONFIG_2, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_2 */ {AD7124_CONFIG_3, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_3 */ {AD7124_CONFIG_4, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_4 */ {AD7124_CONFIG_5, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_5 */ {AD7124_CONFIG_6, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_6 */ {AD7124_CONFIG_7, 0x0860, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Config_7 */ {AD7124_FILTER_0, 0x060020, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_0 */ {AD7124_FILTER_1, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_1 */ {AD7124_FILTER_2, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_2 */ {AD7124_FILTER_3, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_3 */ {AD7124_FILTER_4, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_4 */ {AD7124_FILTER_5, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_5 */ {AD7124_FILTER_6, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_6 */ {AD7124_FILTER_7, 0x060180, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Filter_7 */ {AD7124_OFFSET_0, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_0 */ {AD7124_OFFSET_1, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_1 */ {AD7124_OFFSET_2, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_2 */ {AD7124_OFFSET_3, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_3 */ {AD7124_OFFSET_4, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_4 */ {AD7124_OFFSET_5, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_5 */ {AD7124_OFFSET_6, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_6 */ {AD7124_OFFSET_7, 0x800000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Offset_7 */ {AD7124_GAIN_0, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_0 */ {AD7124_GAIN_1, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_1 */ {AD7124_GAIN_2, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_2 */ {AD7124_GAIN_3, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_3 */ {AD7124_GAIN_4, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_4 */ {AD7124_GAIN_5, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_5 */ {AD7124_GAIN_6, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_6 */ {AD7124_GAIN_7, 0x500000, AD7124_SIZE_3, AD7124_RW}, /* AD7124_Gain_7 */ }; static ad7124_st_reg_t ad7124_channel_regs[AD7124_CHANNEL_EN_MAX] = { {AD7124_CHANNEL_0, 0x8051, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_0 */ {AD7124_CHANNEL_1, 0x8071, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_1 */ {AD7124_CHANNEL_2, 0x8091, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_2 */ {AD7124_CHANNEL_3, 0x80B1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_3 */ {AD7124_CHANNEL_4, 0x80D1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_4 */ {AD7124_CHANNEL_5, 0x80F1, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_5 */ {AD7124_CHANNEL_6, 0x8111, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_6 */ {AD7124_CHANNEL_7, 0x8131, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_7 */ {AD7124_CHANNEL_8, 0x8151, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_8 */ {AD7124_CHANNEL_9, 0x8171, AD7124_SIZE_2, AD7124_RW}, /* AD7124_Channel_9 */ }; ad7124_analog_t ad7124_analog[AD7124_CHANNEL_EN_MAX] = {NULL}; // AD通道采样结构体数组,用于存放AD通道采样数据 /** * @brief 无校验读取AD7124寄存器 * * 读取AD7124的寄存器值,不进行校验。 * * @param p_reg 指向要读取的寄存器结构的指针 * * @return 读取成功返回0,失败返回负值 */ int32_t ad7124_no_check_read_register(ad7124_st_reg_t *p_reg) { int32_t ret = 0; uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t i = 0; uint8_t add_status_length = 0; /* Build the Command word */ buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(p_reg->addr); /* * If this is an AD7124_DATA register read, and the DATA_STATUS bit is set * in ADC_CONTROL, need to read 4, not 3 bytes for DATA with STATUS */ if ((p_reg->addr == AD7124_DATA) && (ad7124_regs[AD7124_ADC_CONTROL].value & AD7124_ADC_CTRL_REG_DATA_STATUS)) { add_status_length = 1; // 此处是根据寄存器配置而决定,根据AD7124_ADC_CONTROL第10位决定 } /* Read data from the device */ ret = ad7124_read_write_spi(buffer, p_reg->size + 1 + add_status_length); if (ret < 0) return ret; /* * if reading Data with 4 bytes, need to copy the status byte to the STATUS * register struct value member */ if (add_status_length) { ad7124_regs[AD7124_STATUS].value = buffer[p_reg->size + 1]; } /* Build the result */ p_reg->value = 0; for (i = 1; i < p_reg->size + 1; i++) { p_reg->value <<= 8; p_reg->value += buffer[i]; } return ret; } /** * @brief 向AD7124寄存器写入数据,不进行校验 * * 将数据写入指定的AD7124寄存器,不进行数据校验。 * * @param reg 指向要写入数据的寄存器地址和值的指针 * @return 写入结果,成功返回0,失败返回负值 */ int32_t ad7124_no_check_write_register(ad7124_st_reg_t *reg) { int32_t ret = 0; int32_t reg_value = 0; uint8_t wr_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t i = 0; /* Build the Command word */ wr_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR | AD7124_COMM_REG_RA(reg->addr); /* Fill the write buffer */ reg_value = reg->value; for (i = 0; i < reg->size; i++) { wr_buf[reg->size - i] = reg_value & 0xFF; reg_value >>= 8; } /* Write data to the device */ ret = ad7124_read_write_spi(wr_buf, reg->size + 1); return ret; } /** * @brief 从AD7124寄存器读取数据 * * 该函数用于从AD7124的指定寄存器中读取数据。 * * @param p_reg 指向一个ad7124_st_reg_t类型的指针,其中包含了要读取的寄存器的地址。 * * @return 返回读取到的数据,如果读取失败则返回负数。 * * 在读取寄存器之前,会先检查ERROR寄存器的SPI_IGNORE_ERR位 */ int32_t ad7124_read_register(ad7124_st_reg_t *p_reg) { int32_t ret; if (p_reg->addr != AD7124_ERROR && (ad7124_regs[AD7124_ERROR_EN].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN)) { ret = ad7124_wait_for_spi_ready(AD7124_RDY); // 读寄存器之前检查ERROR寄存器的SPI_IGNORE_ERR位 if (ret < 0) return ret; } ret = ad7124_no_check_read_register(p_reg); return ret; } /** * @brief 向AD7124寄存器写入数据 * * 将数据写入AD7124的指定寄存器。如果错误寄存器中启用了忽略SPI错误的功能,则在写入前会等待SPI接口准备就绪。 * * @param p_reg 指向要写入数据的寄存器结构体的指针 * * @return 返回写入操作的结果。如果操作成功,则返回0;否则返回负数表示错误。 */ int32_t ad7124_write_register(ad7124_st_reg_t *p_reg) { int32_t ret; if ((ad7124_regs[AD7124_ERROR_EN].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN)) { ret = ad7124_wait_for_spi_ready(AD7124_RDY); if (ret < 0) return ret; } ret = ad7124_no_check_write_register(p_reg); return ret; } /** * @brief 重置AD7124设备 * * 该函数通过SPI接口向AD7124发送重置命令,并等待设备完成上电过程。 * * @return 返回函数执行结果,成功返回0,失败返回错误码。 */ int32_t ad7124_reset(void) { int32_t ret = 0; uint8_t wr_buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 发送64个1,复位ad7124芯片 ret = ad7124_read_write_spi(wr_buf, 8); /* Read POR bit to clear */ ret = ad7124_wait_to_power_on(AD7124_RDY); return ret; } /** * @brief 等待SPI接口准备就绪 * * 等待AD7124的SPI接口准备就绪,直到超时。 * * @param timeout 超时时间(单位:毫秒) * @return 成功返回0,超时返回AD7124_TIMEOUT */ int32_t ad7124_wait_for_spi_ready(uint32_t timeout) { int32_t ret; int8_t ready = 0; while (!ready && --timeout) { /* Read the value of the Error Register */ ret = ad7124_read_register(&ad7124_regs[AD7124_ERROR]); if (ret < 0) return ret; /* Check the SPI IGNORE Error bit in the Error Register */ ready = (ad7124_regs[AD7124_ERROR].value & AD7124_ERR_REG_SPI_IGNORE_ERR) == 0; } return timeout ? 0 : AD7124_TIMEOUT; } /** * @brief 等待AD7124电源开启 * * 此函数将等待AD7124设备电源开启,直到超时或检测到电源开启标志。 * * @param timeout 超时时间 * * @return 返回0表示成功,返回AD7124_TIMEOUT表示超时 */ int32_t ad7124_wait_to_power_on(uint32_t timeout) { int32_t ret; int8_t powered_on = 0; while (!powered_on && timeout--) { ret = ad7124_read_register(&ad7124_regs[AD7124_STATUS]); if (ret < 0) return ret; /* Check the POR_FLAG bit in the Status Register */ powered_on = (ad7124_regs[AD7124_STATUS].value & AD7124_STATUS_REG_POR_FLAG) == 0; } return (timeout || powered_on) ? 0 : AD7124_TIMEOUT; } /** * @brief 等待AD7124转换准备就绪 * * 该函数等待AD7124完成转换并准备就绪。如果等待超时,则返回错误码。 * * @param timeout 超时时间 * @return 成功时返回0,超时时返回AD7124_TIMEOUT */ int32_t ad7124_wait_for_conv_ready(uint32_t timeout) { int32_t ret; int8_t ready = 0; while (!ready && --timeout) { /* Read the value of the Status Register */ ret = ad7124_read_register(&ad7124_regs[AD7124_STATUS]); if (ret < 0) return ret; /* Check the RDY bit in the Status Register */ ready = (ad7124_regs[AD7124_STATUS].value & AD7124_STATUS_REG_RDY) == 0; } return timeout ? 0 : AD7124_TIMEOUT; } /** * @brief 从AD7124读取数据 * * 从AD7124的数据寄存器中读取数据值。 * * @return 读取到的数据值 */ int32_t ad7124_read_data(void) { int32_t read_data; /* Read the value of the Status Register */ ad7124_read_register(&ad7124_regs[AD7124_DATA]); /* Get the read result */ read_data = ad7124_regs[AD7124_DATA].value; return read_data; } /** * @brief 从AD7124获取模拟信号数据 * * 该函数通过SPI接口从AD7124芯片获取模拟信号数据,并将数据保存到ad7124_analog中。 * * @details * - 遍历所有模拟通道,对每个通道执行以下操作: * - 等待AD7124完成转换。 * - 读取转换后的数据。 * - 计算电压值(单极性计算公式)。 * - 计算电流值(基于电压值和电阻值),有的通道没有电流值可以忽略。 * * @note * - 转换完成后,通过公式计算电压和电流值,并将结果保存到全局数组ad7124_analog中。 * - 电压计算公式:Code = (0xFFFFFF × AIN × Gain)/VREF,其中VREF为参考电压,GAIN为增益,AD_CODE为AD代码。 * - 电流计算公式:电流 = 电压 / 电阻 * 1000,其中电阻值为AD7124_RES,单位转换为mA。 */ // void ad7124_get_analog(void) // { // int32_t read_data; // uint8_t i; // uint8_t channel; // // for (i = STOP_NC_ADC; i < AD7124_CHANNEL_EN_MAX; i++) // // { // // ad7124_regs[AD7124_CHANNEL_0].value = ad7124_channel_regs[i].value; // // ad7124_write_register(&ad7124_regs[AD7124_CHANNEL_0]); // // ad7124_read_register(&ad7124_regs[AD7124_STATUS]); // while (ad7124_wait_for_conv_ready(AD7124_RDY)) // ; // 等待转换完成 // channel = ad7124_regs[AD7124_STATUS].value; // ad7124_analog[channel].channel = channel; // read_data = ad7124_read_data(); // ad7124_analog[channel].data = read_data; // ad7124_analog[channel].voltage = (float)(read_data * VREF / GAIN / AD_CODE); // AD7124单极性计算公式:Code = (0xFFFFFF × AIN × Gain)/VREF // ad7124_analog[channel].current = (float)(ad7124_analog[channel].voltage / AD7124_RES * 1000); // 乘1000是为了将单位转换为mA // // ad7124_regs[AD7124_CHANNEL_0].value = 0; // // ad7124_write_register(&ad7124_regs[AD7124_CHANNEL_0]); // // } // } void ad7124_get_analog(uint8_t channel_nr) { int32_t read_data; // for (i = STOP_NC_ADC; i < AD7124_CHANNEL_EN_MAX; i++) // { ad7124_regs[AD7124_CHANNEL_0].value = ad7124_channel_regs[channel_nr].value; ad7124_write_register(&ad7124_regs[AD7124_CHANNEL_0]); while (ad7124_wait_for_conv_ready(AD7124_RDY)) ; // 等待转换完成 ad7124_analog[channel_nr].channel = channel_nr; read_data = ad7124_read_data(); ad7124_analog[channel_nr].data = read_data; ad7124_analog[channel_nr].voltage = (float)(read_data * VREF / GAIN / AD_CODE); // AD7124单极性计算公式:Code = (0xFFFFFF × AIN × Gain)/VREF ad7124_analog[channel_nr].current = (float)(ad7124_analog[channel_nr].voltage / AD7124_RES * 1000); // 乘1000是为了将单位转换为mA ad7124_regs[AD7124_CHANNEL_0].value = 0; ad7124_write_register(&ad7124_regs[AD7124_CHANNEL_0]); // } } /** * @brief 配置AD7124设备 * * 该函数负责初始化AD7124设备,初始化寄存器。 * * @return 初始化结果,成功返回0,失败返回负数 */ int32_t ad7124_setup(void) { int32_t ret; uint8_t reg_nr; // board_spi_init(AD7124); // 初始化SPI,因为DAC161的SPI要和AD7124共用,并且时序不一样,所以要先初始化SPI接口。 /* Reset the device interface.*/ ret = ad7124_reset(); if (ret < 0) return ret; HAL_Delay(10); ad7124_read_register(&ad7124_regs[AD7124_ID]); /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */ for (reg_nr = AD7124_STATUS; reg_nr < AD7124_OFFSET_0; reg_nr++) // 对ad7124的可写寄存器进行配置,不包括只读寄存器 { // ret = ad7124_read_register(&ad7124_regs[reg_nr]); if (ad7124_regs[reg_nr].rw == AD7124_RW) { ret = ad7124_write_register(&ad7124_regs[reg_nr]); ret = ad7124_read_register(&ad7124_regs[reg_nr]); if (ret < 0) break; } } HAL_GPIO_WritePin(AD7124_SYNC_GPIO_Port, AD7124_SYNC_Pin, GPIO_PIN_SET); // AD7124同步信号使能 return ret; } /** * @brief 通过SPI接口对AD7124进行读写操作 * * 通过SPI接口对AD7124进行读写操作,。 * * @param buff 指向待传输数据的指针 * @param length 待传输数据的长度 * * @return 传输结果,成功返回0,失败返回负数 */ int32_t ad7124_read_write_spi(uint8_t *buff, uint8_t length) { int32_t ret; board_spi_init(AD7124); // 初始化SPI,因为DAC161的SPI要和AD7124共用,并且时序不一样,所以要先初始化SPI接口。 board_spi_cs_on(AD7124); ret = spi_transmit_receive(&hspi1, buff, length); board_spi_cs_off(AD7124); return ret; }