⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 77e516.txt

📁 77e516,双串行口通讯
💻 TXT
字号:
 C51编程:请教:W77E516芯片,为何我的串口只能一次接收1个字节? 
串口0使用定时器1做波特率发生器,串口采用中断方式接收,但是用串口调试助手只能一
次发一个字节,如果发两个以上就会有问题,下面是我的程序:
void InitSeriesPort(void)
 {
        ES = 0;//使串口0不能中断
        IP |= 0x10;//将串口0设为高优先级
        T2CON = 0x00;//串行口0使用定时器1做波特率发生器    
        TL1 = 0xFD; //11.0592MHz :9600
        TH1 = 0xFD;//TH1 = 0xdc;//TH1 = 0xFF;            
 }
void SeriesPort (void) interrupt 4 using 2
{    
    if(RI)
    {
          ReceiveData[g_zi]=SBUF;
          En4850=1; TI=0;SBUF=ReceiveData[g_zi]; while(TI==0);TI=0;En4850=0; 
          }
         RI=0;
}
void main() 
{ TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */ 
SCON=0x40;//串行口工作于10位异步模式1
PCON=0;
InitSeriesPort();
//SM2=0;
ET1=0;//定时器1中断
ES = 1;//EA = 1;
TR1=1;//启动定时器1
SendData();
RI=0;REN=1;
PT0=1;
EA=1;
}

各位大侠,帮我分析分析吧!



大家帮帮忙吧!谢谢了。 [kenn654321] 2006-7-21 17:08:17



你的本来就一次只能接受发送一个阿 [lk@422] 2006-7-21 17:10:40



请问:但是我如果用串口调试助手一次发一串数据,它只能接收到第一个,后面就乱了。 [kenn654321] 2006-7-21 17:18:58



楼主,能不能帮我看看我的程序为什么会不能接收一串数据?实在不知道该怎么办了! [kenn654321] 2006-7-21 17:29:18



你的程序发了一次数据,但没有发中断处理 [yunwei] 2006-7-21 19:00:30
主程序没有等待,不知道运行到哪去了


我有串口中断处理啊,你说的是定时器1的中断处理吗?这个不要也可以啊。能讲的再清楚点吗? [kenn654321] 2006-7-22 11:48:39



好像这里错了! [space005] 2006-7-22 12:31:23
“while(TI==0);TI=0;En4850=0;”应该该成“while(TI==1);TI=0;En4850=0;”


这里没错,我总感觉时序上有问题。 [kenn654321] 2006-7-22 13:54:31



大概跑飞了 [ssaassa] 2006-7-22 16:18:29
主程序么sjmp $,串口中断reti后会跑飞俄大概~~~
开了timer1,要写中断处理,不然可能也会跑飞~~~


我已经把定时器1的中断给关了,可是还是只能用串口调试助手1个字节1个字节发送 [kenn654321] 2006-7-22 17:21:54



这里没有问题 [liuhuiwang] 2006-7-22 17:43:24



if(RI)改while(RI), RI=0放在while的第一行再送资料, 不过在中断内等发送完在离开不太好啊! [C.C.] 2006-7-22 17:57:13



你看看你的程序的问题 [liuhuiwang] 2006-7-22 18:03:05
void SeriesPort (void) interrupt 4 using 2{        if(RI)
    {          ReceiveData[g_zi]=SBUF;          En4850=1; 
TI=0;SBUF=ReceiveData[g_zi]; while(TI==0);TI=0;En4850=0;           }         
RI=0;}
非常明显的错误
应该为:
void SeriesPort (void) interrupt 4 using 2
{        
if(RI)    
{          ReceiveData[g_zi]=SBUF; 
RI = 0;
En4850=1;
 TI=0;
SBUF=ReceiveData[g_zi]; 
while(TI==0);
TI=0;
En4850=0;           
}         


这里我改了,但是好象还是不能用串口调试助手一次发一串数据,我看了一下,好象单片机串口接收的数据不能正常存到receivedata数组中。 [kenn654321] 2006-7-22 18:19:36



g_zi没加1 [C.C.] 2006-7-22 18:33:07



把1 加上也不行,我郁闷坏了 [kenn654321] 2006-7-22 18:36:22



你把最後测试的程序贴上来, 最好是完整的 [C.C.] 2006-7-22 18:44:46



请看里面 [kenn654321] 2006-7-22 18:57:35
void SeriesPort (void) interrupt 4 using 0
{    ES=0;
    if(RI)
    {
           ReceiveData[g_zi]=SBUF;
          {En4850=1; TI=0;SBUF=ReceiveData[g_zi]; whil(TI==0);TI=0;En4850=0; } 
           g_zi++; 
          if(g_zi>=30)g_zi=0;
          RI=0; 
          } 
 }
    else TI=0;  
     ES=1;
}

