论坛风格切换切换到宽版
  • 5728阅读
  • 4回复

请教两个单片机之间串口通讯的问题 [复制链接]

上一主题 下一主题
离线BD0AAI
 
发帖
3050
只看楼主 倒序阅读 0楼 发表于: 2006-09-14
请大家帮忙看看两个单片机之间串口通讯的问题

尽管程序可以正常运行,但总感觉串口通讯不是很可靠, 发偶数好一些, 奇数经常会收错, 不知何故, 请高手指教.

两个机器用的都是89s52, rx和tx 交叉对接.


a机的串口中断函数:

#define num 6
unsigned char point;
unsigned char buffer[12]={"0123456789ab"};
bit com_r=0;

com_interrupt(void) interrupt 4   using 3
{
// 串口中断
unsigned char receivr_buffer;
unsigned char t;

if(ri)                             // 接收
  {
  ri=0;
  receivr_buffer=sbuf;
  if (point==0)
    if( receivr_buffer == 0xbb )   // 起始标志
        buffer[point++]=receivr_buffer;
    else point=0;
  else if(point>0 && point<num) buffer[point++]=receivr_buffer;
  if ( (point>=num) && (buffer[1]==buffer[2]) )
           {point=0;com_r=1; com_work();}   // 接收成功,设置收到标志
  }

if(ti)                             // 发送
  {
  // 由 com_sent 函数发第一个字符,引发中断, 在此仅发后面的字符
  for (t=1;t<num;t++)
    {
    acc=buffer[t];
    sbuf=acc;
    ti=0; while(ti==0); _nop_();
    ti=1;
    }
  ti=0;
  }

}

void com_init(void)
{
// 串口初始化
scon=0x50;     // 选择串口工作方式 1   允许接收
pcon=0;                  // smod=0 速度不加倍
tmod=0x20;     // 定时器1 工作在方式2, 定时器0 工作在方式   0  
tl1=0xfd;
th1=0xfd;     // 传输速率 9600 smod=0
tr1=1;       // 启动定时器 1
et1=0;       // 禁止定时器 1 中断
es=1;       // 允许串口中断
ps=1;       // 提高串口中断优先级  
ea=1;      
}


void com_send(void)
{
//char t;
// 把缓冲区 第1字节 发送出去
buffer[0]=0xaa;
buffer[4]=0;
buffer[5]=0;
dispcom(0);                  // 显示串口命令
acc=buffer[0];
sbuf=acc;
delayms(20);
}



b机的部分程序:
// 串口相关变量
bit                  com_r=0;
unsigned char            buffer[10];
unsigned char            point;


com_interrupt(void) interrupt 4   using 3
{
// 串口中断

unsigned char receivr_buffer;
unsigned char t;
if(ri)                             // 接收
  {
  ri=0;
  receivr_buffer=sbuf;
  if (point==0)
    if( receivr_buffer == 0xaa )   // 起始标志
        buffer[point++]=receivr_buffer;
    else point=0;
  else if(point>0 && point<num) buffer[point++]=receivr_buffer;
  if (point>=num && (buffer[1]==buffer[2]) )
           {
           point=0;
           if (buffer[3]==0xa0 && buffer[1]==0x00 )
                 {jdq_1=1; jdq_2=1; jdq_3=1; jdq_4=1; jdq_7=1; jdq_8=1; }                                          
           else
                 {com1=buffer[3]; com2=buffer[1];com_r=1; }      // 接收成功,设置收到标志
           if (buffer[3]==0xa0 && buffer[1]==0x02 )
                 start=0;
           }                                
}      

if(ti)                             // 发送
  {
  // 由 com_sent 函数发第一个字符,引发中断, 在此仅发后面的字符
  for (t=1;t<num;t++)
    {
    acc=buffer[t];
    sbuf=acc;
    ti=0;
           while(ti==0); _nop_();
    ti=1;
    }
  ti=0;
  }
}

void com_init(void)
{
// 串口初始化

// 串口初始化
scon=0x50;     // 选择串口工作方式 1    
pcon=0;                  // smod=0 速度不加倍
tmod=0x20;            // 定时器1 工作在方式2, 定时器0 工作在方式 0
tl1=0xfd;
th1=0xfd;     // 传输速率 9600 smod=0
tr1=1;       // 启动定时器 1
et1=0;       // 允许定时器 1 中断
es=1;       // 允许串口中断
ps=1;       // 提高串口中断优先级  
ea=1;    
ren=1;            // 允许接收
}
离线BG8WJ
发帖
166
只看该作者 1楼 发表于: 2006-09-14
if (point==0)
if( receivr_buffer == 0xbb ) // 起始标志
buffer[point++]=receivr_buffer;
else point=0;
else if(point>0 && point<num) buffer[point++]=receivr_buffer;
这个语句是否正确?
if (point==0)
{
xxxxxxxx
}
else
不等于
if()
xxxxx
xxxx
else
没有{}的存在却是在某些编译程序中会被错误的编译。
另外在中断中不必使用—nop()—操作,应为对于while (ti)已经能够正确的理解 必须是
等sbuf发送空后才会执行下一次发送操作的。
for (t=1;t<num;t++)
{
acc=buffer[t];
sbuf=acc;
ti=0; while(ti==0); _nop_();有问题
ti=1;
}
ti=0;
本人个人建议在uart发送中如果你是使用中断方式的话,不要在中断中调用延时等函数,这血函数的调用可能会引起发送的时序超出预想的范围。
在硬件电路上tx 和rx连接需要注意干扰问题毕竟这个ttl uart方式对于干扰电压没有rs232的分辨率高。
离线bg4kc
发帖
2015
只看该作者 2楼 发表于: 2006-09-14
读了开头那段程序,接收好像只能收到很多0xbb
离线BD0AAI
发帖
3050
只看该作者 3楼 发表于: 2006-09-16
感谢两位的帮助.
加上{}也许会跟可靠一些. 我会去掉nop试试。
bg4kc: 程序中的原意是只接收 0xbb开始的数据,只是个标志,后面的内容接收没有问题。
离线lan_boy001
只看该作者 4楼 发表于: 2006-09-18
其实很简单啊
1 速度不要太快
2 程序很简单的,根本没有那么长一串
3 晶体振荡器的选择
4 能够有校验最好