首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 单片机 >

请各位帮小弟我修改下串口程序的异常

2012-02-23 
请各位帮我修改下串口程序的错误C/C++ code#include reg52.h#define uchar unsigned char#define uint u

请各位帮我修改下串口程序的错误

C/C++ code
#include <reg52.h>#define uchar unsigned char#define uint unsigned intunsigned char flag,a,i;uchar b[4];uchar code table[]="I get ";void init(){    TMOD=0x20;     //确定T1的工作方式    TH1=0xfd;        //计算T1的初值,装载TH1,TL1    TL1=0xfd;    TR1=1;            //启动T1    REN=1;            //确定串行口的工作方式    SM0=0;    SM1=1;    EA=1;    ES=1;}void main(){    init();    while(1)    {        if(flag==1)        {            ES=0;            //关闭串口中断,否则发送数据时同样申请中断,程序进入死循环            for(i=0;i<6;i++)            {                SBUF=table[i];                while(!TI);                TI=0;            }            for(i=0;i<4;i++)            {                SBUF=b[i];                while(!TI);        //发送完毕后,TI会被硬件置1,跳出循环,说明数据发送完毕                TI=0;    //            }            ES=1;            flag=0;        }    }}void ser() interrupt 4{    uchar j;    for(j=0;j<4;j++)    {        while(!RI);        RI=0;                //接受数据完成后,内部硬件置1,进入串口中断函数后        b[j]=SBUF;        }                        //必须有软件清0    flag=1;                //将flag置1,方便在主程序中检测}


  现在用串口助手发送字符的时候,如果一次输入正好是4个字符,那么程序时没有错误的
但如果每次输入了2个字符,那么点击发送键后,串口助手是没有显示的,因为中断函数里的j还没有到4,
这样就需要发送2次,串口助手才会收到字符

但如果每次发送3个字符的话,第一次依然没有显示,但第二次发送后会保留多余的字符到b[j],这样以后再一次发送4个字符的话,串口助手以后收到的字符就会和发送的有点出入

求修改!
  如果输入少于4个字符,下次发送的时候,可以把b[]里保存的字符清空
  如果输入大于4个字符,下子发送的事业,也可以把b[]里多保存的字符清空

最好在中断函数里修改后发出来

[解决办法]
1.你给一个数据接受中断就进入了,然后进入了那个for循环,如果你输入的不满4个字符,由于 while(!RI);你的中断程序总是 处于等待状态,根本就没有从接收中断跳出来,所以不会返回的数据的,
2.而当你给的字符一旦满4个立刻回从接收中断跳出,并执行串口发送,所以你会看到发的字符多于4个的时候,能够显示前4个字符,至于多余的部分,由于你第五发送的数据引起中断前,你就在主函数里关闭了中断,进行串行发送,所以第五个数据及其以后的就进入等待状态,等到你给pc发送完毕之后重新打开串口中断,又把第五个及其以后的数据写入你那个字符数组b[]了。但是这时候再次进入接收中断,重新进行初始化,j在for循环被赋初值0,所以你发的4个以后的多余数据存储在b[0]b[1]。。。。。当中了,当然了你多余的数据如果不足4个又回到了第一种情况,只有等到4个才会从中断跳出来了。。多余四个就是第二种情况,多余的等到下次从头开始存入。。。。
[解决办法]
楼主可以加一个接收超时,如果超过一定时间还没接收到4个字符,就将接收清空;
如果超过四个接不保存,超时并且接收到大于等于4个时就将表明,接收完毕。
[解决办法]

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,a,i;
uchar b[4];
uchar code table[]="I get ";
void init()
{
TMOD=0x20; //确定T1的工作方式
TH1=0xfd; //计算T1的初值,装载TH1,TL1
TL1=0xfd;
TR1=1; //启动T1
REN=1; //确定串行口的工作方式
SM0=0;
SM1=1;
EA=1;
ES=1;
}

void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0; //关闭串口中断,否则发送数据时同样申请中断,程序进入死循环
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI);
TI=0;
}
for(i=0;i<4;i++)
{
SBUF=b[i];
while(!TI); //发送完毕后,TI会被硬件置1,跳出循环,说明数据发送完毕
TI=0; //
}
ES=1;
flag=0;
}
}
}

void ser() interrupt 4
{ long int i=0,p=0;
uchar a[100];
uchar j;
for(j=0;j<100;j++)
{
while(!RI){i++;if(i==10000) return;}
RI=0; //接受数据完成后,内部硬件置1,进入串口中断函数后
p++;
if (p<4)
b[j]=SBUF;
else 
a[j]=SBUF;
} //必须有软件清0
flag=1; //将flag置1,方便在主程序中检测
}
------解决方案--------------------


[Quote=引用:]
当接收到第一个字节的串口数据后启动一个定时器(定时间隔由串口波特率和收发的数据量来确定),定时器到时后检查是否收到所需的字节数。如果没有,则清除接收缓冲区、关闭定时器,等待下一次接收。

另:为什么非要在单片机处理接收超时的问题?不能在PC上做吗?
在单片机一帧数据接收完整后,可以给PC发送一个接收成功的标志。PC端接收到后就可以发送下一帧数据,如果PC端在超时时间内没有接收到单片机的接收成功标志,则给单片机发送一个重发标志,然后重新发送上一帧数据。

因为PC上的资源较多,使用定时器判断超时也方便。换个思路,一样可以解决问题。
[解决办法]
对于8楼的说法,我感觉靠谱。呵呵,pc那边不是不能做,而是一般来说pc那边我们是用的网上某个地方下载的串口调试工具,而那个上位机软件根本就没有“握手”程序,所以。要想让pc那边检验标志那除非你自己去编一个适用于自己的上位机发送接收程序,但一般来说我们是不专注于上位机的,,而且那样检验是否超时的工作和在单片机上做是一样的。。。pc资源固然丰富,不过那不是做单片机的人所擅长的吧。。。。

热点排行