这个程序主要是想单片机串口接收到什么数据,让它把接收到的数据发出来,但是我用软
件调试时发现receivedata的数组里总是0,接硬件后用串口调试助手1个字节一个字节个单
片机的串口发数据,单片机可以准确无误的给我返回我刚发的数据,可是发2个以上的字节
就出现乱码,{En4850=1; TI=0;SBUF=ReceiveData[g_zi]; while
(TI==0);TI=0;En4850=0; } 我以前这样在中断中用过,所以这里应该没错。数组我是这样
定义的:
static unsigned char  g_zi,ReceiveData[40];


我的所有程序在下面:
#include <reg52.h> 

sbit BT_SND =P1^5; 
sbit BT_REC =P1^4; 

sbit En4851 = P1^1;        //UART1 enabel H---SEND,L---RECEIVE
sbit En4850 =  P3^2;     //UART0 enabel

#define F_TM F0
#define TIMER0_ENABLE TL0=TH0; TR0=1; 
#define TIMER0_DISABLE TR0=0;

#define OSCU 1 //1 11.0592  0 22.1184 

static unsigned char idata g_zi,ReceiveData[40];
bit ReceiveFinish;


sbit ACC0= ACC^0; 
sbit ACC1= ACC^1; 
sbit ACC2= ACC^2; 
sbit ACC3= ACC^3; 
sbit ACC4= ACC^4; 
sbit ACC5= ACC^5; 
sbit ACC6= ACC^6; 
sbit ACC7= ACC^7;



void IntTimer0() interrupt 1 
{ 
F_TM=1; 
} 
//发送一个字符 
void PSendChar(unsigned char inch) 
{ 

ACC=inch;

F_TM=0; 
BT_SND=0; //start bit 
TIMER0_ENABLE; //启动 
while(!F_TM);
 
BT_SND=ACC0; //先送出低位 
F_TM=0; 
while(!F_TM);



BT_SND=ACC1; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC2; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC3; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC4; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC5; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC6; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC7; 
F_TM=0; 
while(!F_TM);



BT_SND=1; 
F_TM=0; 
while(!F_TM);


TIMER0_DISABLE; //停止timer 

} 

//接收一个字符 
unsigned char PGetChar() 
{ 
TL0=TH0;
TIMER0_ENABLE; 

F_TM=0; 
while(!F_TM); //等过起始位
ACC0=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC1=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC2=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC3=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC4=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC5=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC6=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC7=BT_REC;

F_TM=0;

while(!F_TM) 
{ 
if(BT_REC) 
{ 
break; 
} 
} 
TIMER0_DISABLE; //停止timer 
return ACC; 


} 
//检查是不是有起始位 
bit StartBitOn() 
{ 
return (BT_REC==0);

} 
/*上面为模拟串口程序*/

/*下面为串口与主机的无线通讯程序*/
void SeriesPort (void) interrupt 4 using 0
{    ES=0;
    if(RI)
    {
          ReceiveData[g_zi]=SBUF;
          {En4850=1; TI=0;SBUF=ReceiveData[g_zi]; whil(TI==0);TI=0;En4850=0; } 
          g_zi++; 
          if(g_zi==1) {if(ReceiveData[0]!=0xFE) g_zi=0;    }
          if(g_zi==2) { if(ReceiveData[1]!=0xF8) g_zi=0;}
          if(g_zi==3) { if(ReceiveData[2]>36) g_zi=0;}
          if(g_zi==(ReceiveData[2]+2)) {ReceiveFinish=1;g_zi=0; } 
          RI=0;                    
                                
    }
    else TI=0;  
     ES=1;
}

/*
void Timer1 (void) interrupt 3 using 1
//void Timer1 (void) interrupt 3 using 2
{    
      #if OSCU    
      {  TH1 = 0xff;   //time=50ms, Fosc=11.0592MHz
         TL1 = 0xdc;

      }
      #else
      {    
         TH1 = 0x4B;  //time=25ms, Fosc=22.1184MHz
         TL1 = 0xFF;
      }    
      #endif
 
}
*/
void InitSeriesPort(void)
 {
        ES = 0;//使串口0不能中断
        PS = 0;//将串口0设为低优先级
        RCLK=0;TCLK=0;//串行口0使用定时器1做波特率发生器

        #if OSCU 
        {   TL1 = 0xFD; //11.0592MHz :9600
            TH1 = 0xFD;//TH1 = 0xdc;//TH1 = 0xFF;
        }
        #else
        {        
            TL1 = 0xFA;    //22.1184MHz  :9600
            TH1 = 0xFA;//TH1 = 0xFF;        
        }
        #endif
 }

void SendData(void) 
{
    unsigned char idata i;
    unsigned char  zd[2];
    ES = 0;
    En4850=1; //允许发送
    TI=0;
    for(i=0;i<2;i++)
    {
        zd[i]=0x50+i;
        SBUF=zd[i];
        while(TI==0);
        TI=0;
    }
  ES = 1;  En4850=0;//允许接收 
}





void main() 
{ 
unsigned char gch,i;

ReceiveFinish=0;
TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */ 
SCON=0x40;//串行口0工作于10位异步模式1
PCON=0;
InitSeriesPort();
ET1= 0;//关定时器1中断
TR1=1;//启动定时器1
SendData();
RI=0;REN=1;


PT0=1; 
TR0=0; //在发送或接收才开始使用 
TF0=0; 
TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的 timer是
104.167*11.0592/12= 96  

TL0=TH0; 
ET0=1; 
EA=1;

PSendChar(0x55);
PSendChar(0x66);
PSendChar(0x77);
PSendChar(0x88);
g_zi=0;
while(1) 
    {
if(ReceiveFinish)
{ReceiveFinish=0;
for(i=0;i<=(ReceiveData[2]+2);i++)
{En4850=1; TI=0;SBUF=ReceiveData[g_zi]; while(TI==0); TI=0;En4850=0; } 
}

if(StartBitOn()) 
           { 
           gch=PGetChar(); 
           PSendChar(gch);
           } 
      }
}



忘了问你该不会是485吧? 如果是那当然不行, 因为485为half duplex [C.C.] 2006-7-22 19:05:30



我用的是半双工的485,请问:那我怎么用串口调试助手一次发一串数据呢? [kenn654321] 2006-7-22 19:11:14



半双工不可以收发同时, 你必须改成全部收完再发送, 只是收多少算收完就必须有协议才行 [C.C.] 2006-7-22 19:17:57



这个我有协议,在程序里也可以看到,当receivefished=1时结束。 [kenn654321] 2006-7-22 19:33:48



请教:如果我程序里的方法不行,怎样才能把它改成全部收完呢? [kenn654321] 2006-7-22 19:37:55



不要在串口中断发送资料, 将主程序改一下(你怎麽两个地方都有发送啊?) [C.C.] 2006-7-22 19:57:27
if(ReceiveFinish)
{ReceiveFinish=0;
for(i=0;i<=(ReceiveData[2]+2);i++)
{En4850=1; TI=0;SBUF=ReceiveData[i]; while(TI==0); TI=0;En4850=0; } 
}



好的,我现在就试试。 [kenn654321] 2006-7-22 20:00:47



把串口中断的 else TI=0; 和 ES=0, ES=1 拿掉 [C.C.] 2006-7-22 20:07:07



请C.C.看里面 [kenn654321] 2006-7-22 20:13:03
我把中断中的发送数据删除掉只在后面发,但是软件调试时receivedata的数组里一直都是
0,好象存不进去,请问你以前遇到过这种情况吗?你可以把我的程序用软件调试一下。
#include <reg52.h> 

sbit BT_SND =P1^5; 
sbit BT_REC =P1^4; 

sbit En4851 = P1^1;        //UART1 enabel H---SEND,L---RECEIVE
sbit En4850 =  P3^2;     //UART0 enabel

#define F_TM F0
#define TIMER0_ENABLE TL0=TH0; TR0=1; 
#define TIMER0_DISABLE TR0=0;

#define OSCU 1 //1 11.0592  0 22.1184 

static unsigned char idata g_zi,ReceiveData[40];
bit ReceiveFinish;


sbit ACC0= ACC^0; 
sbit ACC1= ACC^1; 
sbit ACC2= ACC^2; 
sbit ACC3= ACC^3; 
sbit ACC4= ACC^4; 
sbit ACC5= ACC^5; 
sbit ACC6= ACC^6; 
sbit ACC7= ACC^7;



