搜索
bottom↓
回复: 38

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

[复制链接]

出0入0汤圆

发表于 2015-7-31 19:10:09 | 显示全部楼层 |阅读模式
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];
uchar cnt;
bit outflag;
/***************************************************/
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)
                {
                        ES=0;
                        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;
                        ES=1;
                }
        }
}
/***************************************************/
void serial_serve(void) interrupt 4
{
        uchar temp;
        uint i;
        if(RI==1)
        {
                RI=0;
                temp=SBUF;
                if(temp=='#')
                {
                        a[0]=temp;
                        for(i=1;i<5;i++)
                        {
                                while(RI!=1);
                                RI=0;
                                a[i]=SBUF;
                        }
                        a[1]=a[1]-0x30;
                        a[3]=a[3]-0x30;
                        outflag=1;               
                }
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2015-7-31 19:39:01 | 显示全部楼层
首先outflag没有赋初值,  “ while(RI!=1);                                 RI=0;”,这两句感觉很怪异,因为当串口接收完数据后自会产生中断!不用while语句。
PS:个人看法,水平较低,说错勿怪~

出0入0汤圆

发表于 2015-7-31 19:42:28 | 显示全部楼层
                   for(i=1;i<5;i++)
                        {
                                while(RI!=1);//这一句中断再次来的时候  会跳到中断开始去执行
                                RI=0;
                                a[i]=SBUF;
                        }

你非要用这种结构接收数据的话,在for前后关闭 开启中断。

出0入0汤圆

发表于 2015-7-31 19:51:17 | 显示全部楼层
   if(outflag==1)
                {
                        ES=0;               我 也 不 懂 但好奇,吧这里的 ES=0;去掉试下 看什么效果

出0入0汤圆

 楼主| 发表于 2015-7-31 20:08:04 | 显示全部楼层
代码修改如下,依旧只能接收一次指令

#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];
uchar cnt;
bit outflag=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
{
        uchar temp;
        uint i;
        if(RI==1)
        {
                RI=0;
          EA=0;
                temp=SBUF;
                if(temp=='#')
                {
                        a[0]=temp;
                        for(i=1;i<5;i++)
                        {
                                while(RI!=1);
                                RI=0;
                                a[i]=SBUF;
                        }
                        a[1]=a[1]-0x30;
                        a[3]=a[3]-0x30;
                        outflag=1;               
                }
        }
        EA=1;
}

出0入0汤圆

发表于 2015-7-31 20:29:30 | 显示全部楼层
daiya 发表于 2015-7-31 20:08
代码修改如下,依旧只能接收一次指令

#include

逻辑都没搞撑偷。
编下去肯定是错的

出0入0汤圆

发表于 2015-7-31 20:45:54 | 显示全部楼层
daiya 发表于 2015-7-31 20:08
代码修改如下,依旧只能接收一次指令

#include

这个中断程序不太正确,单片机没接收一个字节就会进入中断,所以在中断里有个for循环,执行这个完全没有意义

出0入0汤圆

 楼主| 发表于 2015-7-31 21:07:25 | 显示全部楼层
miaoguoqiang 发表于 2015-7-31 20:29
逻辑都没搞撑偷。
编下去肯定是错的

请问哪里逻辑不对呢?我是新手,经验不足

出0入0汤圆

 楼主| 发表于 2015-7-31 21:09:34 | 显示全部楼层
dlmaowf 发表于 2015-7-31 20:45
这个中断程序不太正确,单片机没接收一个字节就会进入中断,所以在中断里有个for循环,执行这个完全没有 ...

中断关了,执行for的

出0入0汤圆

发表于 2015-7-31 21:10:57 | 显示全部楼层
for(i=1;i<5;i++)
                        {
                                while(RI!=1);
                                RI=0;
                                a[i]=SBUF;去掉看  

出0入0汤圆

发表于 2015-7-31 19:10:10 | 显示全部楼层
daiya 发表于 2015-7-31 21:07
请问哪里逻辑不对呢?我是新手,经验不足

简单的修改一下,按照你的,大概意思应该是接受到#之后,再连续接收4个字节。
接收完成后主程序中进行处理。处理完成后继续判断#字符串的到来。

void serial_serve(void) interrupt 4
{
        uchar temp;
        static uint len=0;
        if(RI)
        {
                RI=0;
                                temp=SBUF;
                                if(!outflag)
                                {
                                        if((temp=='#')&&(len==0))
                                        {
                                                a[len++]=temp;
                                        }
                                        else if(len)
                                        {
                                                a[len++]=temp;
                                                if(len==5)
                                                {
                                                        a[1]=a[1]-0x30;
                                                        a[3]=a[3]-0x30;
                                                        len=0;
                                                        outflag=1;
                                                }       
                                        }
                                }
        }
}

出0入0汤圆

 楼主| 发表于 2015-7-31 21:20:27 | 显示全部楼层
miaoguoqiang 发表于 2015-7-31 21:12
简单的修改一下,按照你的,大概意思应该是接受到#之后,再连续接收4个字节。
接收完成后主程序中进行处 ...

是啊,我是想这样

出0入0汤圆

 楼主| 发表于 2015-8-1 08:06:57 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 08:27 编辑
miaoguoqiang 发表于 2015-7-31 21:12
简单的修改一下,按照你的,大概意思应该是接受到#之后,再连续接收4个字节。
接收完成后主程序中进行处 ...


我修改了一下,烧到实验板上,可是没有反应,请帮我看看代码有没有什么问题!

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;
                                }       
                        }
                }
                                       
        }
}

