找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 730|回复: 3
收起左侧

单片机程序 只能切换LED1和LED2的状态,不能同时亮或同时灭 不知问题出在哪里?

[复制链接]
ID:706724 发表于 2023-3-6 14:59 | 显示全部楼层 |阅读模式
本例程是,STC官方的例程,学习过后,欲将其改造:通过按键改flag次数,然后将flag次数,写进EEPROM,再读取出来,相对应的LED状态随着flag的改变而改变。现在问题是:只能切换LED1和LED2的状态,不能同时亮或同时灭。不知问题出在哪里?请高手们不吝指导一下!谢谢!

    #include "STC8G.h"
    #include "intrins.h"

    #define FOSC        11059200UL
    #define BRT         (65536 - FOSC / 115200 / 4)

    #define uchar unsigned char   
    #define uint unsigned int
    //sfr     P0M1    =   0x93;
    //sfr     P0M0    =   0x94;
    //sfr     P1M1    =   0x91;
    //sfr     P1M0    =   0x92;
    //sfr     P2M1    =   0x95;
    //sfr     P2M0    =   0x96;
    //sfr     P3M1    =   0xb1;
    //sfr     P3M0    =   0xb2;
    //sfr     P4M1    =   0xb3;
    //sfr     P4M0    =   0xb4;
    //sfr     P5M1    =   0xc9;
    //sfr     P5M0    =   0xca;

    //sfr     AUXR    =   0x8e;
    //sfr     T2H     =   0xd6;
    //sfr     T2L     =   0xd7;

    //sfr     IAP_DATA    =   0xC2;
    //sfr     IAP_ADDRH   =   0xC3;
    //sfr     IAP_ADDRL   =   0xC4;
    //sfr     IAP_CMD     =   0xC5;
    //sfr     IAP_TRIG    =   0xC6;
    //sfr     IAP_CONTR   =   0xC7;
    //sfr     IAP_TPS     =   0xF5;

    //void UartInit()
    //{
    //    SCON = 0x5a;
    //    T2L = BRT;
    //    T2H = BRT >> 8;
    //    AUXR = 0x15;
    //}

    //void UartSend(char dat)
    //{
    //    while (!TI);
    //    TI = 0;
    //    SBUF = dat;
    //}
    sbit LED1=P5^4;
    sbit LED2=P3^3;
    sbit KEY=P3^2;
    //          uchar V;
    char flag=1;

    void IapIdle()
    {
            EA=0;                                          //禁止中断
        IAP_CONTR = 0;                              //关闭IAP功能
        IAP_CMD = 0;                                //清除命令寄存器
        IAP_TRIG = 0;                               //清除触发寄存器
        IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
        IAP_ADDRL = 0;
            EA=0;                                         //重启中断
    }

    char IapRead(int addr)
    {
        char dat;
    EA=0;
        IAP_CONTR = 0x80;                           //使能IAP
        IAP_TPS = 12;                               //设置等待参数12MHz
        IAP_CMD = 1;                                //设置IAP读命令
        IAP_ADDRL = addr;                           //设置IAP低地址
        IAP_ADDRH = addr >> 8;                      //设置IAP高地址
        IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
        _nop_();
        dat = IAP_DATA;                             //读IAP数据
        IapIdle();                                  //关闭IAP功能
            EA=1;
        return dat;

    }

    void IapProgram(int addr, char dat)
    {
            EA=0;
        IAP_CONTR = 0x80;                           //使能IAP
        IAP_TPS = 12;                               //设置等待参数12MHz
        IAP_CMD = 2;                                //设置IAP写命令
        IAP_ADDRL = addr;                           //设置IAP低地址
        IAP_ADDRH = addr >> 8;                      //设置IAP高地址
        IAP_DATA = dat;                             //写IAP数据
        IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
        _nop_();
        IapIdle();                                  //关闭IAP功能
            EA=1;
    }

    void IapErase(int addr)
    {
            EA=0;
        IAP_CONTR = 0x80;                           //使能IAP
        IAP_TPS = 12;                               //设置等待参数12MHz
        IAP_CMD = 3;                                //设置IAP擦除命令
        IAP_ADDRL = addr;                           //设置IAP低地址
        IAP_ADDRH = addr >> 8;                      //设置IAP高地址
        IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
        _nop_();                                    //
        IapIdle();                                  //关闭IAP功能
            EA=1;
    }

    void main(void)
    {
      uchar V;
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        P4M0 = 0x00;
        P4M1 = 0x00;
        P5M0 = 0x00;
        P5M1 = 0x00;

    //    UartInit();
    //    IapErase(0x0400);
    //    UartSend(IapRead(0x0400));
    //        P5=IapRead(0x0400);
    //    IapProgram(0x0400, 0x12);
    //    UartSend(IapRead(0x0400));
    //P3=IapRead(0x0400);
                  IT0 = 0;
            EX0 = 1;
            EA = 1;
               
          V = IapRead(0x0400);             // 开机读取EEPROM区数据,还原关电前LED的亮灭状况
            IapErase(0x0400);                 //擦除
                                 
             while(1)            
                                    
            {
                           IapProgram(0x0400, V);      //写入     
                            V= IapRead(0x0400);         //读取                        

               
                                          
          for(V=flag;flag<=4;flag++)
             {
                     if(V==1)
                            {
                                     LED1=0;LED2=1;
                                     IapErase(0x0400);          // 擦除
                                     IapProgram(0x0400, 1);     //写入
                                        }
                        if(V== 2)
                            {
                                                LED1=1; LED2=0;
                                                IapErase(0x0400);          // 擦除
                                               IapProgram(0x0400, 2);     //写入
                                                    }
                        if(V== 3)
                                 {
                                          LED1=0; LED2=0;
                                           IapErase(0x0400);          // 擦除
                                           IapProgram(0x0400, 3);     //写入
                                                            }
                      if(V== 4)
                              {
                                 LED1=1; LED2=1;
                                  IapErase(0x0400);          // 擦除
                                 IapProgram(0x0400, 4);    //写入
                                                            }
    }
                     }
            
                            }
    //--------------中断函数--------------
               
                            void int0_process() interrupt 0
    {

            if (KEY==1)  
        {  
                  
           if(flag<=4)flag++;
           else flag=1;
    //                         _nop_();
    //                         _nop_();
    //                         _nop_();
    //                         _nop_();

            
        }     



0dd052a361c499db25608fbb65b5c09.jpg
回复

使用道具 举报

ID:161164 发表于 2023-3-6 17:38 | 显示全部楼层
EEPROM有擦写寿命,大概100k
你把擦写放到while(1)中,估计一下子就爆了
建议当V有改变时才擦写EEPROM
回复

使用道具 举报

ID:213173 发表于 2023-3-6 20:25 | 显示全部楼层
V是随时变化的变量,只有断电保存才有实际意义。如此频繁保存,要不了几个时辰,单片机就废了。
回复

使用道具 举报

ID:965189 发表于 2023-3-6 23:56 | 显示全部楼层
进入while(1)之后就是不断擦除、写入,用意何在?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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