单片机/MCU论坛
直播中

jf_56123052

未满1年用户 3经验值
擅长:嵌入式技术
私信 关注
[讨论]

请大佬看看是代码哪儿的问题,显示eeprom的存储空间不足,试过好几种方法还是报错

# include

#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)INTOSC 振荡器, RA4、RA5为IO口
#pragma config WDTE = OFF      // Watchdog Timer Enable bit (WDT enabled)看门狗开
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)上电复位开
#pragma config MCLRE = OFF      // RA3/MCLR pin function select (RA3/MCLR pin function is digital I/O, MCLR internally tied to VDD)RA3/MCLR引脚功能为MCLR
#pragma config BOREN = OFF       // Brown-out Detect Enable bit (BOD enabled)欠压检测功能关
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)程序存储器代码保护被禁用
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)数据代码保护关
//__ CONFIG(0X31A4);
__EEPROM_DATA(5,50,67,6,5,0,0,0);   //0X00第一位表示定时倍数;0X01第二位表示最低电压-低;0X02第三位表示最高电压-高;0X03第四位表示清虫天数记录;0X04第五位表示清虫天数预设;0X05第五位表示为0铅酸电池(最低不能低于2点几V)、为1锂电池(最高不能超过12.6V);0X06空;0X07空

#define uchar unsigned char
#define uint unsigned int

/*#define EEPROM_ADDRESS 0x10 // 定义EEPROM地址

// 定义EEPROM中存储的数据
const unsigned char myEEPROMData[] __at(EEPROM_ADDRESS) = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
__EEPROM_DATA(5,50,67,6,5,0,0,0);*/

uint AN2_val;       //存放AN2通道模拟转换的值
uint AN4_val;       //存放AN4通道模拟转换的值
uchar i = 0;
uchar j = 0;
uint yanshi;
uchar AN2_num1;
uchar AN2_num2;
uchar AN2_num3;
uchar AN4_num1;
uchar AN4_num2;
uchar AN4_num3;
uchar AN4_num4;
uchar yukon_num1;
uchar yukon_num2;
uint anjian_num1;
uchar anjian_num2;
uchar n;
uint num;
uchar daochon_num;
uchar h;
uchar day;         //0为白天,1为晚上
uchar fuzhai=1;     //负载开启
uchar chondian;     //0为充电完成,1为充电未完成,继续充电
uchar taiyangban;   //1为太阳板电压高于电池,0为太阳板电压低于电池
uchar ONOFF=1;  //放电到充电一循环,1开启,0关闭
uchar qcts;
uchar k;
uchar a=6;
uchar t;
uchar z=0;
uchar m;

void init1()
{
    TRISA = 0b00110100;     //设置RA输入输出端口   RA2,RA4,RA5(AN2、AN3)为输入,其他输出
    TRISC = 0b00010011;     //设置RC输入输出端口   RC0、RC1、RC4(AN4、AN5)为输入,其他输出
    PORTA = 0b00000000;     //设置A端口输出为低电平
    PORTC = 0b00000000;     //设置C端口输出为低电平
    ANSEL = 0X14;           //ANS4=1,ANS2=1;AN4和AN2为模拟输入   二进制00010100
   /* CM2 = 1;                //CM2:CM0:111 比较器模式位(关闭)
    CM1 = 1;
    CM0 = 1;*/
    //ADCON1 = 0X10;          //ADCS<2:0>:A/D 转换时钟源选择位   0011 =FOSC/8  4MHz频率   二进制00010000
    ADCON1=0b01010000;  //AD,RC0(AN4)定义为AD口(A/D 转换时钟选择位)
}


