单片机程序

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define choose P2
#define chose41 P1
//引脚定义
uchar code c485[]={0xf0,0xf2,0xf4,0xf8,0x8f,0x9f,0xaf,0xbf,0xcf,0xdf,0xef,0xff};
sbit ros_l=P1^7;   //收发控制
sbit dog=P3^2;    //看门狗
sbit led=P3^5;    //指示灯
sbit c42=P3^3;        //4051  控制
sbit c41=P1^0;     //4051  控制
//变量定义
uint num=0;      //计时计数
bit sm=0;       //灯闪烁
bit tw=1;        //02 03 判断是否重复发送
uchar rxd_buf[11];   //缓冲区
uchar fs[11];  //命令字
uchar temp;     //暂存P0
uchar hc;   //缓冲区控制
//----------函数定义---------------
//------------------------
//延时函数
//------------------------
debouncer(uint tms)
{
    uint i;
    uchar y;
    for(i=0;i<tms;i++)
        for(y=0;y<120;y++);
    }
//--------------------
//系统初始化
//--------------------
init()
{
    c41=1;   
    c42=1;
    dog=1;
    WR=0;
    RD=0;

    TH0=0xFC;
    TL0=0x66;
    TR0=1;
   
    ET0=1;//开定时器0中断
    }
//----------------------
//串口初始化
//----------------------
initser()
{
    ros_l=0;         //默认处于发送
    TMOD=0x21;//定时器1工作模式2
    PCON=0x00;
    TH1=0xfd;
    SCON=0x50;
    TR1=1;
    RI=0;
    ES=1;
    EA=1;  //总中断
    PS=1;
    }
//---------------
//喂狗程序
//---------------
fordog()
{
    dog=0;
    debouncer(1);
    dog=1;
    }
//----------------------
//串口发送(单字节)
//----------------------
void com(uchar tt)
{
    ros_l=1;
    debouncer(1);
    SBUF=tt;
    EA = 0;
    while(TI==0);
    TI=0;
    EA = 1;
    ros_l=0;
    }
//--------------------
//串口发送(多字节)
//--------------------
void comm(uchar *tt,uchar len)
{
    ros_l=1;
    debouncer(2);
    EA=0;
    do
    {
        SBUF=*tt++;
        while(TI==0);
        TI=0;
        }while(--len!=0);
    EA=1;
    debouncer(2);
    ros_l=0;
    }
//-----------------------
//关掉LED
//-----------------------
leddown()
{
    P0=0xFF;
    choose=0x00;
    choose=0x20;   //457的上升沿,使LED显示
    debouncer(2);
    choose=0x80;   //457的上升沿,使LED显示
    }
//-------------------------
//上电执行一次LED闪烁
//-------------------------
ledup()
{
    P0=0x00;
    choose=0x00;
    choose=0x20;   //457的上升沿,使LED显示
    debouncer(2);
    choose=0x80;   //457的上升沿,使LED显示
    debouncer(1000);
    leddown();
    }
//-----------------------
//574错误处理
//-----------------------
void out574();
multi()//对temp处理 处理成单一的按键
{
    uchar t,i,b,c[8];
    bit a;
    b=temp;
    t=0;
    for(i=0;i<8;i++)
    {
        a=((b>>i)&0x01);
        if(a==0)
            {
                c[t]=(0x01<<i);
                t++;
                }               
        }
    b=TL1;
    temp=~c[b%t];
    out574();
    }
//-----------------------
//574输出
//-----------------------
void out574()
{
    switch(temp)
    {
        case 0xFE:
            if(choose==0x40)
            {
                P0=0x7F;   
                }
            if(choose==0x60)
            {
                P0=0xF7;   
                }
            break;
        case 0xFD:
            if(choose==0x40)
            {
                P0=0xBF;   
                }
            if(choose==0x60)
            {
                P0=0xFB;   
                }
            break;
        case 0xFB:
            if(choose==0x40)
            {
                P0=0xDF;   
                }
            if(choose==0x60)
            {
                P0=0xFD;   
                }
            break;
        case 0xF7:
            if(choose==0x40)
            {
                P0=0xEF;   
                }
            if(choose==0x60)
            {
                P0=0xFE;   
                }
            break;
        case 0xEF:P0=0xF7;break;
        case 0xDF:P0=0xFB;break;
        case 0xBF:P0=0xFD;break;
        case 0x7F:P0=0xFE;break;
        default:                             //进行temp的异常处理
            switch(fs[1])
            {
                case 0x01:
                case 0x02:multi();break;     //01 02 调用multi() ;03时不进行处理
                default:break;
                }
            break;
        }
    }