出0入0汤圆

发表于 2015-8-1 10:12:52 | 显示全部楼层
daiya 发表于 2015-8-1 08:06
我修改了一下,烧到实验板上,可是没有反应,请帮我看看代码有没有什么问题!

void serial_serve(void)  ...

有问题,如果第一个字符不是#,也会进入else

出0入0汤圆

 楼主| 发表于 2015-8-1 11:26:22 | 显示全部楼层
miaoguoqiang 发表于 2015-8-1 10:12
有问题,如果第一个字符不是#,也会进入else

没关系,首先只要能接收正常就行了,可是程序不能正常接收

出0入0汤圆

 楼主| 发表于 2015-8-1 11:51:20 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 11:52 编辑
miaoguoqiang 发表于 2015-8-1 10:12
有问题,如果第一个字符不是#,也会进入else


这个中断程序能接收了,我通过另一个程序验证通过了。单片机接收指令后,发送到串口助手

验证程序:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int

/***************************************************/
uchar a[5];
bit outflag=0;
uint len=0;       
uint i=0;

/***************************************************/
void init(void)
{
        TMOD=0x20;
        TH1=0xfd;
        TL1=0xfd;
        TR1=1;
        SCON=0x50;
        EA=1;
        ES=1;
}
/***************************************************/
void main(void)
{
        init();
        while(1)
        {
                if(outflag==1)
                {
                        ES = 0;
                        for(i = 0;i < 5;i++)
                        {
                                SBUF = a;
                                while(!TI);
                                TI = 0;
                        }
                        ES=1;
                        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)
                                {
                                        len=0;
                                        outflag=1;
                                }       
                        }
                }
                                       
        }
}

出0入0汤圆

 楼主| 发表于 2015-8-1 11:55:30 | 显示全部楼层
miaoguoqiang 发表于 2015-8-1 10:12
有问题,如果第一个字符不是#,也会进入else

可是,修改了的原来的程序仍然只能接收一次指令,再发指令就没反应了

#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];
uchar cnt;
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)
                {
                        ES=0;
                        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;
                        }
                        ES=1;
                        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;
                                }       
                        }
                }                                       
        }
}

出0入0汤圆

发表于 2015-8-1 15:50:21 | 显示全部楼层
daiya 发表于 2015-8-1 11:55
可是,修改了的原来的程序仍然只能接收一次指令,再发指令就没反应了

#include

主程序没有必要关中断。
你试下我上面写的那段程序

出0入0汤圆

发表于 2015-8-1 16:07:02 | 显示全部楼层
//送上我的代码给你参考,我也是借鉴了别人的
/**
  * @brief  UART0_Interrupt (ISR)
  * @param  None
  * @retval None
  */
void UART0_Interrupt (void) interrupt 4
{
        unsigned char tmpch;//临时变量
        SFRPAGE = UART0_PAGE;
        if (RI0 == 1)
        {
                RI0 = 0;                           // Clear interrupt flag      
                tmpch=SBUF0;
                if(tmpch=='b')//数据帧头
                {
                        recstatu = 1;//数据接收标志
                        ccnt   = 0 ;//数据计数
                        packerflag = 0;//接收完成标志清除
                }
                if(tmpch=='d')                          
                    {
                              recstatu = 0;//数据接收标志清除
                              packerflag = 1;//数据接收完成标志置位                     
                    }
                if(recstatu ==1) //允许数据接收                     
                    {
                               rxbuf[ccnt++] = tmpch;
               }
        }
}

在循环中:

while(1)
{
        if(packerflag == 1)
        {
                packerflag = 0;
                //处理函数。对rxbuf数组的数据分析
                .................................
        }
}

出0入0汤圆

发表于 2015-8-1 16:08:14 | 显示全部楼层
//送上我的代码给你参考,我也是借鉴了别人的
/**
  * @brief  UART0_Interrupt (ISR)
  * @param  None
  * @retval None
  */
void UART0_Interrupt (void) interrupt 4
{
        unsigned char tmpch;//临时变量
        SFRPAGE = UART0_PAGE;
        if (RI0 == 1)
        {
                RI0 = 0;                           // Clear interrupt flag      
                tmpch=SBUF0;
                if(tmpch=='b')//数据帧头
                {
                        recstatu = 1;//数据接收标志
                        ccnt   = 0 ;//数据计数
                        packerflag = 0;//接收完成标志清除
                }
                if(tmpch=='d')                          
                    {
                              recstatu = 0;//数据接收标志清除
                              packerflag = 1;//数据接收完成标志置位                     
                    }
                if(recstatu ==1) //允许数据接收                     
                    {
                               rxbuf[ccnt++] = tmpch;
               }
        }
}

在循环中:

while(1)
{
        if(packerflag == 1)
        {
                packerflag = 0;
                //处理函数。对rxbuf数组的数据分析
                .................................
        }
}

出0入0汤圆

 楼主| 发表于 2015-8-1 16:15:11 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 21:14 编辑
miaoguoqiang 发表于 2015-8-1 15:50
主程序没有必要关中断。
你试下我上面写的那段程序


试了,数码管没反应,我们的数组定义不同, 我用的是a[0]-a[4],你定义的是a[1]-a[5]

附代码:
#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[6];
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
{
        uchar temp;
        static uint len=0;
        if(RI)
        {
                 RI=0;
                 temp=SBUF;
                 if(!outflag)
                 {
                         if((temp=='#')&&(len==0))
                         {
                                 a[len++]=temp;
                          }
                         else if(len)
                          {
                                 a[len++]=temp;
                                 if(len==5)
                                  {
                                        a[1]=a[1]-0x30;
                                        a[3]=a[3]-0x30;
                                        len=0;
                                        outflag=1;
                                   }        
                           }
                  }
        }
}

出0入0汤圆

发表于 2015-8-1 16:21:28 | 显示全部楼层
本帖最后由 miaoguoqiang 于 2015-8-1 16:24 编辑
daiya 发表于 2015-8-1 16:15
试了,数码管没反应,我们的数组定义不同, 我用的是a[0]-a[4],你定义的是a[1]-a[5]

附代码:


。。。。。。。。。。。。。
都是a[0]-a[4]好吧!!!!!!!还有把全局变量的len定义删掉
len++的意思是用了只后再加,而不是++len
是没有进中断还是怎么的?在调试代码中可以加入一些IO口的翻转或者指示灯什么的观察。

出0入0汤圆

 楼主| 发表于 2015-8-1 16:33:44 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 16:45 编辑
miaoguoqiang 发表于 2015-8-1 16:21
。。。。。。。。。。。。。
都是a[0]-a[4]好吧!!!!!!!还有把全局变量的len定义删掉
len++的意思 ...


我运行了你的代码,也是只能接收一次指令。你的代码和我的程序完全兼容

#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[6];
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
{
        uchar temp;
        static uint len=0;
        if(RI)
        {
                RI=0;
                temp=SBUF;
                if(!outflag)
                {
                        if((temp=='#')&&(len==0))
                        {
                                a[len++]=temp;
                            }
                            else if(len)
                            {
                                a[len++]=temp;
                                      if(len==5)
                                      {
                                                a[1]=a[1]-0x30;
                                                a[3]=a[3]-0x30;
                                                len=0;
                                                outflag=1;
                                      }        
                            }
                  }
        }
}

出0入0汤圆

发表于 2015-8-1 16:45:19 | 显示全部楼层
daiya 发表于 2015-8-1 16:33
我运行了你的代码,也是只能接收一次指令。你的代码和我的程序完全兼容 ...

观察程序运行到什么地方了。
串口中断加一句TI的清除标志

出0入0汤圆

 楼主| 发表于 2015-8-1 16:50:08 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 21:16 编辑
miaoguoqiang 发表于 2015-8-1 16:45
观察程序运行到什么地方了。
串口中断加一句TI的清除标志


我把中间一段代码换掉就可以循环响应指令了,修改内容if(outflag==1){...}。数码管随输入指令改变,单片机把接收的指令发送回串口调试助手