void ADAN2()         //对RA2(AN2)进行A/D模拟转换输入
{   
    ADCON0 = 0X09;  //二进制0000 1001 (bit7:0 左对齐,bit6:0 参考电压VDD, bit5:0 未用, bit4-bit2:010 通道02(AN2), bit1:0 A/D转换结束/未进行, bit0:(ADON)1 A/D转换模块正在工作)    A/D 控制寄存器
    for (i=0; i<16; i++)
    {
        asm("NOP");  //稍微延时
        asm("NOP");
        asm("NOP");
        asm("NOP");  

        GO_DONE = 1;    //1 = A/D 转换正在进行。该位置 1 将启动 A/D 转换。 在转换结束后该位将被硬件自动清零。      ADCON0 _ A/D 控制寄存器
        while (GO_DONE)   //循环检测GO_DONE是否为0,为0转换结束
        {
            continue;
        }
        AN2_val + = ADRESH;   //将左对齐后的20次结果赋值
    }

    ADON = 0;   //A/D转换模块结束
    AN2_val = AN2_val/16;  //取20次检测电压的平均值

    if (AN2_val < eeprom_read(0X01))   //读写寄存器__EEPROM_DATA(5,50,67,6,5,0,0,0)中第二位,电源电压为10.8v时,电路分压后测出AN2电压为:0.98v  (5v是参考电压,一个数值代表多少电压:5/1024=0.00448,如果输入电压为0.98v,0.98/0.00448=218.75)
    {
        AN2_num1++;
        if(AN2_num1 > 16)     //(超过20次电压低于10.8v)
        {
            AN2_num1 = 0;   //计数清0
            fuzhai = 0;    //负载未开启工作
        }
    }
    else
    {
        AN2_num1 = 0;   //清0
    }

    if (AN2_val > eeprom_read(0X02))   //读写寄存器__EEPROM_DATA(5,50,67,6,5,0,0,0)中第三位,电源电压为14.4v时,电路分压后测出AN2电压为:1.31v   (如果输入电压为1.31v,1.31/0.00448=292.41)
    {
        AN2_num2++;
        if(AN2_num2++ > 16)   //(超过20次电压高于14.4v)
        {
            AN2_num2 = 0;   //计数清0
            chondian = 0;  //充电完成
        }
    }
    else
    {
        AN2_num3++;  //计数自增
        if (AN2_num3 > 16)   //(超过20次电压低于14.4v)
        {
            AN2_num3 = 0;   //计数清0
            chondian = 1;   //充电未完成,继续充电
        }
    }
}


void ADAN4()         //对RC0(AN4)进行A/D模拟转换输入
{
    ADCON0 = 0X11;  //二进制0000 1001 (bit7:0 左对齐,bit6:0 参考电压VDD, bit5:0 未用, bit4-bit2:100 通道04(AN4), bit1:0 A/D转换结束/未进行, bit0:(ADON)1 A/D转换模块正在工作)    A/D 控制寄存器
    for (j=0; j<16; j++)
    {
        asm("NOP");  //稍微延时
        asm("NOP");
        asm("NOP");
        asm("NOP");  

        GO_DONE = 1;    //1 = A/D 转换正在进行。该位置 1 将启动 A/D 转换。 在转换结束后该位将被硬件自动清零。      ADCON0 _ A/D 控制寄存器
        while (GO_DONE)   //循环检测GO_DONE是否为0,为0转换结束
        {
            continue;
        }
        AN4_val + = ADRESH;   //将左对齐后的20次结果赋值
    }

    AN4_val = AN4_val/16;  //取20次检测电压的平均值
    ADON = 0;   //A/D转换模块结束

    if(AN2_val - AN4_val < 13)   //连续检测20次太阳板比铅酸电池或锂电池低于3V   (晚上)
    {
        AN4_num1++;
        if (AN4_num1 > 24)  //(超过20次太阳板电压比电源电压低于3v)
        {
            AN4_num1 = 0;   //计数清0
            day = 1;   //晚上        
        }
    }   
    else
    {
        AN4_num1 = 0;
    }

    if (AN2_val - AN4_val > 23)  //连续检测20次太阳板高于5.5V的铅酸电池或锂电池   (白天)
    {
        AN4_num2++;
        if (AN4_num2 > 24)   //(超过20次太阳板电压比电源电压高于5.5v)
        {
            AN4_num2 = 0;
            day = 0;  //白天
        }
    }
    else
    {
        AN4_num2 = 0;
    }

    if (AN4_val < 0b00000011)  //连续检测20次太阳板电压高于电池电压,开始充电,连续检测20次太阳板电压低于电池电压,不充电
    {
        AN4_num3++;
        if (AN4_num3 > 16)  //连续检测20次太阳板电压高于电池电压
        {
            AN4_num3 = 0;  //计数清零
            taiyangban = 1;  //1为太阳板电压高于电池
            fuzhai = 1;  //负载工作开启
            ONOFF=1;  //放电到充电一循环,开启
        }
    }
    else
    {
        AN4_num4++;
        if (AN4_num4 > 16)  //连续检测20次太阳板电压低于电池电压
        {
            AN4_num4 = 0;  //计数清零
            taiyangban = 0;  //0为太阳板电压低于电池
        }
    }
}


void kaijishansuo()   //开机闪烁5次
{
    if (yanshi > 800)  //1s溢出(3906)
    {
        yanshi = 0;
        if (z == 0)
            z = 1;
        else
            z = 0;
        a--;
    }
}


void condianshansuo()    //充电连续闪烁   
{
    if (yanshi > 1500)  //1s溢出
    {
        yanshi = 0;
        if (z == 0)
            z = 1;
        else
            z = 0;
    }
}


void panduan ()    //转换后的数据判断,定义是否需要开灯、充电、雨控等待
{
    if (fuzhai == 1)   //负载开启
    {
        if (day == 1)  //晚上
        {
            if (ONOFF == 1)  //放电到充电一循环,开启
            {
                TMR1ON=1;  //中断TMR1开启,开始计时
                if (RC1 == 0)  //雨控控制,0为雨控检测无雨,短接帽断路
                {
                    yukon_num1++;
                    if (yukon_num1 > 16)  //检测超过20次没有雨
                    {
                        yukon_num1 = 0;  //计数清0
                        RC2 = 1;  //没有雨水,继电器启动
                    }
                }
                else   //雨控控制,0为雨控检测有雨,短接帽连通,将5v电压拉到RC1引脚
                {
                    yukon_num2++;
                    if (yukon_num2 > 16)   //检测超过20次有雨
                    {
                        yukon_num2 = 0;  //计数清0
                        RC2 = 0;   //下雨,继电器关闭
                    }
                }
            }
            else
            {
               RC2 = 0;  //未实现放电到充电的循环,继电器关闭,负载未启动
            }
        }
        else
        {
            RC2 = 0;  //白天继电器关闭,负载未启动
        }
    }
    else
    {
        RC2 = 0;  //继电器关闭,负载未启动
    }

    if (chondian == 1)  //1为充电未完成,继续充电
    {
        if (taiyangban == 1)  //1为太阳板电压高于电池
        {
            RC1 = 1;  //RC3高电平,电源模块充电,太阳板给电池充电
            if (num > 0)
                num = 0;  //定时清0
            if (h > 0)
                h = 0;
            condianshansuo();  ////充电蓝灯闪烁
        }
        else
        {
            RC3 = 0;  //充电完成,RC3低电平,电源模块不充电
            if (a < 1)   //蓝灯不闪烁
                z = 0;   //RA0=0
        }
    }
    else
    {
        RC3 = 0;  //充电完成,RC3低电平,电源模块不充电
        if (a < 1)  //蓝灯不闪烁
            z = 0;  //RA0=0
    }
}


void anxia()
{
    anjian_num1++;
    if (anjian_num1 > 4000)  
    {
        anjian_num1 = 0;
        anjian_num2++;  //增加一小时(定时数据)
        a = 2;   //蓝灯闪烁一次
        k = 1;  //有未写入数据
    }
}