//-----------------------
//随机片选74LS245
//-----------------------
whi245()
{
    uchar b;
    b=TL1;
    switch(b%2)
    {
        case 0:
            choose=0x40;
            break;
        case 1:
            choose=0x60;
            break;
        default:break;
        }
    }
//----------------------------
//01模式下执行的数据处理
//----------------------------
dat245_1()
{
    switch(choose)
     {
         case 0x40:    //前8个中的有变化
             out574();
             choose=0x00;
            debouncer(2);
            choose=0x80;   //457的上升沿,使LED显示
            fs[3]=0;
            if(fs[2]!=~temp)
            {
                fs[2]=~temp;
                tw=1;
                }
            else
            {
                tw=0;
                }
             break;
         case 0x60:   //后4个中有变化
             out574();
             choose=0x20;
            debouncer(2);
            choose=0x80;   //457的上升沿,使LED显示
            fs[2]=0;
            if(fs[3]!=~(temp&0x0F))
            {
                fs[3]=~(temp&0x0F);
                tw=1;
                }
            else
            {
                tw=0;
                }
            break;
         default:break;
         }
    }
//-----------------------
//处理函数
//-----------------------
manage()
{
    uchar history[12];
    uchar t,i;
    switch(fs[1])
    {
        case 0x01:
            c41=1;
            c42=1;
            sm=1;   //闪烁控制开启1/4S
            num=0;
            leddown();
            whi245();
            while(P0==0xff&&sm==1)  //端口没有变化一直等待,并由定时器中断控制片选
            {
                fordog();
                }
            temp=P0;  //P0存入缓冲区
            if(sm==1)      // 只有在扫描时  才对接收的数据进行处理
            {
                EA=0;     //关掉总中断
                dat245_1();
                fs[10]=fs[1]^fs[2]^fs[3];
                comm(fs,11);
                sm=0;
                num=0;
                }
            break;
        case 0x02:                 //有过的按键不再进行发送
            for(t=0;t<12;t++)        //在记录中都写入FF使得在中断此命令时不会再进行数据处理
            {
                history[t]=0xff;   
                }
            t=0;                   
            c41=1;
            c42=1;
            sm=1;
            num=0;
            while(sm==1)   //循环进行扫描
            {
                leddown();
                whi245();
                while(P0==0xFF&&sm==1)  //端口没有变化一直等待,并由定时器中断控制片选
                {
                    fordog();
                    }
                temp=P0;  //P0存入缓冲区
                   ET0=0;    //关掉定时器0中断           
                switch(choose)
                 {
                     case 0x40:    //前8个中的有变化
                         out574();
                         choose=0x00;
                        debouncer(2);
                        choose=0x80;   //457的上升沿,使LED显示
                          fs[3]=0;
                        for(i=0;i<t;i++)
                        {
                            tw=1;
                            if(history[i]==~temp)  //有相同元素tw=0,并跳出;
                            {
                                tw=0;
                                    break;
                                }
                            }
                        if(tw==1)       //没有相同元素
                        {
                            fs[2]=~temp;
                            history[t]=fs[2];
                            t++;
                            }
                     break;
                     case 0x60:   //后4个中有变化
                         out574();
                         choose=0x20;
                        debouncer(2);
                        choose=0x80;   //457的上升沿,使LED显示
                        fs[2]=0;
                        for(i=0;i<t;i++)
                        {
                            tw=1;
                            if(history[i]==~(temp&0x0F))
                            {
                                tw=0;
                                break;
                                }
                            }
                           if(tw==1)
                        {
                            fs[3]=~(temp&0x0F);
                            history[t]=fs[3];
                            t++;
                            }
                         break;
                     default:break;
                         }
                fs[10]=fs[1]^fs[2]^fs[3];
                ET0=1;
                if(tw==1&&sm==1)
                {
                    comm(fs,11);
                    }
                fordog();
                }
            break;
      case 0x03:
              c41=1;
            c42=1;
            sm=1;
            num=0;
            while(sm==1)
            {
                whi245();
                while(P0==0xFF&&sm==1)
                {
                    fordog();
                    }
                temp=P0;
                ET0=0;
                dat245_1();
                fs[10]=fs[1]^fs[2]^fs[3];
                ET0=1;
                if((sm==1)&&(tw==1))
                {
                    comm(fs,11);
                    }
                }
            break;
       case 0x05:
            c41=1;
            c42=1;
            sm=0;
            initser();
            num=0;
            leddown();
            break;
        case 0x06://分数
        case 0x07://测试
            if(fs[2]==0xa5)   //出现07 A5的全部扫描时处理
            {
                for(i=0;i<12;i++)
                { 
                    c42=0;
                    if(i<4)
                    {
                        c42=1;
                        }
                    chose41=c485[i];
                    debouncer(1);
                    comm(fs,11);
                    initser();
                    }
                break;
                }
        case 0x08://闪烁
        case 0x09://灯带
            sm=1;
            num=0;
            leddown();
            switch(fs[2])
            {
                case 0x01:chose41=0xF0;c42=1;break;
                case 0x02:chose41=0xF2;c42=1;break;
                case 0x03:chose41=0xF4;c42=1;break;
                case 0x04:chose41=0xF6;c42=1;break;
                case 0x05:chose41=0x8F;c42=0;break;
                case 0x06:chose41=0x9F;c42=0;break;
                case 0x07:chose41=0xAF;c42=0;break;
                case 0x08:chose41=0xBF;c42=0;break;
                case 0x09:chose41=0xCF;c42=0;break;
                case 0x0A:chose41=0xDF;c42=0;break;
                case 0x0B:chose41=0xEF;c42=0;break;
                case 0x0C:chose41=0xFF;c42=0;break;
                default: break;
                }
            if(sm==1)
            {
                ros_l=1;   //发送态
                debouncer(2);
                comm(fs,11);
                ros_l=0;  //接收状态
                initser();
                c41=1;
                c42=1;
                EA=1;
                }
            sm=0;
            num=0;
            break;
        default:break;
        }
    }