#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};
/***************************************************/
uchar a[5];
bit outflag=0;
uint len=0;       
uint i=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)
                {
                        ES = 0;
                        for(i = 0;i < 5;i++)
                        {
                                SBUF = a;
                                while(!TI);
                                TI = 0;
                        }
                        ES=1;
                        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;
                                }       
                        }
                }
                                       
        }
}

出0入0汤圆

 楼主| 发表于 2015-8-1 16:55:08 | 显示全部楼层
miaoguoqiang 发表于 2015-8-1 16:45
观察程序运行到什么地方了。
串口中断加一句TI的清除标志

问题可能出现在if(outflag==1){...}部分

出0入0汤圆

 楼主| 发表于 2015-8-1 17:00:05 | 显示全部楼层
miaoguoqiang 发表于 2015-8-1 16:45
观察程序运行到什么地方了。
串口中断加一句TI的清除标志

初始化SCON时已清零TI

出0入0汤圆

发表于 2015-8-1 18:10:24 | 显示全部楼层
daiya 发表于 2015-8-1 17:00
初始化SCON时已清零TI

一定要在串口中断里面加。

出0入0汤圆

 楼主| 发表于 2015-8-1 21:00:07 | 显示全部楼层
本帖最后由 daiya 于 2015-8-1 21:07 编辑
miaoguoqiang 发表于 2015-8-1 18:10
一定要在串口中断里面加。


在中断里加TI=0了,还是只能接收第一条指令,再发送指令就无效了

#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[6];
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
{
        uchar temp;
        static uint len=0;
        TI=0;
        if(RI)
        {
                RI=0;
                temp=SBUF;
                if(!outflag)
                {
                        if((temp=='#')&&(len==0))
                        {
                                a[len++]=temp;
                            }
                            else if(len)
                            {
                                a[len++]=temp;
                                      if(len==5)
                                      {
                                                a[1]=a[1]-0x30;
                                                a[3]=a[3]-0x30;
                                                len=0;
                                                outflag=1;
                                      }        
                            }
                  }
        }
}

出0入0汤圆

 楼主| 发表于 2015-8-1 21:23:31 | 显示全部楼层
控制指令的定义见附件

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-1 22:02:31 | 显示全部楼层
还有主程序里面显示数码管这段程序也得改改。你自己琢磨调试方法,这样才能更上一层楼。
不是一句简单的接收到一次就不行了,再发指令也得发不一样的指令啊。要用严谨的思维去推导原因,调试方法才是解决问题的关键。

别按书上写的什么控制指令的定义,自己写一段简单的帧头帧尾做协议就可以了。

出0入0汤圆

发表于 2015-8-2 03:22:28 | 显示全部楼层
慢慢跟踪下,不难的。

出0入0汤圆

 楼主| 发表于 2015-8-2 07:15:20 | 显示全部楼层
本帖最后由 daiya 于 2015-8-2 07:17 编辑

哦,我再调一调看看

出0入0汤圆

发表于 2015-8-2 19:47:15 | 显示全部楼层
你可以试着去掉串口中断里     if(!outflag)    直接接收省的错过什么

出0入0汤圆

发表于 2015-8-2 19:51:11 | 显示全部楼层
还有就是 你最好不要用static 直接放在外面当全局就好了 反正51内存都是开多少用多少的 不会释放

出0入0汤圆

 楼主| 发表于 2015-8-3 06:15:14 | 显示全部楼层
jlhgold 发表于 2015-8-2 19:47
你可以试着去掉串口中断里     if(!outflag)    直接接收省的错过什么

我已经简化成如下程序了,可仍然只响应一次指令,再发指令就没反应了

#include<reg52.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};
/***************************************************/
uchar a[5];
uint len=0;       
uint i=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);
        }
}
/***************************************************/
void serial_serve(void) interrupt 4
{
        if(RI)
        {
                RI=0;
                        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;
                                }       
                        }
                                       
        }
}

出0入0汤圆

 楼主| 发表于 2015-8-4 06:14:55 | 显示全部楼层
问题解决了,原来的串口助手不好,换了一个,就能不断接收指令了

出0入0汤圆

发表于 2015-8-8 14:26:10 | 显示全部楼层
你的中断处理程序太繁琐,不用在中断处理程序中建立这么多的循环及判断,这样在你的串口接受数据时,又有数据发送过来时,你原来的中断处理程序可能没结束,便又触发了串口中断,在串口中断中你只需要做的就是:1、将串口数据送入缓冲区;2、移动一位缓冲区当前指针;3、中断返回;4、在主程序处理缓冲区的内容。

出10入113汤圆

发表于 2015-8-8 14:31:47 | 显示全部楼层
顶38楼兄弟,中断服务程序里别太啰嗦,这一定是个好习惯。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 00:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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