找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3840|回复: 20
打印 上一主题 下一主题
收起左侧

大神们求助,我是小白,出现问题如下

[复制链接]
跳转到指定楼层
楼主
ID:221124 发表于 2017-7-20 16:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#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).
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:144941 发表于 2017-7-20 17:16 | 只看该作者
T1与寄存器重复定义了,还有些寄存器没有定义,看看引用头文件是否正确
回复

使用道具 举报

板凳
ID:221124 发表于 2017-7-20 17:39 | 只看该作者
whble 发表于 2017-7-20 17:16
T1与寄存器重复定义了,还有些寄存器没有定义,看看引用头文件是否正确

如何改
回复

使用道具 举报

地板
ID:144941 发表于 2017-7-20 17:57 | 只看该作者
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(30): error C231: 'T1': redefinition
2011.C(30): error C231: 'T1': redefinition与#include <reg52.h>里面一个寄存器定义重复 换个比如A1什么的
回复

使用道具 举报

5#
ID:213173 发表于 2017-7-20 18:13 | 只看该作者
全部错误都是相应寄存器没有定义,或者说是头文件用错。#include <STC15F2K60S2.H>
1个警告是:void dis_lcd1602(uchar x,uchar y,uchar dat) 没有引用
回复

使用道具 举报

6#
ID:221156 发表于 2017-7-20 18:34 | 只看该作者
头文件未引用,重新检查一下。
回复

使用道具 举报

7#
ID:221124 发表于 2017-7-22 17:28 | 只看该作者
改完之后出现这样的问题如何弄   求助啊
Build target 'Target 1'
linking...
BL51 BANKED LINKER/LOCATER V6.22 - SN: Eval Version
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2009
"STARTUP.obj",
"6.obj"
TO "6"
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_DIS_LCD1602?6
******************************************************************************
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 08DBH BYTE (110%) *
******************************************************************************
Program Size: data=74.7 xdata=250 code=3502
LINK/LOCATE RUN COMPLETE.  1 WARNING(S),  0 ERROR(S)
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_DIS_LCD1602?6
*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
    MODULE:  D:\KEIL4\C51\LIB\C51S.LIB (-----)
    LIMIT:   0800H BYTES
Target not created
回复

使用道具 举报

8#
ID:221124 发表于 2017-7-22 17:37 | 只看该作者
whble 发表于 2017-7-20 17:57
2011.C(245): error C202: 'CCON': undefined identifier
2011.C(246): error C202: 'CL': undefined iden ...

改完变成这样了,问题如下,求助啊,急
Build target 'Target 1'
linking...
BL51 BANKED LINKER/LOCATER V6.22 - SN: Eval Version
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2009
"STARTUP.obj",
"6.obj"
TO "6"
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_DIS_LCD1602?6
******************************************************************************
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 08DBH BYTE (110%) *
******************************************************************************
Program Size: data=74.7 xdata=250 code=3502
LINK/LOCATE RUN COMPLETE.  1 WARNING(S),  0 ERROR(S)
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_DIS_LCD1602?6
*** FATAL ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
    MODULE:  D:\KEIL4\C51\LIB\C51S.LIB (-----)
    LIMIT:   0800H BYTES
Target not created
回复

使用道具 举报

9#
ID:155507 发表于 2017-7-22 19:44 | 只看该作者
你的软件没有破解,请按以下步骤破解
如何破解Keil
若不破解Keil,那么我们程序容量会被限制在2k内。若破解,代码的容量将不被限制。
第一步:打开Keil编译器
第二步:单击【File】
第三步:单击【License Management】
第四步:复制License Management界面中的CID号
第五步:打开注册机
第六步:将刚复制的CID号粘贴到注册机的CID号框中
第七步:点击【Generate】将会生成激活码
第八步:把生成的激活码复制粘贴到KEIL的New License ID Code(LIC)里
第九步:然后点击【Add Lic】
、  注册完成之后,会在License Management界面中间的PK51的后面添加使用截止日期到2020,说明已经成功破解了。
注意:若破解的时候出现:
ERROR R206: NO REGISTRY ACCESS, ADMINISTRATION RIGHTS REQUIRED
【翻译】错误R206:没有注册使用权,需要管理员权限。
解决方法:
用管理员的身份运行Keil这个编译器,然后再按上述的方法操作一遍即可破解。


http://pan.baidu.com/s/1jIiNr8M
keil4自己下载吧,破解版
回复

使用道具 举报

10#
ID:213173 发表于 2017-7-22 19:47 | 只看该作者
为你写诗 发表于 2017-7-22 17:37
改完变成这样了,问题如下,求助啊,急
Build target 'Target 1'
linking...

1.用#include "STC15F2K60S2.h"代替#include <reg52.h>
2.把下面STC15F2K60S2.H文件复制放到你的工程文件里以便调用
3.注释掉void dis_lcd1602(uchar x,uchar y,uchar dat)程序中没有引用
已经验证过了,这3件事做好编译就能通过。
STC15F2K60S2.zip (2.33 KB, 下载次数: 11)


回复

使用道具 举报

11#
ID:220342 发表于 2017-7-23 11:41 | 只看该作者
T1这个和单片机的寄存器名称重复了,还有其它的CCON、\CH没作定义就用了,当然会报错
回复

使用道具 举报

12#
ID:220342 发表于 2017-7-23 11:42 | 只看该作者
你试下将所用T1改为其他名称,例如A试下
回复

使用道具 举报

13#
ID:213173 发表于 2017-7-27 21:33 | 只看该作者
在程序中用//或/**/注释掉某段语句的性质和删除是一样的,不同的是可以非常方便的恢复。
/*
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);        //写数据
}  */
回复

使用道具 举报

14#
ID:222959 发表于 2017-7-28 11:13 | 只看该作者
可以先检查一下头文件
回复

使用道具 举报

15#
ID:105206 发表于 2017-7-28 13:59 | 只看该作者
老兄,我改了头文件,编译没问题的,
Build target 'Target 1'
compiling main.c...
linking...
Program Size: data=51.7 xdata=250 code=3428
".\Objects\test" - 0 Error(s), 0 Warning(s).
Build Time Elapsed:  00:00:00
回复

使用道具 举报

16#
ID:105206 发表于 2017-7-28 14:01 | 只看该作者
这是你的文件

#include <STC12C5A60S2.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;               
}
回复

使用道具 举报

17#
ID:493140 发表于 2019-5-12 12:05 | 只看该作者
解决了没有
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表