void IntTimer0() interrupt 1 
{ 
F_TM=1; 
} 
//发送一个字符 
void PSendChar(unsigned char inch) 
{ 

ACC=inch;

F_TM=0; 
BT_SND=0; //start bit 
TIMER0_ENABLE; //启动 
while(!F_TM);
 
BT_SND=ACC0; //先送出低位 
F_TM=0; 
while(!F_TM);



BT_SND=ACC1; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC2; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC3; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC4; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC5; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC6; 
F_TM=0; 
while(!F_TM);



BT_SND=ACC7; 
F_TM=0; 
while(!F_TM);



BT_SND=1; 
F_TM=0; 
while(!F_TM);


TIMER0_DISABLE; //停止timer 

} 

//接收一个字符 
unsigned char PGetChar() 
{ 
TL0=TH0;
TIMER0_ENABLE; 

F_TM=0; 
while(!F_TM); //等过起始位
ACC0=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC1=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC2=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC3=BT_REC;

F_TM=0; 
while(!F_TM); 
ACC4=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC5=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC6=BT_REC;



F_TM=0; 
while(!F_TM); 
ACC7=BT_REC;

F_TM=0;

while(!F_TM) 
{ 
if(BT_REC) 
{ 
break; 
} 
} 
TIMER0_DISABLE; //停止timer 
return ACC; 


} 
//检查是不是有起始位 
bit StartBitOn() 
{ 
return (BT_REC==0);

} 
/*上面为模拟串口程序*/

/*下面为串口与主机的无线通讯程序*/
void SeriesPort (void) interrupt 4 using 0
{    ES=0;
    if(RI)
    {    
          ReceiveData[g_zi]=SBUF;
          //{En4850=1; TI=0;SBUF=ReceiveData[g_zi]; while(TI==0); 
TI=0;En4850=0; } 
          g_zi++; 
          if(g_zi==1) { if(ReceiveData[0]!=0xFE) g_zi=0;    }
          if(g_zi==2) { if(ReceiveData[1]!=0xF8) g_zi=0;}
          if(g_zi==3) { if(ReceiveData[2]>36) g_zi=0;}
          if(g_zi==(ReceiveData[2]+2)) { ReceiveFinish=1; 
g_zi=0; } 
           RI=0;                    
                                
    }
    else TI=0;  
    ES=1;
}
void InitSeriesPort(void)
 {
        ES = 0;//使串口0不能中断
        PS = 0;//将串口0设为低优先级
        RCLK=0;TCLK=0;//串行口0使用定时器1做波特率发生器

        #if OSCU 
        {   TL1 = 0xFD; //11.0592MHz :9600
            TH1 = 0xFD;//TH1 = 0xdc;//TH1 = 0xFF;
        }
        #else
        {        
            TL1 = 0xFA;    //22.1184MHz  :9600
            TH1 = 0xFA;//TH1 = 0xFF;        
        }
        #endif
 }

void SendData(void) 
{
    unsigned char idata i;
    unsigned char  zd[2];
    ES = 0;
    En4850=1; //允许发送
    TI=0;
    for(i=0;i<2;i++)
    {
        zd[i]=0x50+i;
        SBUF=zd[i];
        while(TI==0);
        TI=0;
    }
  ES = 1;  En4850=0;//允许接收 
}





void main() 
{ 
unsigned char gch,i;

ReceiveFinish=0;
TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */ 
SCON=0x40;//串行口0工作于10位异步模式1
PCON=0;
InitSeriesPort();
ET1= 0;//关定时器1中断
TR1=1;//启动定时器1
SendData();
RI=0;REN=1;


PT0=1; 
TR0=0; //在发送或接收才开始使用 
TF0=0; 
TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的 timer是
104.167*11.0592/12= 96  

TL0=TH0; 
ET0=1; 
EA=1;

PSendChar(0x55);
PSendChar(0x66);
PSendChar(0x77);
PSendChar(0x88);
g_zi=0;ReceiveData[0]=1;ReceiveData[2]=0x55;
while(1) 
    {
if(ReceiveFinish)
{ReceiveFinish=0;
for(i=0;i<=(ReceiveData[2]+2);i++)
{En4850=1; TI=0;SBUF=ReceiveData[g_zi]; while(TI==0); TI=0;En4850=0; } 
}

if(StartBitOn()) 
           { 
           gch=PGetChar(); 
           PSendChar(gch);
           } 
      }
}


我测试可以啊! 我送 FE F8 01 会回送资料(必须先把else ti=0 才可以) [C.C.] 2006-7-22 20:23:13



主程序不是要改成 SBUF=ReceiveData[i]; [C.C.] 2006-7-22 20:26:01



对,主程序里把g_zi改为i后,再把中断里发送的数据去掉后就好了,我发现中断里发送数据会干扰接收到的数据,非常感谢你能给我这么多指点!谢谢! [kenn654321] 2006-7-22 20:37:30




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -