📄 dcdccontrol.c
字号:
// 该程序用于进行A/D转换的演示,A/D转换的结果存于数足ADRESULT[16]中,
// 寄存器cesi用于测试每个A/D转换的结果
#include "regs240x.h"
/* 常量声明 */
#define Vo_amplify 18.53; // Vo经过运放的调节倍数
#define Vo_Constant 28.0; // 输出恒定值
#define Vo_error 0.5; // 输出允许误差值
#define PWM_period 2000; // 根据40M时钟设定PWM的输出周期值
#define Kp 0.001; // PI控制的比例参数
#define Ki 0.001; // PI控制的积分参数
/* 变量声明 */
float ek_1_overall=0;
float dk_1_overall=0;
int i;
/* 屏蔽中断子程序 */
void inline disable()
{
asm(" setc INTM");
}
/* 开总中断子程序 */
void inline enable()
{
asm(" clrc INTM");
}
/* 系统初始化子程序 */
Initial()
{
asm(" setc SXM"); // 符号位扩展有效
asm(" clrc OVM"); // 累加器中结果正常溢出
asm(" clrc CNF"); // B0被配置为数据存储空间
SCSR1=0x81FE; // CLKIN=6M,CLKOUT=4*CLKIN=24M
WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WD复位后的缺省值为1,故可以用软件禁止看门狗
IMR=0x0003; // 允许INT1,INT2中断
IFR=0x0FFFF; // 清除全部中断标志,"写1清0"
WSGR=0x00; // 禁止所有的等待状态
i=0;
return;
}
/* 定时器1初始化 */
//1/(40*10(6))*64*(T2PER+1)=5*10(-3) T2PER=3124
void Timer3init()
{
EVBIMRA=0X0080; // 允许定时器2的周期中断
EVBIFRA=EVBIFRA&0X0080; // 清除定时器2的周期中断标志
T3CON=0X160C; // timer2为连续增计数模式预分频值为64,使用内部时钟
T3PER=0X0ffff; //0X1869//0x0c34 // TIMER2的周期寄存器的值根据5ms(10ms)的定时和预分频值确定
T3CNT=0X00; // TIMER2的计数器清零
return;
}
/* AD初始化子程序 */
void ADinit()
{
//GPTCONA=0X000; // T1,T2无事件启动AD转换,禁止T2周期中断触发AD转换
ADCTRL1=0X10; // 采样时间窗口预定标位ACQ PS3-ACQ PS0为0,
// 转换时间预定标位CPS为0,AD为启动/停止模式,排
// 序器为级连工作方式,且禁止特殊的两种工作模式
ADCTRL2=0X0000; // 不可以用EVB的一个事件信号触发AD转换,不用中断模式
MAXCONV=0X07; // 16通道
CHSELSEQ1=0X3333;
CHSELSEQ2=0X3333;
CHSELSEQ3=0X3333;
CHSELSEQ4=0X3333;// 转换通道是0-15 */
CALIBRATION=0x0000; //不启用校正功能
return;
}
/* PWM初始化子程序 */
//1/(40(6))*1*(T1PER+1)=1/(20(3))
void PWMinit()
{
MCRA=MCRA|0X0140; // IOPA6/PWM1,IOPB0/PWM3设置为基本功能引脚
ACTRA=0X0AAA; // 设置PWM1,3比较输出方式:高有效
DBTCONA=0X00; // 不使能死区控制
CMPR1=0;
CMPR2=0; // 初始化PWM1,3占空比为0,输出低
T1CON=0X1000; // 定时器1为连续增计数模式,预定标系数为X/1(X为CPU时钟频率)
T1PER=0X07CF; // 设置定时器1的周期寄存器,确定PWM频率为20KHZ
COMCONA=0X8200; // 使能比较操作
return;
}
/* 启动AD转换子程序 */
void ADsoc()
{
ADCTRL2=ADCTRL2|0X4000; // 复位SEQ1,且清除INT FLAG SEQ1标志写"1"清0
ADCTRL2=ADCTRL2|0x2000; // 软件触发启动SEQ1
return;
}
/* 采样数据处理程序 */
float ADprocess()
{
int i; //暂时变量,用于for循环
int ADRESULT[8]; // 用于保存AD转换的结果
int result; // 存放Vo的暂时结果
float Vo_AD; // 存放输入电压
//asm(" clrc SXM"); // 抑制符号位扩展
//Vo_temp=0;
ADRESULT[0]=RESULT0>>6; // 将AD转换结果右移6位
ADRESULT[0]=ADRESULT[0]&0x03ff; // 去掉后2位(由外界干扰引起的测量不准
// Vo_temp+=ADRESULT;
ADRESULT[1]=RESULT1>>6;
ADRESULT[1]=ADRESULT[1]&0x03ff;
// Vo_temp+=ADRESULT;
ADRESULT[2]=RESULT2>>6;
ADRESULT[2]=ADRESULT[2]&0x03fc;
// Vo_temp+=ADRESULT;
ADRESULT[3]=RESULT3>>6;
ADRESULT[3]=ADRESULT[3]&0x03fc;
//Vo+=ADRESULT;
ADRESULT[4]=RESULT4>>6;
ADRESULT[4]=ADRESULT[4]&0x03fc;
//Vo+=ADRESULT;
ADRESULT[5]=RESULT5>>6;
ADRESULT[5]=ADRESULT[5]&0x03fc;
//Vo+=ADRESULT;
ADRESULT[6]=RESULT6>>6;
ADRESULT[6]=ADRESULT[6]&0x03fc;
//Vo+=ADRESULT;
ADRESULT[7]=RESULT7>>6;
ADRESULT[7]=ADRESULT[7]&0x03fc;
result=ADRESULT[0]+ADRESULT[1];
for(i=2;i<8;i++)
{
result=result+ADRESULT[i];
}
//Vo+=ADRESULT;
result=result/8; // 取8个AD转换结果的平均值
Vo_AD=result*3.3/1023; // 计算Vo模拟量
Vo_AD=Vo_AD * Vo_amplify; // 计算Vo真实值
// asm(" setc SXM"); // 符号位扩展有效
return Vo_AD;
}
/* 输出恒定控制字程序 */
void BoostControl(float Vo_BC)
{
float ek; // 存放当前误差
float ek_1; // 存放上次误差
float dk; // 存放当前PI控制输出量
float dk_1; // 存放上一次PI控制输出量
float delta_dk; // delta_dk=dk-dk_1
//float Vo=0; // 存放输入电压
float Vh,Vl,temp1,temp2;
int CMPR1_TEMP;
Vh=Vo_Constant;
Vh=Vh+Vo_error;
Vl=Vo_Constant;
Vl=Vl-Vo_error;
ek_1=ek_1_overall*10;
dk_1=dk_1_overall*10;
if(Vo_BC>Vh || Vo_BC<Vl)
{
ek=Vo_Constant;
ek=ek-Vo_BC; // 计算当前误差
delta_dk=Ki
delta_dk+=Kp;
delta_dk=delta_dk*ek;
temp1=Kp;
temp1=temp1*ek_1;
delta_dk=delta_dk-temp1;
dk=dk_1+delta_dk; // 计算当前占空比dk
if(dk>0.1428) // 限幅,占空比最大为14.29%
{
dk=0.1428;
}
if(dk<0)
{
dk=0;
}
temp2=PWM_period;
temp2=temp2*dk;
CMPR1_TEMP=temp2; // 通过得到的dk设置比较寄存器
CMPR1=CMPR1_TEMP;
ek_1_overall=ek/10; // 计算完成,则当前误差作为下次计算的上一次误差
dk_1_overall=dk/10; // 当前控制量作为下次计算的上一次控制量
}
return;
}
/* 若是其它中断则直接返回子程序 */
void interrupt nothing()
{
return;
}
/* 定时器2周期中断服务程序 */
void interrupt t3int()
{
int flag; // 定义一个局部变量
float Vo;
i=i+1; // 察看中断次数
flag=EVBIFRA&0X0080;
if(flag!=0x0080)
{
enable(); // 允许总中断
return; // 如果不是定时器2总中断,则直接返回
}
// 如果是定时器2的周期中断,则执行下面的程序
ADsoc(); // 启动AD转换
flag=AUTO_SEQ_SR&0X0F00;
while(flag>0){flag=AUTO_SEQ_SR&0X0F00;} // 等待AD转换结束
Vo=ADprocess(); // 对采样数据处理
BoostControl(Vo); // 对Boost电路进行PI控制,使输出维持在28V
T3CNT=0X00; // 定时器2的计数器重新赋0
EVBIFRA=EVBIFRA&0X0080; // 清除定时器2周期中断标志,否则以后的中断将被忽略
enable(); // 允许总中断,因一旦进入中断服务程序后总中断就自动关闭
return;
}
/* 主函数 */
main()
{
// float a=0.00001;
disable( ); // 禁止总中断
Initial( ); // 系统初始化
/* ek_1=a;
dk_1=a;
dk_1=1.6/4;
a=dk_1;
a=a*4.0;
ek_1=0;
dk_1=0;*/
Timer3init(); // 定时器2初始化
ADinit( ); // AD初始化子程序
PWMinit(); // PWM输出初始化
T1CON=T1CON|0x0040; // 启动定时器1,启动PWM输出
enable( ); // 开总中断
T3CON=T3CON|0x0040; // 启动定时器2
T3CON=T3CON|0x0040;
while(1)
{
;
} // 等待中断
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -