#include "BL0939.h"
#include "utils.h"
#include <drv_gpio.h>
#include "gd32f10x.h"
#include "iocontrol.h"
#include "sysconfig.h"
// 继电器开关
volatile uint8_t JDQEnable = 0;
#define PIN_B_LEAK GET_PIN(B, 0) // 漏电
#define PIN_B_ZX GET_PIN(B, 1) // 过零
// 所有数值需要根据实际电路及实际电阻进行微调
#define ZMPT107_1 (65 / 1000.0f) // zmpt107-1的采样电阻为50,0.05,实际测试发现电阻存在偏差,进行微调,约为0.063551
#define PowerK_A ((4046 * (3.3f * 1000 / 2000) * ZMPT107_1 * 1000.0f) / (1.218f * 1.218f * (22 * 5))) // 2000为变比 3.3为负载电阻
#define EnergyK_A ((1638.4f * 256 * 1.218f * 1.218f * (22 * 5)) / (3600000 * 4046 * (3.3f * 1000 / 2000) * ZMPT107_1 * 1000.0f))
#define VoltageK_A (79931 * ZMPT107_1 * 1000 / 1.218f / (22 * 5))
#define CurrentK_A (324004 * 3.3f * 1000 / 2000 / 1.218f) // 324004*3.3*1000/2000/1.218=877843 452444.46
#define CreepK_A ((uint8_t)(PowerK_A / (3.0517578125 * 8))) // 1瓦以下不计量 108.917 约108=6c
#define LEAK_B ((30 * 100 * 324004) / (600 * 1.218f) * 0.72f / 512 * 0.95f) //5%的跳动 1776.88=0x6f0
// 存放电量数据
BL0939_Para_t m_para[CHECK_CHANNELS * CHIP_NUM];
// 每个芯片的地址,根据实际情况进行修改
static uint8_t BUS_ADDR[CHIP_NUM] = {0x0f}; // N片bl0939的地址
// 发送和接收的结构体
static RN_SEND RnSend = {0}; // 发送结构体对象
static RN_RECV RnRecv = {0}; // 接收结构体对象
volatile uint8_t SendFinsh = 0;
volatile uint8_t RecvFinsh = 0;
#define USART2_RDATA_ADDRESS ((uint32_t) & USART_DATA(USART2))
typedef struct
{
uint8_t addr;
uint8_t data[3];
uint8_t len;
} BL0903_req_t;
static BL0903_req_t config_req[] =
{
{MODE, {0x00, 0x10, 0x00}, 3}, // 报警功能开启50hz 400ms/
//{TPS_CTRL, {0xff, 0xff, 0x00}, 3}, // 开启A通道过流,漏电报警
//{A_F_RMS_CTL, {0xE6, 0xF4, 0x00}, 3}, // 短路40A:0x3A77 80A:0x74E6
//(30mA∗负载电阻阻值∗324004/(变比∗1.218))*0.72/512*0.95 //5%的跳动 约为1,776=0x6f0
//600:1零序电流互感器,100欧负载电阻,30mA时5mV对应 有效值1372171
//20mA时对应有效值 924163,快速有效值约660210
//FAST_RMS=1372171*0.72, 判断阈值约 FAST_RMS/0x200=0x789
{B_F_RMS_CTL, {0xf0, 0x06, 0x00}, 3}, // 漏电30mA // {B_F_RMS_CTL, {0x62, 0x84, 0x00}}, // 漏电30mA
{WA_CREEP, {CreepK_A, 0x00, 0x00}, 1}, // 有功功率防潜 CreepK_A
};
static void usartSendData(uint8_t* buff, uint16_t len);
static void delay_nms(uint32_t n);
static void blSend(void); // 串口发送
static rt_bool_t blWrite(uint8_t wreg, uint8_t *pbuf, uint16_t uclen, uint8_t ch);
static rt_bool_t blRead(uint8_t wreg, uint8_t ch);
static rt_bool_t blockRecv(void); // 阻塞接收+超时处理
static uint8_t writeData(uint8_t wreg, uint8_t *data, uint8_t len, uint8_t ch);
static uint8_t readData(uint8_t wreg, uint8_t *data, uint8_t len, uint8_t ch);
static rt_bool_t blCheckSum(uint8_t reg, uint8_t *data, uint8_t ch);
static uint8_t getDeviceId(const uint32_t m_ch);
static uint8_t softReset(uint8_t ch);
static uint8_t initBLDevices(uint8_t ch);
static uint8_t setPowerCheckIC(const uint32_t m_ch);
// 读取功率
static uint8_t read_ch_pow(float *POW, uint8_t ch);
// 读取电流值
static uint8_t read_ch_cur(float *Cur, uint8_t ch);
// 读取电压值
static uint8_t read_ch_vol(uint16_t *Vol, uint8_t ch);
// 读取用电量
static uint8_t read_ch_energy_pow(uint32_t *Energy_Pow, uint8_t ch);
// 设置过载电流
#if 0
static uint8_t writeChOilvl(uint16_t Over_Cur, uint8_t ch);
#endif
/*******************************************************************************
函 数 名: delay_nms
功能描述: 延时nms
入口参数: n:ms数
出口参数: 无
********************************************************************************/
static void delay_nms(uint32_t n)
{
rt_thread_mdelay(n);
}
// 过零检测
static void irq_BZX(void *args)
{
const rt_base_t level = rt_hw_interrupt_disable();
// 真实的控制继电器
extern void realControlJDQ(uint8_t value);
realControlJDQ(JDQEnable);
rt_hw_interrupt_enable(level);
}
// 漏电检测
static void irq_LEAK(void *args)
{
const rt_base_t level = rt_hw_interrupt_disable();
if (rt_pin_read(PIN_B_LEAK) == PIN_HIGH)
JDQEnable = 0;
rt_hw_interrupt_enable(level);
}
static void usartSendData(uint8_t *buff, uint16_t len)
{
for (uint16_t tx_count = 0; tx_count < len; tx_count++)
{
while (RESET == usart_flag_get(USART2, USART_FLAG_TBE))
;
usart_data_transmit(USART2, buff[tx_count]);
}
}
// 命令复位
static uint8_t softReset(uint8_t ch)
{
static uint8_t resetCount = 0;
uint8_t t_data[3] = {0x55, 0x00, 0x00};
uint8_t reset[3] = {0x5A, 0x5A, 0x5A};
blWrite(USR_WRPROT, t_data, 3, ch); // 写使能
blWrite(SOFT_RESET, reset, 3, ch); // 写数据
delay_nms(3);
uint8_t r_data[3] = {0};
if ((readData(MODE, r_data, 3, ch) == RET_POW_SUC) && r_data[1] == 0)
{
rt_kprintf("channel %d reset success!\n", ch);
delay_nms(5);
resetCount = 0;
return RET_POW_SUC;
}
else
{
if (++resetCount > 3)
{
resetCount = 0;
return RET_POW_FAL;
}
return softReset(ch);
}
}
// 芯片初始化
static uint8_t initBLDevices(uint8_t ch)
{
// 读取id检验通信是否成功
if (getDeviceId(ch) == RET_POW_SUC)
{
rt_kprintf("channel %d init success!\n", ch);
return RET_POW_SUC;
}
return RET_POW_FAL;
}
// 读取芯片id
static uint8_t getDeviceId(const uint32_t ch)
{
static uint8_t failCount = 0;
uint8_t id = 0;
// 读取防潜,默认0x0b
if ((readData(WA_CREEP, &id, 1, ch) == RET_POW_SUC) && ((id == 0x0B) || (id == CreepK_A)))
{
rt_kprintf("channel %d init (%d)...\r\n", ch, id);
failCount = 0;
delay_nms(5);
return RET_POW_SUC;
}
else
{
rt_kprintf("channel %d init (%d)...\r\n", ch, id);
// 读取失败,重复读取
if (++failCount >= 3)
{
failCount = 0;
return RET_POW_FAL;
}
return getDeviceId(ch);
}
}
// 配置芯片寄存器
static uint8_t setPowerCheckIC(const uint32_t ch)
{
uint8_t tempAddr = 0;
softReset(ch);
for (uint8_t i = 0; i < (sizeof(config_req) / sizeof(BL0903_req_t)); i++)
{
tempAddr = config_req[i].addr;
if (writeData(tempAddr, config_req[i].data, config_req[i].len, ch) == RET_POW_FAL)
{
rt_kprintf("channel %d init failed.\r\n", ch);
return RET_POW_FAL;
}
delay_nms(1);
}
return RET_POW_SUC;
}
#if 0
// 设置过载电流
static uint8_t writeChOilvl(uint16_t Over_Cur, uint8_t ch)
{
uint8_t addr = ((ch % 2) == 0) ? A_F_RMS_CTL : B_F_RMS_CTL;
Over_Cur |= 0x8000; // 周波刷新
uint8_t data[2] = {Over_Cur & 0xff, (Over_Cur >> 8)};
if (writeData(addr, data, 2, ch) == RET_POW_FAL)
{
rt_kprintf("channel %d oilvl set failed.\r\n", ch);
return RET_POW_FAL;
}
return RET_POW_SUC;
}
#endif
// 往芯片写数据
static uint8_t writeData(uint8_t wreg, uint8_t *data, uint8_t len, uint8_t ch)
{
static uint8_t timeCount = 0;
uint8_t t_data[3] = {0x55, 0x00, 0x00};
blWrite(USR_WRPROT, t_data, 3, ch); // 写使能
blWrite(wreg, data, len, ch); // 写数据
t_data[0] = 0;
blWrite(USR_WRPROT, t_data, 3, ch); // 写禁能
uint8_t r_data[3] = {0};
readData(wreg, r_data, 3, ch);
if (rt_memcmp(data,