This commit is contained in:
ADElectronics 2017-11-28 22:31:40 +03:00
parent 6a1f93f17b
commit 764b020238
1201 changed files with 527271 additions and 1 deletions

View file

@ -0,0 +1,91 @@
/**************************************************************************/
/**************************************************************************/
#ifndef _INA219_H_
#define _INA219_H_
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define INA219_ADDRESS (0x80) // 1000000r (A0+A1=GND)
#define INA219_READ (0x01)
/*=========================================================================*/
/*=========================================================================
CONFIG REGISTER (R/W)
-----------------------------------------------------------------------*/
#define INA219_REG_CONFIG (0x00)
/*---------------------------------------------------------------------*/
#define INA219_CONFIG_RESET (0x8000) // Reset Bit
#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) // Bus Voltage Range Mask
#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range
#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) // 0-32V Range
#define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask
#define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range
#define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range
#define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range
#define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range
#define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask
#define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511
#define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023
#define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047
#define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097
#define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask
#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample
#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample
#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample
#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample
#define INA219_CONFIG_SADCRES_12BIT_1S_532US_ (0x0040) // 1 x 12-bit shunt sample
#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together
#define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask
#define INA219_CONFIG_MODE_POWERDOWN (0x0000)
#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001)
#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002)
#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003)
#define INA219_CONFIG_MODE_ADCOFF (0x0004)
#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005)
#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006)
#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007)
/*=========================================================================*/
/*=========================================================================
SHUNT VOLTAGE REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_SHUNTVOLTAGE (0x01)
/*=========================================================================*/
/*=========================================================================
BUS VOLTAGE REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_BUSVOLTAGE (0x02)
/*=========================================================================*/
/*=========================================================================
POWER REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_POWER (0x03)
/*=========================================================================*/
/*=========================================================================
CURRENT REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_CURRENT (0x04)
/*=========================================================================*/
/*=========================================================================
CALIBRATION REGISTER (R/W)
-----------------------------------------------------------------------*/
#define INA219_REG_CALIBRATION (0x05)
/*=========================================================================*/
#endif // _INA219_H_

View file