void sonkai()
{
    if(k == 1)
    {
        eeprom_write(0x04,anjian_num2);  //把anjian_num2写到地址0x04
        qcts = anjian_num2;  //清除定时时间
        k = 0;   //没有未写入数据
        anjian_num1 = 0;  
        anjian_num2 = 0;  //清除定时数据
    }

    if(t == 1)  //开始读定时时间
    {
        if (a < 1)  //蓝灯不闪烁的时候
        {
            if (anjian_num2 > 0)  //定时时间大于0
            {
                anjian_num1++;
                if (anjian_num1 > 4000)  //延时7200
                {
                    if (anjian_num1%2000 == 0)  //延时时间/2000=0
                    {
                        anjian_num2--;  //减去一次已显示的
                        a = 2;    //蓝灯闪烁一次
                    }
                }
            }
            else
            {
                t = 0;    //读定时时间控制位清除
                anjian_num1;  //延时清零
            }
        }
    }
    else
    {
        if ( anjian_num1>200 )  //短按10s-20s之间,可以开始读定时间t=1
        {
            if (anjian_num1<1000)
            {
                a = 6;    //开始读蓝灯闪烁5次
                t = 1;    //开始读定时时间
                anjian_num2 = eeprom_read(0x04);     //从内存读取定时数据
            }
        }
        anjian_num1 = 0;   //延时清零
    }
}

void shezhi()  //设置定时时间
{
    if (RC4 == 0)  //按键按下
        anxia();
    else  //按键松开
        sonkai();
}


void dianchi()  //每次开机判断所使用的电池,和读入定时时间
{
    if (RA4 == 0 )  ////RA4口为低时是用蓄电池
    {
        if (eeprom_read(0x05)==1)   //如果RA4口为蓄电池,控制位为1时,就写入蓄电池的数据
        {
            eeprom_write(0x01,50);  //最低电压
            eeprom_write(0x02,67);  //最高电压
            eeprom_write(0x05,0);  //标记为蓄电池   ????
        }
    }
    else        //RA4口为高时是用锂电池
    {
         if (eeprom_read(0x05)==0)   //如果RA4口为锂电池,控制位为0时,就写入锂电池的数据
        {
            eeprom_write(0x01,43);  //最低电压(41)
            eeprom_write(0x02,58);  //最高电压
            eeprom_write(0x05,1);  //标记为锂电池   ???
        }
    }

    qcts = eeprom_read(0x04);    //(预计清·虫天数为5天一次)
    if(eeprom_read(0x03) <= qcts)   //(判断清除天数几天一次)
        eeprom_write(0x03,6);   //(将清虫天数记录设为6天一次)
}


void  init2 ()
{
    T0CS = 0;  //Timer0使用内部时钟             OPTION_REG _ 选择寄存器
    PSA=1;   //将预分频器给看门狗WDT           OPTION_REG _ 选择寄存器
    TMR0=0x00;  //定时器
    T0IF=1;  //Timer0 启动控制位使能(0关闭)(标志位)    INTCON _ 中断控制寄存器
    T0IE=1;  //Timer0中断开启(使能位)                   INTCON _ 中断控制寄存器

    TMR1CS = 0;  //Timer1使用内部时钟           Timer1 控制寄存器
    T1CKPS0=1;  //1:8倍预分频比                Timer1 控制寄存器      T1CKPS1:T1CKPS0:11=1:8倍预分频比
    T1CKPS1=1;  //1:8倍预分频比                Timer1 控制寄存器
    //TMR1H=(65536-(500000/8))/256; //初始化TMR1的高八位初始值   0.5s中断溢出一次
    //TMR1L=(65536-(500000/8))%256; //初始化TMR1的低八位初始值
    TMR1H=0x0B;  //高八位置初始值   
    TMR1L=0xE9;  //低八位置初始值  
    TMR1ON=0;  //Timer1 启动控制位使能(0关闭)       Timer1 控制寄存器
    TMR1IF=0;  //中断标志位清零                      外设中断标志寄存器 1
    TMR1IE=1;  //Timer1中断开启                      外设中断使能寄存器 1
    PEIE=1;  //外部中断开启                          INTCON ? 中断控制寄存器
    GIE=1;  //全局中断开启                           INTCON ? 中断控制寄存器
}


