打印

51单片机串口通讯,单片机为什么只能接收一次指令

[复制链接]
1606|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
daiya1981|  楼主 | 2015-8-2 08:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
51串口通讯,单片机本该不断接收串口调试助手的指令,动态改变数码管和LED显示内容的,可是下面的程序只能接收一次指令,再发送就没反应了,该怎么修改才能实现不断自动接收指令呢?

代码如下:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar SEG7[16]={0xc0,0xf9,0xa4,0xb0,
                                                                0x99,0x92,0x82,0xf8,
                                                                0x80,0x90,0x88,0x83,
                                                                0xc6,0xa1,0x86,0x8e};
uchar ACT[4]={0xf7,0xfb,0xfd,0xfe};

/***************************************************/
sbit D0=P2^0;
sbit D1=P2^1;
sbit D2=P2^2;
sbit D3=P2^3;
sbit D4=P2^4;
sbit D5=P2^5;
sbit D6=P2^6;
sbit D7=P2^7;
#define ON 0
#define OFF 1
uchar a[5];
bit outflag=0;
uint len=0;
/***************************************************/
void delay(uint k)
{
        uint i,j;
        for(i=0;i<k;i++)
        {
                for(j=0;j<121;j++)
                {
                        ;
                }
        }
}
/***************************************************/
void init(void)
{
        TMOD=0x20;
        TH1=0xfd;
        TL1=0xfd;
        TR1=1;
        SCON=0x50;
        EA=1;
        ES=1;
}
/***************************************************/
void main(void)
{
        init();
        while(1)
        {
                P0=SEG7[a[1]];
                P1=ACT[1];
                delay(1);
                P0=SEG7[a[3]];
                P1=ACT[0];
                delay(1);
                if(outflag==1)
                {
                        switch(a[1])
                        {
                                case 1:if(a[3]==1)D0=ON;else D0=OFF;break;
                                case 2:if(a[3]==1)D1=ON;else D1=OFF;break;
                                case 3:if(a[3]==1)D2=ON;else D2=OFF;break;
                                case 4:if(a[3]==1)D3=ON;else D3=OFF;break;
                                case 5:if(a[3]==1)D4=ON;else D4=OFF;break;
                                case 6:if(a[3]==1)D5=ON;else D5=OFF;break;
                                case 7:if(a[3]==1)D6=ON;else D6=OFF;break;
                                case 8:if(a[3]==1)D7=ON;else D7=OFF;break;
                                default:break;
                        }
                        outflag=0;
                }
        }
}
/***************************************************/
void serial_serve(void) interrupt 4
{
        if(RI==1)
        {
                RI=0;
                if(!outflag)
                {
                        if((SBUF=='#')&&(len==0))
                        {
                                a[0]=SBUF;
                        }
                        else
                        {
                                len=len+1;
                                a[len]=SBUF;
                                if(len==4)
                                {
                                        a[1]=a[1]-0x30;
                                        a[3]=a[3]-0x30;
                                        len=0;
                                        outflag=1;
                                }       
                        }
                }                                       
        }
}

相关帖子

沙发
gx_huang| | 2015-8-2 10:23 | 只看该作者
似乎没有看出什么问题,是发#123之类的指令吧。
中断程序中,最好先把SBUF读出到一个变量,然后判断这个变量,不要反复操作SBUF。

使用特权

评论回复
板凳
gx_huang| | 2015-8-2 10:30 | 只看该作者
另外,从软件角度考虑问题,串口中断的a[]数组,当接收到帧尾时,最好处理后转存到另外一个数组或者变量。你目前的串口命令比较短,问题不大,在比较复杂的系统中,最好还是小心一些。也许前面一帧命令刚接收到,还没有执行完,后面的命令又下发了,部分内容被覆盖了。
请参考一下我下面的程序处理。
void uart_int() interrupt 4
{
        uchar i,buff;
        if(TI)
        {
                TI=0;
                for(i=0;i<15;i++){;}
                i=*uart_s;
                uart_s++;
                if(i!=0)
                {
                        T_R=1;
                        SBUF=i;
                        tx=1;
                }
                else
                {
                        tx=0;
                        T_R=0;
                }
        }
        if(RI)
        {
                buff=SBUF;RI=0;
                //tx_1s_en=0;
                if(rcv_cnt==0)
                {
                        if(buff=='W' || buff=='R' || buff=='F')
                        {
                                rcv_cnt=1;
                                rcv_buff[0]=buff;
                        }
                }
                else
                {
                        if(buff>='0' && buff<='9') buff=buff-'0';
                                else if(buff>='A' && buff<='F') buff=buff-'A'+10;
                                        else buff=0xff;

                        rcv_buff[rcv_cnt]=buff;
                        rcv_cnt++;
                        if((rcv_cnt>=11 && rcv_buff[0]=='W')
                                || (rcv_cnt>=2 && rcv_buff[0]=='R')
                                        || (rcv_cnt>=2 && rcv_buff[0]=='F'))
                        {
                                rcv_cnt=0;
                                for(i=0;i<11;i++) data_buff[i]=rcv_buff[i];
                                rcv_ok=1;
                        }
                }
        }
}

使用特权

评论回复
地板
runningwzf| | 2015-8-2 18:36 | 只看该作者
串口这东西传输多字节,建议还是加入协议,比如SLIP

使用特权

评论回复
5
森林长老| | 2020-7-1 07:05 | 只看该作者
学习了,谢谢!

使用特权

评论回复
6
ayb_ice| | 2020-7-1 08:23 | 只看该作者
本帖最后由 ayb_ice 于 2020-7-1 08:25 编辑

一次中断SBUF只能读一次,SBUF是特殊的东西,实际是有两级缓冲的
最好的做法是
u8 ucTmp;
if (RI)
{
    ucTmp = SBUF;
    RI = 0;
....

当然此处不一定是这个问题

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

7

帖子

0

粉丝