#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ADC_FLAG 0X10
#define M 40
/*****************************************
功能定义
*****************************************/
sbit lockA = P3^2; //
sbit lockB = P3^3; //
sbit Key_0 = P2^0; //Key_0
sbit Key_1 = P2^1; //Key_1
sbit Key_2 = P2^2; //Key_2
sbit Key_3 = P2^3; //Key_3
uchar PWM = 230;
uchar channel=0; //ADC采样第一通道
uint CurrentA; //设定A输出电流
uint CurrentB; //设定B输出电流
uint OUT_voltage; //输出电压
uint OUT_Current; //输出总电流
uchar KEY_VALUE = 5;
uchar X=1;
uchar Y=1;
uchar site = 12;
float SUM1, SUM2, SUM3 , I3;
uchar T1 = 0;
uint protect_i ;
xdata uint U1,I1,I2;
xdata float PI = 3.5;
xdata uint I1_VALUE[M] , I2_VALUE[M] , U1_VALUE[M] ;
//data 加强抗干扰能力
data bit Charge = 0;
data bit ADC_ready=0; //ADC完毕
data bit flag1 = 0;
data bit flag2 = 0;
data bit k=0;
data bit Release = 0;
data bit protect = 0; //过流保护
//函数说明: 延时程序
void delay(uchar t)
{
uint j;
uchar i;
for(i=0;i<t;i++)
for(j=0;j<1000;j++);
}
//1602液晶
sbit RS = P2^4;
sbit RW = P2^5;
sbit E = P2^6;
//短延时
void delay5ms()
{
uchar i,v,k;
for(i=1;i>0;i--)
for(v=168;v>0;v--)
for(k=22;k>0;k--);
}
//写指令
void lcd_Write_com(uchar com)
{
RS=0; //定义指令寄存器
RW=0; //写允许
P0=com; //写指令
delay5ms(); E=1; //片选端上拉
delay5ms(); E=0; //下降沿锁存
}
//写数据
void lcd_write_date(uchar date)
{
RS=1; //定义数据寄存器
RW=0; //写允许
P0=date; //写数据
delay5ms(); E=1; //片选端上拉
delay5ms(); E=0; //下降沿锁存
}
//显示程序
void dis_lcd1602(uchar x,uchar y,uchar dat)
{
uchar add;
if(y==1) add=(0x80+x);
if(y==2) add=(0xc0+x);
lcd_Write_com(add); //写指令
lcd_write_date(dat); //写数据
}
//液晶初始化
void lcd1602_init()
{
lcd_Write_com(0x38); //设置8位格式,2行,5*7
lcd_Write_com(0x01); //清屏
lcd_Write_com(0x0C); //整体显示,关光标,不闪烁
lcd_Write_com(0x06); //设定输入方式,增量不移位
lcd_Write_com(0x80); //初始坐标
}
//液晶显示汉字程序
void hz_lcdDis(uchar x,uchar y,uchar *p) //汉字显示
{
uchar i=0,temp;
if(x)temp = 0x40; else temp = 0;
for(i=y;*p!='\0';i++,p++)
{
lcd_Write_com(i|0x80+temp);
lcd_write_date(*p);
delay5ms();
}
}
//液晶显示数字程序
void num_lcdDis(uchar X,uchar Y,uint num,uchar n)
{
uint i=0,temp,hang;
n +=1;
if(X)hang = 0x40;else hang = 0;
for(i=(n-1);i>0;i--)
{
lcd_Write_com((i+Y-1)|0x80+hang); //从个位开始显示
temp = num%10+0x30;
lcd_write_date(temp);
delay5ms();
num/=10;
}
}
//函数说明: 平均滤波函数
#define N 50
uint Filter(uint adc_data)
{
uint value=0;
uchar count,count_ADC;
for(count=0;count<N;count++)
{
for(count_ADC=0;count_ADC<3;count_ADC++)
{
while(!ADC_ready){}
ADC_ready=0;
}
value+=adc_data;
}
return (value);
}
//函数说明: 按键程序
//开关按键
void Key_0_()
{
if(Charge==0) { lockA=0;lockB=0; hz_lcdDis(0,8,"K");num_lcdDis(0,11,X,2);num_lcdDis(0,14,Y,2);} //0有效
else { lockA=1;lockB=1; hz_lcdDis(0,8,"G");num_lcdDis(0,11,X,2);num_lcdDis(0,14,Y,2);} //1有效
Charge=~Charge;
}
//函数说明:按键程序
//调整光标位置
void Key_1_()
{
lockA=1;
lockB=1;
flag1 = 1;
flag2 = 1;
hz_lcdDis(0,8,"G");
if(k) { site = 14; hz_lcdDis(0,14," _");num_lcdDis(0,11,X,2); }
else { site = 12; hz_lcdDis(0,11," _");num_lcdDis(0,14,Y,2); }
k =~k;
}
//函数说明: 按键程序
//
void Key_2_()
{
Charge = 0;
lockA=1;
lockB=1;
hz_lcdDis(0,8,"G");
if((site == 12)&&(X < 255)) { ++X; num_lcdDis(0,11,X,2);}
else if((site==14)&&(Y < 255)) { ++Y; num_lcdDis(0,14,Y,2);}
}
//函数说明: 按键程序
//任意比例设定-
void Key_3_()
{
flag1 = 1;
flag2 = 1;
Charge = 0;
lockA=1;
lockB=1;
hz_lcdDis(0,8,"G");
if((site == 12)&&(X > 0 )) { --X; num_lcdDis(0,11,X,2);}
else if((site==14)&&(Y > 0)) { --Y; num_lcdDis(0,14,Y,2);}
}
//按键扫描
void key_scan()
{
uchar temp;
temp = P2&0x0F;
if(temp != 0x0F)
{
delay(10);
temp = P2&0x0F;
if(temp!= 0x0F)
{
Release = 1;
switch(temp)
{
case 0x0E: KEY_VALUE = 0; break; //20
case 0x0D: KEY_VALUE = 1; break; //21
case 0x0B: KEY_VALUE = 2; break; //22
case 0x07: KEY_VALUE = 3; break; //23
default: KEY_VALUE = 4; break;
}
}
}
else Release = 0;
if( Release ==0 )
{
switch( KEY_VALUE )
{
case 0: Key_0_(); KEY_VALUE = 4; break;
case 1: Key_1_(); KEY_VALUE = 4; break;
case 2: Key_2_(); KEY_VALUE = 4; break;
case 3: Key_3_(); KEY_VALUE = 4; break;
default: break;
}
}
}
//函数说明: PWM初始化
void init_pwm()
{
CCON = 0;
CL = 0;
CH = 0;
CMOD = 0X08; //0X08:43KHZ // 0X02,22KHZ // 0X0A,10KHZ //
CCAPM1 =0x42; //8位PWM输出,无中断
CCAP1L =CCAP1H = 230;//初始化pwm输出的占空比 上电默认2A 电流值对应电压值进行换算即可
CR=1;
}
//函数说明: 中断 始化函数
void InitADC()
{
P1M1=0x27; //0x00100111
P1M0=0x00;
P1ASF=0X27; //选择ADC通道0125
ADC_RES=0;
ADC_CONTR=0X88; //1110 0000 E8 开电源,最高速
EA=1;
EADC=1;
}
void DISPLAY(void)
{
if(T1 < M)
{
I1_VALUE[T1] = I1;
SUM1 += I1_VALUE[T1];
I2_VALUE[T1] = I2;
SUM2 += I2_VALUE[T1];
U1_VALUE[T1] = U1;
SUM3 += U1_VALUE[T1];
T1++;
if( T1 >= M)
{
T1 = 0 ;
SUM1 /= M;
SUM2 /= M;
SUM3 /= M;
if(SUM1 > 2) SUM1 += 1;
if(SUM2 > 2) SUM2 += 1;
num_lcdDis(1,11,(uint)(SUM3)/10,2);
num_lcdDis(1,14,(uint)SUM3%10,1);
num_lcdDis(0,3,(uint)SUM1/100,1);
num_lcdDis(0,5,(uint)SUM1%100,2);
num_lcdDis(1,3,(uint)SUM2/100,1);
num_lcdDis(1,5,(uint)SUM2%100,2);
SUM1 = 0;
SUM2 = 0;
SUM3 = 0;
}
}
}
void PI_calculate(void)
{
if(Charge == 1) //Charge 模式下进行自动调整
{
if((float)I1 > ((float)X/(float)Y)*I2 ) PI += 0.1 ;
else PI -= 0.1 ;
CCAP1L = CCAP1H = PWM;
if((flag1 == 1)&&(flag2 == 1)) //进入比例模式 比例最大 2:0.5即4:1 最小0.5:2 即1:4
{
PWM = 255-(uint)((I3*X/(X+Y)-PI)*256/500+0.5); //255-(uint)((I3*X/(X+Y))*255/500+0.5); //电流值等于电压值 I3*X/(X+Y)/100/5*255 1为调节量
}
else if((flag1==0)&&(flag2==0)&&(I3 < 200)) //2A切换点
{
PWM = 230; //切换到0.5A模式
}
else if((flag1==0)&&(flag2==0)&&(I3 > 200))
{
PWM = 153; //切换到2A模式
}
}
}
void Protect_recover(void)
{
if((protect == 1)&&(protect_i++>500)) //延时自恢复 大概半分钟S
{
lockA=0; lockB=0;
protect_i = 0;
protect = 0;
hz_lcdDis(0,8,"K");
}
}
//函数说明: 主函数
void main(void)
{
lockA=1;
lockB=1;
lcd1602_init();
hz_lcdDis(0,4,"Welcome!");
init_pwm();
InitADC();
delay(250);
EA=1; //开总中断
lcd_Write_com(0x01); //清屏
hz_lcdDis(0,0,"CA= . A S= X: Y ");
hz_lcdDis(1,0,"CB= . A U= . V");
while(1) //主循环
{
EA = 1;
I1=Filter(CurrentA)/99; //输出实际电流 Filter()=0.02Ω*I*放大倍数*1023/5v*50=I*放大倍数*204.6,为了显示放大100倍处理 =102.3
I2=Filter(CurrentB)/100; //输出实际电流 Filter()=0.02Ω*I*放大倍数*1023/5v*50=I*放大倍数*204.6,为了显示放大100倍处理 =102.3 //总电流
U1=Filter(OUT_voltage)/255; //输入电压 1:3采样电阻 ,Filter()*5V*4/(50*1023) 同时为了小数转成uint时,需要进行*10,使真实位变小数位 =255.7;显示数值滤波处理
EA = 0;
I3=I1+I2;
if(I3 > 450) //4.5A保护
{ lockA=1; lockB=1; hz_lcdDis(0,8,"P");protect = 1;}
Protect_recover(); //自恢复时间在半分钟
PI_calculate();
DISPLAY();
key_scan();
}
}
//函数说明: ADC中断
//实现功能:执行ADC采集并做电压和电流的调整。
void ADC_interrupt()interrupt 5 //ADC转换完后ADC_FLAG由硬件自动置位,须由软件清零
{
uint ADC_value; //ADC转换结果 10位
ADC_value=(ADC_RES<<2)+ADC_RESL; //ADC_value=(ADC_RES<<2)+ADC_RESL;
switch(channel)
{
case 0: CurrentA=ADC_value;
channel=1;
break;
case 1: CurrentB=ADC_value;
channel=5;
break;
case 5:OUT_voltage=ADC_value;
channel=0;
break;
default:break;
}
ADC_CONTR&=!ADC_FLAG; //清除 ADCflag
ADC_CONTR=0xE8|channel;
ADC_ready=1;
}
compiling 2011.c...
2011.C(30): error C231: 'T1': redefinition
2011.C(30): error C231: 'T1': redefinition
2011.C(245): error C202: 'CCON': undefined identifier
2011.C(246): error C202: 'CL': undefined identifier
2011.C(247): error C202: 'CH': undefined identifier
2011.C(248): error C202: 'CMOD': undefined identifier
2011.C(249): error C202: 'CCAPM1': undefined identifier
2011.C(250): error C202: 'CCAP1L': undefined identifier
2011.C(251): error C202: 'CR': undefined identifier
2011.C(257): error C202: 'P1M1': undefined identifier
2011.C(258): error C202: 'P1M0': undefined identifier
2011.C(259): error C202: 'P1ASF': undefined identifier
2011.C(260): error C202: 'ADC_RES': undefined identifier
2011.C(261): error C202: 'ADC_CONTR': undefined identifier
2011.C(263): error C202: 'EADC': undefined identifier
2011.C(312): error C202: 'CCAP1L': undefined identifier
2011.C(377): error C202: 'ADC_RES': undefined identifier
2011.C(391): error C202: 'ADC_CONTR': undefined identifier
2011.C(392): error C202: 'ADC_CONTR': undefined identifier
2011.c - 19 Error(s), 0 Warning(s).
|