@ -0,0 +1,275 @@
/*
* ina219buf.c
*
* Created on: 02/05/2017
* Author: pvvx
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "device.h"
#include "PinNames.h"
#include "basic_types.h"
#include "diag.h"
#include "osdep_api.h"
//#include "i2c_api.h"
//#include "i2c_ex_api.h"
#include "pinmap.h"
#include "rtl_lib.h"
#include "ina219/ina219buf.h"
#include "rtl8195a/rtl_libc.h"
#include "driver/i2c_drv.h"
INA219DRV ina219drv = {
.addr = INA219_ADDRESS>>1,
.config =
INA219_CONFIG_BVOLTAGERANGE_16V | // INA219_CONFIG_BVOLTAGERANGE_32V
INA219_CONFIG_GAIN_8_320MV | // INA219_CONFIG_GAIN_1_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_2S_1060US | // INA219_CONFIG_SADCRES_12BIT_128S_69MS |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS,
.calibration = 8192,
.i2c.status = DRV_I2C_OFF,
.i2c.idx = 1, // I2C1
.i2c.io_sel = S0, // PC_4, PC_5
.i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
};
void ina219_write(unsigned char reg, unsigned short data)
{
PINA219DRV p = &ina219drv;
p->buf_i2c.uc[0] = reg;
p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8));
p->buf_i2c.uc[2] = (unsigned char)data;
_i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1);
}
unsigned int ina219_read(unsigned char reg)
{
PINA219DRV p = &ina219drv;
p->buf_i2c.uc[0] = reg;
_i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1);
p->buf_i2c.ui = 0;
_i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1);
return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1];
}
#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
/* Пример непрерывного чтения регистров
* тока и напряжения IN219 по прерыванию таймера */
void ina_tick_handler(void *par) {
PINA219DRV p = &ina219drv;
i2c_drv_t *pi2c = &p->i2c;
switch(p->status) {
default:
// Disable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
p->status = 1;
break;
case 1:
// Master Target Address
i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
// Enable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
p->status = 2;
break;
case 2:
// Заполним FIFO ic I2C командами инициализации INA219
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->config >> 8;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->config & 0x0FF) | BIT_IC_DATA_CMD_STOP;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CALIBRATION;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->calibration >> 8;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->calibration & 0x0FF) | BIT_IC_DATA_CMD_STOP;
//
p->status = 3;
break;
case 4:
if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
uint32 tmp = i2c_reg(REG_DW_I2C_IC_CLR_INTR);
p->errs++;
p->status = 0;
break;
} else {
// Считаем готовые значения из FIFO ic I2C
p->buf_i2c.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[3] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[2] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->count++;
}
case 3:
// Заполним FIFO ic I2C командами чтения
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_BUSVOLTAGE | BIT_IC_DATA_CMD_STOP;
// Read command.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_SHUNTVOLTAGE | BIT_IC_DATA_CMD_STOP;
// Read command.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
p->status = 4;
break;
}
}
void ina219_init(void)
{
PINA219DRV p = &ina219drv;
if(p->init <= 0) {
rtl_printf("Init INA219\n");
p->status = 0;
p->count = 0;
p->errs = 0;
// (!) Установки драйвера I2C заданы в структуре ina219drv
// rtl_printf("INA219 control reg = 0x%04x\n", p->config);
// _i2c_setup(&p->i2c, INA219_I2C_PIN_SDA , INA219_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
_i2c_init(&p->i2c);
// _i2c_set_speed(&p->i2c, INA219_I2C_BUS_CLK);
rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
// (!) Инициализация INA219 перенесена в прерывание таймера
// ina219_write(INA219_REG_CONFIG, p->config);
// ina219_write(INA219_REG_CALIBRATION, p->calibration);
// Initial a periodical timer
gtimer_init(&p->timer, INA219_TIMER);
// Tick every 0.000532 sec (N*532 μs)
uint32 tus = 1 << ((p->config >> 3) & 7);
tus *= 532;
rtl_printf("INA219 Read Period = %u us\n", tus);
gtimer_start_periodical(&p->timer, tus, (void*)ina_tick_handler, (uint32_t)&ina219drv);
p->init = 1;
}
}
void ina219_deinit(void)
{
PINA219DRV p = &ina219drv;
i2c_drv_t *pi2c = &p->i2c;
if(p->init > 0) {
rtl_printf("Deinit INA219\n");
gtimer_stop(&p->timer);
gtimer_deinit(&p->timer);
// (!) Не используется ina219_write / ina219_read для сокращения кода
// ina219_write(INA219_REG_CONFIG, INA219_CONFIG_MODE_POWERDOWN);
// Break controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
vTaskDelay(2); // +WDT
// Disable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
vTaskDelay(2); // +WDT
// Master Target Address
i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
// Enable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
// Заполним FIFO ic I2C командой отключения INA219
vTaskDelay(2); // +WDT
// Write addr reg. INA219 POWER_DOWN
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN >> 8);
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN & 0x0F) | BIT_IC_DATA_CMD_STOP;
vTaskDelay(2); // +WDT
_i2c_deinit(&p->i2c);
}
p->init = -1;
}
static void ShowIna(void)
{
PINA219DRV p = &ina219drv;
rtl_printf("INA219: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
rtl_printf("INA219: Cnt = %u, Err = %u\n", p->count, p->errs);
}
static void fATINA(int argc, char *argv[])
{
if(argc > 1) {
if(atoi(argv[1])) {
ina219_init();
vTaskDelay(10); // +WDT
}
else ina219_deinit();
}
ShowIna();
}
extern void dump_bytes(uint32 addr, int size);
extern uint32 hextoul(uint8 *s);
i2c_drv_t ti2c;
/* Sample:
* ati2c i
* ati2c w 40 5
* ati2c r 40 2
*/
static void fATI2C(int argc, char *argv[])
{
i2c_drv_t *pi2c = &ti2c;
uint8 buf[32];
if(argc > 1) {
if(argv[1][0] == 'i') {
if(!pi2c->status) {
uint8 sda = 0;
uint8 scl = 0;
uint8 mode = 0;
uint32 speed = 0;
if(argc > 2) sda = hextoul(argv[2]);
else if(argc > 3) scl = hextoul(argv[3]);
else if(argc > 4) mode = hextoul(argv[4]);
else if(argc > 5) speed = hextoul(argv[5]);
if(!sda) sda = PC_4;
if(!scl) scl = PC_5;
if(!mode) mode = DRV_I2C_FS_MODE;
if(!speed) speed = 400000;
if(_i2c_setup(pi2c, sda, scl, mode) == DRV_I2C_OK
&& _i2c_init(pi2c) == DRV_I2C_OK
&& _i2c_set_speed(pi2c, speed) == DRV_I2C_OK) {
rtl_printf("I2C%d Init\n", pi2c->idx);
};
} else {
rtl_printf("Already init!\n");
return;
};
} else {
if(pi2c->status) {
if(argv[1][0] == 'd') {
_i2c_ic_off(pi2c);
rtl_printf("I2C%d DeInit\n", pi2c->idx);
return;
};
int i;
for(i = 0; i + 2 < argc; i++) {
buf[i] = hextoul(argv[i+2]);
};
if(i) {
if(argv[1][0] == 'w') {
_i2c_write(pi2c, buf[0], &buf[1], i-1, 1);
rtl_printf("I2C%d write[%d]:\n", pi2c->idx, i-1);
dump_bytes(&buf[0], i);
}
else if(argv[1][0] == 'r') {
i = buf[1];
if(i > sizeof(buf) - 1) i = sizeof(buf) - 1;
_i2c_read(pi2c, buf[0], &buf[1], i, 1);
rtl_printf("I2C%d read[%d]:\n", pi2c->idx, i);
dump_bytes(&buf[0], i+1);
};
};
};
};
};
rtl_printf("I2C%d drvStatus = %d\n", pi2c->idx, pi2c->status);
return;
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_ina219[] = {
{"ATI2C", 0, fATI2C, ": Test I2C, <i>nit, <d>einit, <w>rite, <r>ead"},
{"ATINA", 0, fATINA, "=[0/1]: INA219 =1 start, =0 stop"}
};

View file

@ -0,0 +1,43 @@
/**************************************************************************
* Драйвер для INA219
**************************************************************************/
#ifndef _INA219DRV_H_
#define _INA219DRV_H_
#include "ina219/ina219.h"
#include "device.h"
#include "timer_api.h"
#include "driver/i2c_drv.h"
typedef struct _ina219data {
signed short voltage; // Voltage, 1mV
signed short current; // Current, 50uA?
signed short power; // Power, 1mW
unsigned short shunt; // 10uV
} INA219DATA, *PINA219DATA;
typedef struct _ina219drv {
unsigned char status;
unsigned char addr;
signed char init;
unsigned char tmp;
unsigned short config; // регистр конфигурации INA219
unsigned short calibration; // коэф. шунта для INA219
unsigned int count;
unsigned int errs;
gtimer_t timer;
union { // буфер
unsigned char uc[4];
unsigned short us[2];
signed short ss[2];
unsigned int ui;
} buf_i2c;
i2c_drv_t i2c;
} INA219DRV, *PINA219DRV;
#define INA219_I2C_PIN_SDA PC_4
#define INA219_I2C_PIN_SCL PC_5
#define INA219_I2C_BUS_CLK 300000 //hz
#define INA219_TIMER TIMER3 // используемый таймер
#endif // _INA219DRV_H_

View file

@ -0,0 +1,347 @@
/*
* ina219drv.c
*
* Created on: 02/05/2017
* Author: pvvx
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "device.h"
#include "PinNames.h"
#include "basic_types.h"
#include "diag.h"
#include "osdep_api.h"
//#include "i2c_api.h"
//#include "i2c_ex_api.h"
#include "pinmap.h"
#include "rtl_lib.h"
#include "ina219/ina219drv.h"
#include "rtl8195a/rtl_libc.h"
#include "driver/i2c_drv.h"
#include "platform_stdlib.h"
#include "web_websocket.h"
#include "tcpsrv/tcp_srv_conn.h"
#include "hal_com_reg.h"
//#define ReadTSF_Lo32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR)))
//#define ReadTSF_Hi32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR1)))
INA219DRV ina219drv = {
.addr = INA219_ADDRESS>>1,
.config =
INA219_CONFIG_BVOLTAGERANGE_16V | // INA219_CONFIG_BVOLTAGERANGE_32V
INA219_CONFIG_GAIN_8_320MV | // INA219_CONFIG_GAIN_1_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US | //INA219_CONFIG_SADCRES_12BIT_2S_1060US | // INA219_CONFIG_SADCRES_12BIT_1S_532US | //
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS,
.calibration = 8192, // при шунте 0.1 Ом
.buf_idx = 709, // циклический буфер на 710 замеров (по 4 байт -> sizeof(INA219DATA))
// Если шаг заполнения 1 ms -> буфер на 0.71 сек
// Оптимизация под TCP: (TCP_MSS*2 - 80)/4 = (1460*2 - 80)/4 = 710
.i2c.status = DRV_I2C_OFF,
.i2c.idx = 1, // I2C1
.i2c.io_sel = S0, // PC_4, PC_5
.i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
};
/*
void ina219_write(unsigned char reg, unsigned short data)
{
PINA219DRV p = &ina219drv;
p->buf_i2c.uc[0] = reg;
p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8));
p->buf_i2c.uc[2] = (unsigned char)data;
_i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1);
UBaseType_t f;
portBASE_TYPE d;
}
unsigned int ina219_read(unsigned char reg)
{
PINA219DRV p = &ina219drv;
p->buf_i2c.uc[0] = reg;
_i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1);
p->buf_i2c.ui = 0;
_i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1);
return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1];
}
*/
#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
/* Пример непрерывного чтения регистров
* тока и напряжения IN219 по прерыванию таймера */
void ina_tick_handler(void *par) {
PINA219DRV p = &ina219drv;
i2c_drv_t *pi2c = &p->i2c;
switch(p->status) {
default:
// Disable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
p->status = 1;
break;
case 1:
// Master Target Address
i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
// Enable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
p->status = 2;
break;
case 2:
// Заполним FIFO ic I2C командами инициализации INA219
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->config >> 8;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->config & 0x0FF) | BIT_IC_DATA_CMD_STOP;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CALIBRATION;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->calibration >> 8;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->calibration & 0x0FF) | BIT_IC_DATA_CMD_STOP;
//
p->status = 3;
break;
case 4:
if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
(volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
p->errs++;
p->status = 0;
break;
} else {
if(p->pbuf) {
PINA219DATA pd = p->pbuf + p->buf_tx;
// Считаем готовые значения из FIFO ic I2C
pd->v.vuc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
pd->v.vuc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
pd->i.iuc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
pd->i.iuc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
else p->buf_tx++;
if(p->buf_rx == p->buf_tx) {
p->overrun++; // todo: if(p->overrun++ > 100000) deinit() ?
if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
else p->buf_rx++;
};
} else {
(volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
(volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
(volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
(volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
};
}
case 3:
// Заполним FIFO ic I2C командами чтения
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_BUSVOLTAGE | BIT_IC_DATA_CMD_STOP;
// Read command.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
// Write addr reg.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_SHUNTVOLTAGE | BIT_IC_DATA_CMD_STOP;
// Read command.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
p->status = 4;
break;
}
}
uint16 ina219_chkdata(uint16 cnt)
{
PINA219DRV p = &ina219drv;
if(p->init <= 0) return 0;
int len = p->buf_tx - p->buf_rx;
if(len < 0) len += p->buf_idx + 1;
if(cnt > (uint16)len) cnt = (uint16)len;
return cnt;
}
size_t ina219_getdata(void *pd, uint16 cnt)
{
PINA219DRV p = &ina219drv;
if(p->init <= 0) return 0;
// cnt = ina219_chkdata(cnt);
unsigned short *pus = (unsigned short *) pd;
taskDISABLE_INTERRUPTS();
uint16 buf_rx = p->buf_rx;
*pus++ = cnt; // кол-во замеров
*pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
// если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
p->count += cnt; // p->overrun = 0;
unsigned char *puc = (unsigned char *) pus;
if(cnt) {
uint16 lend = buf_rx + cnt;
if(lend > p->buf_idx) {
lend -= p->buf_idx + 1;
p->buf_rx = lend;
} else {
p->buf_rx = lend;
lend = 0;
};
size_t len = (cnt - lend) *sizeof(INA219DATA);
if(len) memcpy(puc, (void *)(p->pbuf + buf_rx), len);
if(lend) memcpy(puc + len, (void *)p->pbuf, lend *sizeof(INA219DATA));
}
taskENABLE_INTERRUPTS();
return cnt * sizeof(INA219DATA) + 4;
}
//#define mMIN(a, b) ((a<b)?a:b)
#define mMAX(a, b) ((a>b)?a:b)
#include "web_srv.h"
#include "websock.h"
int ina219_ws(TCP_SERV_CONN *ts_conn, char cmd)
{
PINA219DRV p = &ina219drv;
switch(cmd) {
case 'd': // deinit
if(p->init > 0) {
gtimer_stop(&p->timer);
gtimer_deinit(&p->timer);
_i2c_deinit(&p->i2c);
if(p->pbuf) {
free(p->pbuf);
p->pbuf = NULL;
}
p->init = -1;
return 0;
}
return 1;
case 'c': // get count
return ina219_chkdata(p->buf_idx + 1);
case 'i': // init
return p->init;
default: // get_data
if(p->init <= 0) {
p->status = 0;
p->count = 0;
p->overrun = 0;
p->errs = 0;
if(!p->pbuf) {
p->pbuf = zalloc((p->buf_idx + 1) * sizeof(INA219DATA));
if(!p->pbuf) {
error_printf("Error create buffer!\n");
return -1;
};
p->buf_tx = 0;
p->buf_rx = 0;
};
_i2c_init(&p->i2c);
gtimer_init(&p->timer, INA219_TIMER);
gtimer_start_periodical(&p->timer, 532*2, (void*)ina_tick_handler, (uint32_t)&ina219drv);
p->init = 1;
// return 0;
}
case 'g': // get
{
uint32 i = ina219_chkdata(p->buf_idx + 1);
if(i) {
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
i = mMIN((web_conn->msgbufsize / sizeof(INA219DATA)), i);
if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, ina219_getdata(web_conn->msgbuf, i)) != ERR_OK)
return -1;
}
return i;
}
}
return -1;
}
void ina219_init(void)
{
PINA219DRV p = &ina219drv;
if(p->init <= 0) {
rtl_printf("Init INA219\n");
p->status = 0;
p->count = 0;
p->errs = 0;
if(!p->pbuf) {
p->pbuf = zalloc((p->buf_idx + 1) * sizeof(INA219DATA));
if(!p->pbuf) {
error_printf("Error create buffer!\n");
return;
};
p->buf_tx = 0;
p->buf_rx = 0;
};
// (!) Установки драйвера I2C заданы в структуре ina219drv
// _i2c_setup(&p->i2c, INA219_I2C_PIN_SDA , INA219_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
_i2c_init(&p->i2c);
// _i2c_set_speed(&p->i2c, INA219_I2C_BUS_CLK);
rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
// (!) Инициализация INA219 перенесена в прерывание таймера
// ina219_write(INA219_REG_CONFIG, p->config);
// ina219_write(INA219_REG_CALIBRATION, p->calibration);
// Initial a periodical timer
gtimer_init(&p->timer, INA219_TIMER);
// Tick every 0.000532 sec (N*532 μs)
// uint32 tus = (1 << ((p->config >> 3) & 7));
// tus *= 532;
uint32 tus = 532*2;
gtimer_start_periodical(&p->timer, tus, (void*)ina_tick_handler, (uint32_t)&ina219drv);
rtl_printf("INA219 Timer Period = %u us\n", tus);
p->init = 1;
}
}
void ina219_deinit(void)
{
PINA219DRV p = &ina219drv;
i2c_drv_t *pi2c = &p->i2c;
if(p->init > 0) {
rtl_printf("Deinit INA219\n");
gtimer_stop(&p->timer);
gtimer_deinit(&p->timer);
// (!) Не используется ina219_write / ina219_read для сокращения кода
// ina219_write(INA219_REG_CONFIG, INA219_CONFIG_MODE_POWERDOWN);
// Break controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
vTaskDelay(2); // +WDT
// Disable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
vTaskDelay(2); // +WDT
// Master Target Address
i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
// Enable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
// Заполним FIFO ic I2C командой отключения INA219
vTaskDelay(2); // +WDT
// Write addr reg. INA219 POWER_DOWN
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN >> 8);
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN & 0x0F) | BIT_IC_DATA_CMD_STOP;
vTaskDelay(2); // +WDT
_i2c_deinit(&p->i2c);
if(p->pbuf) {
free(p->pbuf);
p->pbuf = NULL;
}
}
p->init = 0;
}
static void ShowIna(void)
{
PINA219DRV p = &ina219drv;
rtl_printf("INA219: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
rtl_printf("INA219: Cnt = %u, Err = %u\n", p->count, p->errs);
}
static void fATINA(int argc, char *argv[])
{
if(argc > 1) {
if(atoi(argv[1])) {
ina219_init();
vTaskDelay(10); // +WDT
}
else ina219_deinit();
}
ShowIna();
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_ina219[] = {
{"ATINA", 0, fATINA, "=[0/1]: INA219 =1 start, =0 stop"}
};

View file

@ -0,0 +1,55 @@
/**************************************************************************
* Драйвер для INA219
**************************************************************************/
#ifndef _INA219DRV_H_
#define _INA219DRV_H_
#include "ina219/ina219.h"
#include "device.h"
#include "timer_api.h"
#include "driver/i2c_drv.h"
typedef struct _ina219_data {
union {
signed short voltage; // Voltage, 1mV
unsigned char vuc[2];
} v;
union {
signed short current; // Current, 50uA?
unsigned char iuc[2];
} i;
} INA219DATA, *PINA219DATA;
typedef struct _ina219drv {
unsigned char status;
unsigned char addr; // адрес INA219 на шине I2C (формат 7 bit)
signed char init;
unsigned char tmp;
unsigned short config; // регистр конфигурации INA219
unsigned short calibration; // коэф. шунта для INA219
unsigned short count; // счетчик считанных значений
unsigned short overrun; // счет переполнений буфера
unsigned short errs; // счет ошибок на I2C
unsigned short buf_idx; // объем буфера pbuf[buf_idx+1], максимальный индекс-номер замера
unsigned short buf_rx; // индекс-номер ещё не считанного замера
unsigned short buf_tx; // индекс-номер для записи следующего замера
PINA219DATA pbuf;
gtimer_t timer;
union { // буфер
unsigned char uc[4];
unsigned short us[2];
signed short ss[2];
unsigned int ui;
} buf_i2c;
i2c_drv_t i2c;
} INA219DRV, *PINA219DRV;
#define INA219_I2C_PIN_SDA PC_4
#define INA219_I2C_PIN_SCL PC_5
#define INA219_I2C_BUS_CLK 300000 //hz
#define INA219_TIMER TIMER3 // используемый таймер
#endif // _INA219DRV_H_