📄 esp.c
字号:
/********************************************************************************
* 杭州利尔达 *
* MSP430FE42X单相防窃电多功能电表平台 *
* ----- ESP SD16实现 *
* *
* *
* 说明:本软件为杭州利尔达单相防窃电多功能电表DEMO软件 *
* *
*********************************************************************************/
#include "msp430xe42x.h"
#include "extern_function.h"
#include "emeter_cfg.h"
#include "globe.h"
/*****************************************************************
* 模拟前端初始化函数 *
* *
* 说明:配置SD16 ADC模块 *
* 配置两个电流通道和一个电压通道,实现防窃电电表 *
* 电流通道I1使用锰铜分流器,电流通道I2使用电流互感器CT ×
******************************************************************/
#define SD16CONF0_FUDGE 0xC0
#define SD16CONF1_FUDGE 0x40
void init_analog_front_end_ESP(void)
{
/**
* 首先,我们必须确认ESP模块处在关闭状态,否则不能对SD16寄存器初始化
*/
ESPCTL &= ~ESPEN;
/**
* 进行模拟前端的共性配置:
* 选择时钟原SMCLK
* 选择时钟原分频系数,不同的主频下分频系数不同,分频结果均为1.094MHz
* 选择参考原
*/
SD16CTL= 0x800
| SD16SSEL_1 // 时钟原: SMCLK
| SD16DIV_3 // 8分频 => ADC clock: 1.094MHz
| SD16REFON; // 选用内部参考原
// -------------------------------------------------------------------
/**
* 配置电流通道I1
* 锰铜分流器
* 锰铜分流器电阻 Rs = 300 微欧
* 最大电流40A时
* 锰铜分流器的电压有效值 VRs(RMS) = 0.3 * 40 = 12mV
* 锰铜分流器的电压峰值 VRs(peak) = 16.97mV
* 当前置放大器放大倍数 GAIN = 16时, 最大输入电压 VIN = 16.97 * 16 = 271mV < 500mV
* GAIN = 32时, 最大输入电压 VIN = 16.97 * 32 = 543mV > 500mV
* 所以选择电流通道I1的放大倍数 GAIN = 16
*
*/
SD16INCTL0= SD16GAIN_1; // 设置电流通道I1的增益放大倍数GAIN = 16
SD16CCTL0 = SD16OSR_256; // 设置电流通道I1过采样率为 256
// -------------------------------------------------------------------
/**
* 配置电流通道I2
* 电流互感器CT
* 此通道暂时短接不用
*/
SD16INCTL1= SD16GAIN_16; // 设置电流通道I2的增益放大倍数GAIN = 1
SD16CCTL1 = SD16OSR_256; // 设置电流通道I2过采样率为 256
// -----------------------------------------------------------
/**
* 配置电压通道
* 电阻分压,最大输入电压 VIN=(220 + 220*0.2) * (1/991)*1.414 = 376 mV
* 选择增益放大倍速 GAIN = 1
*/
SD16INCTL2= SD16GAIN_1;// 设置电压通道V1的增益放大倍数GAIN = 1
SD16CCTL2 = SD16OSR_256; // 设置电压通道V1过采样率为 256
SD16CONF0 = SD16CONF0_FUDGE;
SD16CONF1 = SD16CONF1_FUDGE;
} // 模拟前端初始化函数结束
/*********************************************************************
* 设置ESP430CE1模块参数函数 *
* *
* 参数寄存器地址送入\a param *
* 设置的内容送入\a data *
* *
*********************************************************************/
void set_parameter(unsigned int param, unsigned int data)
{
unsigned int timeout= 0xffff; //定义超时溢出计数寄存器
MBOUT1= data; // 写本次邮箱发送的数据
MBOUT0= param; // 写本次邮箱发送的地址
do
{
//等待ESP430CE1的反馈信息
while (((MBCTL & IN0IFG) == 0) && (timeout-- > 0)) ;
if (timeout == 0)
{
display(ERROR);
return;
}
//判断反馈消息是否与发送的内容相符
} while ((MBIN0 != mPARAMSET) || (MBIN1 != param));
} // End of set_parameter()
/********************************************************************
* 初始化ESP430CE1模块 *
* *
********************************************************************/
void init_esp_parameter(void)
{
// 定义超时溢出计数寄存器
unsigned int timeout,i;
// 确信嵌入式处理器在使能状态
ESPCTL |= ESPEN;
MBCTL = 0;
// 初始化前需要保证ESP不在测量状态或者校准状态
if ((ESP430_STAT0 & ACTIVEFG) != 0)
{
// 如果不是在空闲状态,则使它进入空想状态
MBOUT1= ESP_IDLE;
MBOUT0= mSET_MODE;
timeout= 0xffff;
// 等待进入空闲状态,以便后续的设置
while (((ESP430_STAT0 & ACTIVEFG) != 0) && (timeout-- > 0)) ;
}
MBOUT1 = 0;
MBOUT0 = modeRESET;
for(i=0;i<50000;i++);
// 读ESP软件版本号
MBOUT0= mSWVERSION;
timeout= 0xffff;
do
{
while (((MBCTL & IN0IFG) == 0) && (timeout-- > 0)) ;
if (timeout == 0)
{
display(ERROR);
return;
}
} while (MBIN0 != mSWRDY);
/*************** 初始化参数寄存器 ******************/
// 配置参数寄存器Control 0
set_parameter(mSET_CTRL0,
CURR_I2 + // 用电流通道I2作窃电检测
NE0 + // 负电能处理方式为取绝对值
DCREM_V1 +
DCREM_I1 + // 电流通道I1去直流分量功能开
DCREM_I2); // 电流通道I2去直流分量功能开
// 设置电网正常频率 50Hz
set_parameter(mSET_NOMMAINSFREQ, 50);
// 设置相位校正寄存器
set_parameter(mSET_PHASECORR1, (int)(emeter.f_PhaseCorr1/50*(POW_2_20/360)));
set_parameter(mSET_PHASECORR2, (int)(emeter.f_PhaseCorr2/50*(POW_2_20/360)));
// 设置两电流通道自适应因子
set_parameter(mSET_ADAPTI1, (0.32/0.30) * POW_2_14); // = 1.06667 * POW_2_14 = 17476
set_parameter(mSET_ADAPTI2, 1 * POW_2_14); // = 1 * POW_2_14 = 16384
set_parameter(mSET_V1OFFSET, 0);
set_parameter(mSET_I1OFFSET, 0);
set_parameter(mSET_I2OFFSET, 0);
set_parameter(mSET_GAINCORR1, emeter.ui_GainCorr1);
set_parameter(mSET_GAINCORR2, emeter.ui_GainCorr2);
ds.l = emeter.l_PowerOffset1;
set_parameter(mSET_POFFSET1_LO, ds.w[0]);
set_parameter(mSET_POFFSET1_HI, ds.w[1]);
ds.l = emeter.l_PowerOffset2;
set_parameter(mSET_POFFSET2_LO, ds.w[0]);
set_parameter(mSET_POFFSET2_HI, ds.w[1]);
set_parameter(mSET_RATIOTAMP, 0x4333); // 5%
set_parameter(mSET_ITAMP, 0x140);
// 设置开始电流
set_parameter(mSET_STARTCURR_INT, 0);
set_parameter(mSET_STARTCURR_FRAC, 0);
} // End of init_esp_parameter()
/*******************************************************************
* 这个函数使ESP进入测量状态 *
*******************************************************************/
void start_measurement(void)
{
// 设置事件要求信息标志
#ifdef ENERGY_1SEC
set_parameter(mSET_EVENT,
ENRDYME);
#else
set_parameter(mSET_EVENT,
ENRDYME+ZXLDME+ZXTRFG); // 当事件<新的能量值准备好>发生时发出中断请求
#endif
MBCTL= IN0IE; //接收邮箱0中断使能
_EINT();
// 开始测量(使ESP进入测量模式)
MBOUT1= ESP_MEASURE;
MBOUT0= mSET_MODE;
} // End of start_measurement()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -