pile_com_stm32/main/stm32/ads1220.c
2024-02-23 17:21:13 +08:00

516 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ads1220.h"
// #include "main.h"
#include "config.h"
#include "ModbusS.h"
#include "ModbusM.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "utils.h"
#include "config.h"
#include "driver/mcpwm.h"
#define TAG "ADS1220"
#define ADS1220_HOST SPI2_HOST
#define SPI2_PIN_NUM_MISO 6
#define SPI2_PIN_NUM_MOSI 5
#define SPI2_PIN_NUM_CLK 16
#define SPI2_PIN_NUM_CS 15
// To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use,
// but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this.
#define PARALLEL_LINES 16
static spi_device_handle_t spi2;
/***************************************************
*
*ADS1220<32><30><EFBFBD><EFBFBD>
*1.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>Ŷ˿<C5B6>
*
*
*
*
*/
/****************ADS1220<32><30><EFBFBD>ź궨<C5BA><EAB6A8>*******************/
#define ADS1220_nCS_HIGH() gpio_set_level(GPIO_NUM_38, 1)
#define ADS1220_nCS_LOW() gpio_set_level(GPIO_NUM_38, 0)
/*****************************************************/
#define ADS1220_CMD_WREG 0x40 // д<>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_CMD_RREG 0x20 // <20><><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_CMD_RESET 0x06 // <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
#define ADS1220_CMD_START 0x08 // <20><>ʼת<CABC><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_CMD_POWERDOWN 0x02 // <20>͹<EFBFBD><CDB9>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_CMD_RDATA 0x10 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define Channal1 0x00 // ͨ<><CDA8>1
#define Channal2 0x10 // ͨ<><CDA8>2
#define Channal3 0x20 // ͨ<><CDA8>3
#define Channal4 0x30 // ͨ<><CDA8>4
#define ADS1220_REG0 0x00 // <20>Ĵ<EFBFBD><C4B4><EFBFBD> 0
#define ADS1220_REG1 0x01 // <20>Ĵ<EFBFBD><C4B4><EFBFBD> 1
#define ADS1220_REG2 0x02 // <20>Ĵ<EFBFBD><C4B4><EFBFBD> 2
#define ADS1220_REG3 0x03 // <20>Ĵ<EFBFBD><C4B4><EFBFBD> 3
#define PGAGain1 0x00 // PGA<47><41><EFBFBD><EFBFBD> Ĭ<><C4AC>
#define PGAGain2 0x02 //
#define PGAGain4 0x04 //
#define PGAGain8 0x06 //
#define PGAGain16 0x08 //
#define PGAGain32 0x0A //
#define PGAGain64 0x0C //
#define PGAGain128 0x0E //
#define ADS1220_Standby 0 // ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_ConvStart 1 // ת<><D7AA><EFBFBD><EFBFBD>ʼ
#define ADS1220_ConvFinish 2 // ת<><D7AA><EFBFBD><EFBFBD><EFBFBD>
#define ADS1220_Channal1 0 // ͨ<><CDA8>1
#define ADS1220_Channal2 1 // ͨ<><CDA8>2
#define ADS1220_Channal3 2 // ͨ<><CDA8>3
#define ADS1220_Channal4 3 // ͨ<><CDA8>4
#define LED1_GPIO_PIN 9
#define LED2_GPIO_PIN 10
#define GPIO_OUTPUT_PIN_SEL ((1ULL << LED1_GPIO_PIN) | (1ULL << LED2_GPIO_PIN))
#define GPIO_INPUT_IO_39 7
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_39)
// #define GPIO_INPUT_IO_1 5
// #define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
int ads1220_watchdog = 0;
extern QueueHandle_t gpio_evt_queue;
QueueHandle_t gpio_evt_queue = NULL;
// uint16_t gWordVar[gWORD_SIZE];
int ad_value[4];
uint32_t ad_update_time[4];
uint8_t ad_watchdog_cnt = 0;
extern flow_t *pflow;
const uint8_t ch_cmd[4] = {0x0C, 0xA1, 0x0C, 0xB1}; //
static int ch = 0;
void ADS1220_Init(void)
{
// ESP_LOGI(TAG, "Start init ADS1220.\n");
ADS1220_Config();
// ESP_LOGI(TAG, "Start ADS1220_Config.\n");
ch = 0;
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[0]);
ADS1220_WriteCommand(ADS1220_CMD_START);
}
static void IRAM_ATTR ads1220_done_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig,
const cap_event_data_t *edata, void *arg)
{
// uint32_t gpio_num = (uint32_t)arg;
// if (ch == 1)
// {
// pflow[0].update_time = xTaskGetTickCount();
// }
// if (ch == 3)
// {
// pflow[1].update_time = xTaskGetTickCount();
// }
ad_update_time[ch] = edata->cap_value;
xQueueSendFromISR(gpio_evt_queue, &ad_update_time[ch], NULL);
}
static void GPIO_Init(void)
{
// zero-initialize the config structure.
gpio_config_t io_conf = {};
// disable interrupt
io_conf.intr_type = GPIO_INTR_DISABLE;
// set as output mode
io_conf.mode = GPIO_MODE_OUTPUT;
// bit mask of the pins that you want to set,e.g.GPIO18/19
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
// disable pull-down mode
io_conf.pull_down_en = 0;
// disable pull-up mode
io_conf.pull_up_en = 0;
// configure GPIO with the given settings
gpio_config(&io_conf);
// interrupt of rising edge
// io_conf.intr_type = GPIO_INTR_NEGEDGE;
// // bit mask of the pins, use GPIO4/5 here
// io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
// // set as input mode
// io_conf.mode = GPIO_MODE_INPUT;
// // enable pull-up mode
// io_conf.pull_up_en = 1;
// gpio_config(&io_conf);
// change gpio intrrupt type for one pin
// gpio_set_intr_type(GPIO_INPUT_IO_39, GPIO_INTR_NEGEDGE);
// create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(1, sizeof(uint32_t));
// install gpio isr service
// gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
// // hook isr handler for specific gpio pin
// gpio_isr_handler_add(GPIO_INPUT_IO_39, gpio_isr_handler, (void *)GPIO_INPUT_IO_39);
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, GPIO_INPUT_IO_39));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_INPUT_IO_39));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = ads1220_done_handler, // 绑定深度中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf));
}
uint8_t ret = 0;
/****
* ADS1220<32><30><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
**/
u8 ADS1220_ReadReg(u8 reg)
{
u8 Val;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RREG | ((reg & 0x03) << 2);
t.length = 2 * 8;
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = t.rx_data[1];
return Val;
}
/***
* <20><>ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>24Bits
*
**/
// static u32 ADS1220_ReadWrite24Bits(u32 dat)
// {
// uint8_t tmp[3];
// static int val = 0;
// HAL_SPI_TransmitReceive(&spi2, (uint8_t *)&dat, (uint8_t *)tmp, 3, 500);
// val = ((uint32_t)tmp[0] << 16) + ((uint32_t)tmp[1] << 8) + ((uint32_t)tmp[2] << 0);
// // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ 23λ <20><>1 <20><>Ϊ <20>з<EFBFBD><D0B7><EFBFBD>
// if (val & 0x800000)
// {
// val |= 0xFF000000;
// }
// return val;
// }
// ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
s32 ADS1220_ReadData(void)
{
s32 Val = 0;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RDATA;
t.length = 4 * 8; // Command is 24 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = (t.rx_data[1] << 16) | (t.rx_data[2] << 8) | t.rx_data[3];
if (Val & 0x800000)
{
Val |= 0xFF000000;
}
return Val;
}
// ADS1220д<30>Ĵ<EFBFBD><C4B4><EFBFBD>
void ADS1220_WriteReg(u8 reg, u8 dat)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
// t.flags = SPI_TRANS_USE_TXDATA;
t.tx_data[0] = ADS1220_CMD_WREG | ((reg & 0x03) << 2);
t.tx_data[1] = dat;
t.length = 2 * 8; // Command is 16 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
}
// ADS1220д<30><D0B4><EFBFBD><EFBFBD>
void ADS1220_WriteCommand(u8 cmd)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.length = 8 * 2; // Command is 8 bits
t.tx_data[0] = cmd; // The data is the cmd itself
// ESP_LOGI(TAG, "spi_device_polling_transmit befor.\n");
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
// ESP_LOGI(TAG, "spi_device_polling_transmit after.\n");
assert(ret == ESP_OK);
// // ADS1220_CS=0;
// ADS1220_nCS_LOW();
// ADS1220_ReadWriteByte(cmd);
// // ADS1220_CS=1;
// ADS1220_nCS_HIGH();
}
// ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
void ADS1220_PowerDown(void)
{
ADS1220_WriteCommand(ADS1220_CMD_POWERDOWN); //
}
// ADS1220<32><30><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
void ADS1220_StartConv(u8 channal)
{
/*
u8 val ;
val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220.CurrentCH = ADS1220_Channal1;
val = val & 0x0f | Channal1;
ADS1220_WriteReg(ADS1220_REG0, val ); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>0 <20><><EFBFBD><EFBFBD>: AIN P = AIN0, AIN N = AIN1 <20><><EFBFBD>ģʽ ʹ<><CAB9>PGA 64 (110) <20><><EFBFBD><EFBFBD>PGA (0)
*/
ADS1220_WriteCommand(ADS1220_CMD_START); // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
}
// ADS1220<32><30>λ
void ADS1220_Reset(void)
{
ADS1220_WriteCommand(ADS1220_CMD_RESET); // <20><>λADS1220
}
// ADS1220 PGA<47><41><EFBFBD><EFBFBD>
void ADS1220_PGASet(u8 gain)
{
u8 val;
val = ADS1220_ReadReg(ADS1220_REG0);
val = (val & 0xF1) | gain;
ADS1220_WriteReg(ADS1220_REG0, val);
// val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220_StartConv(ADS1220_Channal1); // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
}
// static uint8_t dara_rate = 0x40;
void ADS1220_Config(void)
{
static uint8_t read[4];
ADS1220_WriteCommand(ADS1220_CMD_RESET); // <20><>λADS1220
vTaskDelay(10);
// ESP_LOGI(TAG, "ADS1220_WriteCommand.\n");
ADS1220_WriteReg(ADS1220_REG0, 0xa0); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>0 <20><><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD>: AIN P = AIN0, AIN N = AVSS <20><><EFBFBD><EFBFBD>ģʽ ʹ<><CAB9>PGA1 (100) <20><><EFBFBD><EFBFBD>PGA(0)
ADS1220_WriteReg(ADS1220_REG1, 0x00); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>1 <20><><EFBFBD><EFBFBD>: Turboģʽ 40.SPS(00000)<29><>ʹ<EFBFBD><CAB9><EFBFBD>¶ȴ<C2B6><C8B4><EFBFBD><EFBFBD><EFBFBD>(0) <20>رյ<D8B1><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(0)
ADS1220_WriteReg(ADS1220_REG2, 0x20); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>2 <20><><EFBFBD><EFBFBD>: <20><>ѹ<EFBFBD><D1B9>׼ <20>ڲ<EFBFBD>2.048-v<>ο<EFBFBD>(00) ʹ<><CAB9>оƬFIR<49>˲<EFBFBD>50Hz(10) <20><><EFBFBD><EFBFBD>Դ0ma // Low-side<64><65>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD> Ĭ<><C4AC>(0) <20><><EFBFBD><EFBFBD>Դ <20>ر<EFBFBD>
ADS1220_WriteReg(ADS1220_REG3, 0x00); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>3 <20><><EFBFBD><EFBFBD>: : IDAC1 connect to AIN2 : IDAC2 disabled
read[0] = ADS1220_ReadReg(ADS1220_REG0);
read[1] = ADS1220_ReadReg(ADS1220_REG1);
read[2] = ADS1220_ReadReg(ADS1220_REG2);
read[3] = ADS1220_ReadReg(ADS1220_REG3);
printf("ads1220 reg %02x %02x %02x %02x \n", read[0], read[1], read[2], read[3]);
}
void LED2_Toggle(void)
{
static unsigned char flg = 1;
if (flg)
{
gpio_set_level(LED2_GPIO_PIN, 0);
flg = 0;
}
else
{
gpio_set_level(LED2_GPIO_PIN, 1);
flg = 1;
}
}
static void SPI2_Init(void)
{
esp_err_t ret;
spi_bus_config_t buscfg2 = {
.miso_io_num = SPI2_PIN_NUM_MISO,
.mosi_io_num = SPI2_PIN_NUM_MOSI,
.sclk_io_num = SPI2_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 8};
spi_device_interface_config_t devcfg2 = {
.clock_speed_hz = 1 * 1000 * 1000, // Clock out at 1 MHz
.mode = 0, // SPI mode 0
.cs_ena_posttrans = 2, // Keep the CS low 2 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than SPI CLK
.spics_io_num = SPI2_PIN_NUM_CS, // CS pin
.queue_size = 1, // We want to be able to queue 7 transactions at a time
// .address_bits = 8,
// .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line
// .command_bits = 8,
};
// Initialize the SPI bus
ret = spi_bus_initialize(ADS1220_HOST, &buscfg2, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
// Attach the ADS1220 to the SPI bus
ret = spi_bus_add_device(ADS1220_HOST, &devcfg2, &spi2);
ESP_ERROR_CHECK(ret);
}
extern void zero_totalflow(int ch);
extern int zero_totalflow_req;
extern int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time);
extern cal_4_20ma_t *cal_4_20ma;
extern flow_config_t *flow_config;
extern flow_t *pflow;
extern uint8_t timeout[2];
extern int flow_rem[2];
void ads1220_task(void)
{
uint32_t io_num;
// static uint32_t ad_flow_tick = 10;
while (1)
{
// ESP_LOGI(TAG, "xQueueReceive before\n ");
if (xQueueReceive(gpio_evt_queue, &io_num, 200))
{
int ad_ch;
ads1220_watchdog = 0;
int ad_raw = ADS1220_ReadData();
// if (ch == 3)
// ESP_LOGI(TAG, "ads1220 ch3 ad_rad:%d", (int)ad_raw);
ad_value[ch] = ad_raw / 128;
ad_ch = ch;
gWordVar[AD_RAW_REG_ADDR + ch] = ad_value[ch] / 2;
// ESP_LOGI(TAG, "channel : %d ad_value: %d\n ", ch, ad_value[ch]);
ch++;
if (ch >= sizeof(ch_cmd))
{
ch = 0;
}
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ch]);
ADS1220_WriteCommand(ADS1220_CMD_START);
ad_watchdog_cnt = 0;
LED2_Toggle();
if ((ad_ch == 1 || ad_ch == 3) && flow_config->input_type == 1)
{
int flow_ch = ad_ch / 2;
int time_diff = abs_sub(ad_update_time[ad_ch], pflow[flow_ch].update_time);
ad_flow_cal_t *cal = flow_config->ad_cal;
int t_flow; // time_diff时间段总流量
pflow[flow_ch].flow_ = scale(ad_value[ad_ch], cal_4_20ma->ch[flow_ch].ad_4ma, cal_4_20ma->ch[flow_ch].ad_20ma, cal[flow_ch].flow_min, cal[flow_ch].flow_max);
if (pflow[flow_ch].flow_ < flow_config->min_flow[flow_ch]) // 小流量切除
{
pflow[flow_ch].flow = 0;
}
else
{
pflow[flow_ch].flow = pflow[flow_ch].flow_;
}
// 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为1us
// flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s
// t_diff = time_diff / 1000 将时间差换算成秒
// t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL
// 取出0.01L的整数部分累加,余数部分和下次值累加
// t_flow = pflow[i].flow * 1000 * time_diff / 1000000 / 60;
int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000);
// if (ad_ch == 3) ESP_LOGI(TAG, "time_diff_us:%d", time_diff_us);
t_flow = pflow[flow_ch].flow * (long long)time_diff_us / 60 / 100; //(5 * 60);
flow_rem[flow_ch] += t_flow;
int sub_flow = flow_rem[flow_ch] / 10000;
pflow[flow_ch].total_flow += sub_flow;
flow_rem[flow_ch] = flow_rem[flow_ch] - sub_flow * 10000;
pflow[flow_ch].update_time = ad_update_time[ad_ch];
timeout[flow_ch] = 0;
//if (ad_ch == 3) ESP_LOGI(TAG, "flow:%d total_flow:%d", (int)pflow[flow_ch].flow, (int)pflow[flow_ch].total_flow);
// ESP_LOGI(TAG, "(type1) flow_rem[%d].flow: %u time_diff=%d", flow_ch ,pflow[flow_ch].flow,time_diff);
// ESP_LOGI(TAG, "ads1220 ch:%d time_diff:%d flow:%d total_flow:%d", flow_ch, time_diff, pflow[flow_ch].flow, pflow[flow_ch].total_flow);
}
}
else
{
ADS1220_Init();
}
if (zero_totalflow_req)
{
zero_totalflow_req = 0;
zero_totalflow(0);
zero_totalflow(1);
}
}
}
void ads1220_task_start(void)
{
SPI2_Init();
GPIO_Init();
ADS1220_Init();
xTaskCreate(ads1220_task, "ads1220_task", 4096, NULL, 10, NULL);
}
// void ADS1220_set_rate(int i)
//{
// switch (i)
// {
// case 1 :dara_rate = 0x00;//20SPS
// break;
// case 2 :dara_rate = 0x20;//45SPS
// break;
// case 3 :dara_rate = 0x40;//90SPS
// break;
// case 4 :dara_rate = 0x60;//175SPS
// break;
// default:dara_rate = 0x00;//20SPS
// break;
// }
// }
// int ADS1220_get_rate(void)
//{
// switch (dara_rate)
// {
// case 0x00 :return 20*100;//20SPS
// break;
// case 0x20 :return 45*100;//45SPS
// break;
// case 0x40 :return 90*100;//90SPS
// break;
// case 0x60 :return 175*100;//175SPS
// break;
// default:return 20*100;//20SPS
// break;
// }
// }
// ch0 0.5V 3478
// ch0 1.0V 0
// ch0 1.5V 10429
// ch1 4.000ma 12783
// ch1 12.00ma 38349
// ch2 4.000ma 12764
// ch2 12.00ma 38336