void dc()  //倒虫
{
    if (RC5 == 0)
        RC5 = 1;

    if (RC5 == 1  && RA5 == 0)
        m = 1;           //(步骤控制)

    if (RC5 == 1 && RA5 == 1 && m == 1)
    {
        daochon_num++;  //倒虫天数增加
        m = 0;
    }

    if (daochon_num >= 2)  //超过两天清一次虫
    {
        daochon_num = 0;   //清0
        RC5 = 0;
        eeprom_write(0x03,0);
    }
}

void interrupt time0()
{

   if (TMR1IF == 1)
    {
        TMR1IF=0;  //中断标志溢出清0
        //TMR1H=(65536-(500000/8))/256; //初始化TMR1的高八位初始值
        //TMR1L=(65536-(500000/8))%256; //初始化TMR1的低八位初始值
        TMR1H=0x0B;  //高八位置初始值   
        TMR1L=0xE9;  //低八位置初始值  
        num++;

        if (num == 139)  //定时计时1一个小时溢出
        {
            h++;  //每小时自增
            num = 0;  //溢出清0

            if (h == 1)
            {
                eeprom_write(0x03,eeprom_read(0x03)+1);  //清虫天数计数+1天
            }

            if (h == 5)  //等于设定的小时
            {
                h = 0;  //小时清零
                RC2 = 0;  //继电器/负载关闭
                ONOFF=0;  //放电到充电一循环,时间到置0,关闭               
                TMR1ON=0;  //Timer1 启动控制位使能(0关闭)
            }
        }
    }

   if (T0IF == 1)  //1 = TMR0 寄存器溢出 (必须在软件中清除) 0 = TMR0 寄存器没有溢出
   {
       T0IF = 0; //tmr0溢出清零
       yanshi++;
       TMR0=0x00;
       n++;
       if (n > 250)  //1s/256us=3906.25,1秒溢出
       {
           n = 0;  //溢出清0
           ADAN2();  //读AD转化口RA2/AN2
           ADAN4();  //读AD转化口RC0/AN4
           panduan ();  //转换后的数据判断,定义是否需要开灯、充电、雨控等待

           if (eeprom_read(0x03)>=qcts && TMR1ON==1)  //读清虫设定天数2天的时候  ?????
               dc();  //倒虫
       }

       if (a > 0)
           kaijishansuo();   //开机蓝灯闪烁5次
       if (z == 1)
           RA0 = 1;  //蓝灯闪烁
       else
           RA0 = 0;

       shezhi();  //设置定时时间
   }
}



void main ()
{
    init1();     //通道初始化

    init2 ();    //定时器初始化

    dianchi();   //电池选择

    dc();   //倒虫

    while (1)    //死循环
    {
    }
}
-----------------------------------------------------------
报错显示::: warning: (1273) Omniscient Code Generation not available in Free mode
miewendeng.c:479: warning: (752) conversion to shorter data type
D:\XC8\sources\pic\eeread.c:12: error: (1360) no space for auto/param eeprom_write@addr
(908) exit status = 1
nbproject/Makefile-default.mk:131: recipe for target 'dist/default/production/miewendeng.X.production.hex' failed
make[2]: Leaving directory 'D:/MPLAB X IDE v4.05��Ŀ/miewendeng.X'
nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed
make[1]: Leaving directory 'D:/MPLAB X IDE v4.05��Ŀ/miewendeng.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make[2]: *** [dist/default/production/miewendeng.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

编译已失败 (退出值2, 总时间: 1s)
----------------------------------------
警告:adcshili.c:418: warning: (752) conversion to shorter data type这个警告表示在第418行进行了将数据类型转换为较短的数据类型的操作。
错误:D:\XC8\sources\common\lwdiv.c:31: error: (1358) no space for _eeprom_read temps (1)这个错误表示编译器无法为_eeprom_read temps分配足够的空间。
eeprom_write(0x03,eeprom_read(0x03)+1);  //清虫天数计数+1天  418行
请问大佬这个代码该怎么改啊,刚刚入行的小白琢磨了好几天还是一头雾水。

更多回帖

发帖
×
20
完善资料,
赚取积分