//----------------------
//串口数据处理
take()
{
    uchar i,te;
    te=0x00;
    for(i=1;i<6;i++)      // 计算校验值
    {
        te^=rxd_buf[i];
        }
    if((rxd_buf[0]==0x51)&&(rxd_buf[10]==te))  //数据完整  校验正确
    {
        fordog();
        for(i=0;i<11;i++)
        {
            fs[i]=rxd_buf[i];
            rxd_buf[i]=0;
            }
        manage();
        }
    else
    {
        comm(rxd_buf,11);
        com(0xac);         //回送错误信号  请求重发
        }
    initser();
    }
//------------------------
//主函数
//------------------------
main()
{
    initser();
    init();
    ledup();
    hc=0;
    while(1)
    {
        fordog();
        if(hc==11)             //完成接收
        {
            hc=0;
            ES=1;
            initser();
            take();            //进行处理
            c41=1;   
            c42=1;
            }
         }
    }
//--------------------------
//LED闪烁控制
//--------------------------
void T1_time() interrupt 1
{
     TH0 =0xFC;
     TL0 =0x66;
     if(sm==1)//开始抢答,没有完成时
     {
         switch(choose)//每1ms进行一次切换
         {
             case 0x40:
                 choose=0x60;break;
             case 0x60:
                 choose=0x40;break;
             default:break;
             }
         }
     num++;
     if((num==1000)||(num==200&&sm==1))         //工作指示灯
    {
        led=~led;
        num=0;
        }
}
//-------------------------------
//串口中断程序
//-------------------------------
 void ser_int(void) interrupt 4         //串口接收中断,连续接收
{
    bit start=0;
    if(RI)
    {
        if(SBUF==0x51)
        {   
            rxd_buf[0]=SBUF;
            start=1;
            RI=0;
            ES=0;
            while(start==1)
            {
                for(hc=1;hc<11;hc++)
                {
                    while(!RI);
                    rxd_buf[hc]=SBUF;
                    RI=0;
                    }
                start=0;
                sm=0;
                }
            }
        }
    if(TI) //接收中断不处理
    {
        TI=0;
        }
    }

使用了74LS164,485等  怕自己以后用了找不到

有兴趣的可以看看 不懂的可以问我  大家一起讨论

我也是新手

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值