#include "DSP28_Device.h"
#define write_RAM GpioDataRegs.GPFDAT.bit.GPIOF13 = 0
#define read_RAM GpioDataRegs.GPFDAT.bit.GPIOF13 = 1
#define power_on GpioDataRegs.GPBDAT.bit.GPIOB0 = 0 //主回路上电控制
#define resistance_off GpioDataRegs.GPFDAT.bit.GPIOF9 = 0 //电阻切换控制
#define start_flag * (unsigned int *) 0x002000 //运行标志
#define voltage_key * (unsigned int *) 0x002001 //键盘设定的电压给定值
#define voltage_secect * (unsigned int *) 0x002002 //电压给定方式选择
#define voltage_enactment * (unsigned int *) 0x002003 //当前电压给定值
#define voltage_real * (unsigned int *) 0x002004 //输出电压的实际值
unsigned int power_on_time = 0; //控制主回路上电时间
unsigned int resistance_off_time = 0; //控制切换电阻时间
unsigned int AD_times = 0; //控制AD转换的频率
unsigned int voltage_enactment_value = 0; //电压给定值
unsigned int voltage_value = 0; //输出电压的实际值
unsigned int CMPR_value = 0; //由PID算法得出的比较寄存器的值
unsigned int PID_flag = 0; //PID计算标志
unsigned int voltage_flag = 0; //电压极性标志
float ADCINB0_value = 0; //存放通道A0的AD转换值,模拟给定
float ADCINB4_value = 0; //存放通道A1的AD转换值,测量电压
typedef struct PID
{
float SetPoint; // 设定目标Desired value
float Proportion; // 比例常数Proportional Const
float Integral; // 积分常数Integral Const
float Derivative; // 微分常数Derivative Const
float LastError; // Error[-1]
float PrevError; // Error[-2]
float SumError; // Sums of Errors
} PID;
interrupt void Timer0(void);
interrupt void AD_convert(void);
void Data_exchange(void);
void Voltage_adjust(void);
void Delay(unsigned int);
void PID_Init (PID *);
float PID_calculate(PID *, float);
void main(void)
{
PID sPID;
InitSysCtrl();
//禁止和清除所有CPU中断
DINT;
IER=0x0000;
IFR=0x0000;
InitPieCtrl(); //初始化PIE控制寄存器
InitPieVectTable(); //初始化PIE中断向量表
InitGpio(); //初始化GPIO
InitXintf(); //初始化外部接口
InitSci(); //初始化串口
InitEv(); //初始化事件管理器EVA
InitAdc(); //初始化AD转换器
InitCpuTimers(); //初始化CPU定时器0
//重新分配中断服务的中断向量,使T1UFINT、RXAINT、TINT0指向各自的服务程序
EALLOW;
PieVectTable.TINT0 = &Timer0;
PieVectTable.ADCINT = &AD_convert;
EDIS;
//使能PIE级定时器0的中断
PieCtrl.PIEIER1.bit.INTx7 = 1;
PieCtrl.PIEIER1.bit.INTx6 = 1; //允许AD转换中断
//使能CPU级INT1、INT2、INT9
IER=0x0103;
EINT;
ERTM;
//启动定时器0,每0.02s中断一次
ConfigCpuTimer(&CpuTimer0,150,20000);
//初始化PID参数
PID_Init (&sPID);
PID_flag = 0;
while(1)
{
KickDog(); //喂狗
Data_exchange();
Voltage_adjust();
if(PID_flag == 1)
{
PID_flag = 0;
PID_calculate(&sPID,voltage_value);
}
}
}
/*********************************************************************************
**函数名称:Timer0
**功能描述:定时器0中断服务程序,0.02s中断一次
**输入参数:
**输出参数:
**全局变量:
**调用模块:
**说明:
**注意:
*********************************************************************************/
interrupt void Timer0(void)
{
AD_times++;
power_on_time++;
resistance_off_time++;
if(power_on_time == 50)
{
power_on;
power_on_time = 49;
}
if(resistance_off_time == 75)
{
resistance_off;
resistance_off_time = 74;
}
if(AD_times == 10)
{
PID_flag = 1; //设置PID计算标志
AdcRegs.ADCTRL2.bit.SOC_SEQ1=1; //软件触发,启动SEQ1
AD_times = 0;
}
PieCtrl.PIEACK.all |= PIEACK_GROUP1; //写1清除中断响应标志位
}
/*********************************************************************************
**函数名称: Voltage_adjust()
**功能描述: 根据PID运算的结果,改变PWM输出的占空比,使输出电压跟随给定值
**输入参数:
**输出参数:
**全局变量:
**调用模块:
**说明:
**注意:
*********************************************************************************/
void Voltage_adjust(void)
{
/*先判断有没有启动,没有的话封死IR2110的输出脉冲,然后退出*/
unsigned int temp;
//设置数据方向从双口RAM到DSP2812
read_RAM;
Delay(100);
//判断是否停止,如果没有直接退出
temp = start_flag & 0x00ff;
if(temp != 0x0055)
{
GpioDataRegs.GPADAT.bit.GPIOA4 = 1; //封死IR2110的输出脉冲
EvaRegs.ACTR.all = 0x0fff; //将PWM脉冲强制拉高
voltage_flag = 0;
return;
}
//已经启动,使能IR2110的输出脉冲
GpioDataRegs.GPADAT.bit.GPIOA4 = 0;
EvaRegs.ACTR.all = 0x0999;
//加正压
// if((voltage_value < voltage_enactment_value) && (voltage_flag != 1))
if(voltage_flag != 1)
{
//设置EVA PWM3,PWM4外设功能 PWM1,PWM2 IO方式
EALLOW;
GpioMuxRegs.GPAMUX.all = 0x000c;
GpioMuxRegs.GPADIR.bit.GPIOA0 = 1; //输出方式
GpioMuxRegs.GPADIR.bit.GPIOA1 = 1; //输出方式
EDIS;
GpioDataRegs.GPADAT.bit.GPIOA0 = 1;
GpioDataRegs.GPADAT.bit.GPIOA1 = 1;
Delay(200);
GpioDataRegs.GPADAT.bit.GPIOA1 = 0;
voltage_flag = 1;
}
/*
//加负压
else if((voltage_value > voltage_enactment_value) && (voltage_flag != 2))
{
//设置EVA PWM1,PWM2外设功能 PWM3,PWM4 IO方式
EALLOW;
GpioMuxRegs.GPAMUX.all = 0x0003;
GpioMuxRegs.GPADIR.bit.GPIOA2 = 1; //输出方式
GpioMuxRegs.GPADIR.bit.GPIOA3 = 1; //输出方式
EDIS;
GpioDataRegs.GPADAT.bit.GPIOA2 = 1;
GpioDataRegs.GPADAT.bit.GPIOA3 = 1;
Delay(200);
GpioDataRegs.GPADAT.bit.GPIOA2 = 0;
voltage_flag = 2;
}
*/
//读入按键给定的电压值
temp = voltage_key & 0x00ff;
//计算偏差
CMPR_value = ( temp / 100.0 ) * 7500;
//根据PID输出结果置比较器的值
EvaRegs.CMPR1 = CMPR_value;
EvaRegs.CMPR2 = CMPR_value;
}
/*********************************************************************************
**函数名称:Delay(unsigned int n)
**功能描述:延迟子程序
**输入参数:n,控制延迟时间参数
**输出参数:
**全局变量:
**调用模块:
**说明:
**注意:
*********************************************************************************/
void Delay(unsigned int n)
{
unsigned int m=n;
for(;m>0;m--);
}
/*********************************************************************************
**函数名称:Data_exchange()
**功能描述:DSP2812与AT89S52通过双口RAM交换数据
**输入参数:
**输出参数:
**全局变量:
**调用模块:
**说明: 系统只有在停止的情况下,才能改变电压给定方式
**注意:
*********************************************************************************/
void Data_exchange(void)
{
unsigned int temp;
//设置数据方向从双口RAM到DSP2812
read_RAM;
Delay(100);
//选择电压给定方式
temp = voltage_secect & 0x00ff;
if(temp == 1)
{
voltage_enactment_value = ( ADCINB4_value / 2.5 ) * 100;
if(voltage_enactment_value > 100)voltage_enactment_value = 100;
}
else voltage_enactment_value = voltage_key & 0x00ff;
//设置数据方向从DSP2812到双口RAM
write_RAM;
Delay(100);
voltage_enactment = voltage_enactment_value;
voltage_real = voltage_value;
}
void PID_Init (PID *pp)
{
pp->SetPoint = 0; // 设定目标Desired value
pp->Proportion = 0; // 比例常数Proportional Const
pp->Integral = 0; // 积分常数Integral Const
pp->Derivative = 0; // 微分常数Derivative Const
pp->LastError = 0; // Error[-1]
pp->PrevError = 0; // Error[-2]
pp->SumError = 0; // Sums of Errors
}
float PID_calculate( PID *pp, float NextPoint )
{
float dError,Error;
pp->SetPoint = voltage_enactment_value; // 设定目标Desired value
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error + pp->Integral * pp->SumError + pp->Derivative * dError );
}
interrupt void AD_convert(void)
{
ADCINB0_value=( (float)AdcRegs.RESULT2 ) * 3.0 / 65520.0;
ADCINB4_value=( (float)AdcRegs.RESULT3 ) * 3.0 / 65520.0;