搜索
bottom↓
回复: 11

串口处理问题:不用等待接收多个字节

[复制链接]

出0入0汤圆

发表于 2012-4-19 22:19:18 | 显示全部楼层 |阅读模式
本帖最后由 GZLJZ 于 2012-4-20 00:30 编辑

大家好,我之前把波特率设为115200,这样接收发送多个字节都直接在中断里了,
看到大家做485通信都经常波特率设为9600,接收一个字节就要约1MS,做485程序发送接收切换都要加入延时,这样如果发送接收20字节就要20MS多了,
这样单这个串口中断就占80MS,如果主循环里需要80MS以内处理的事情就做不了,
大家是这样处理这个问题的呢?

编辑原因:特率设为9600,接收一个字节好像是约1MS,我写4MS了

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2012-4-19 22:31:59 | 显示全部楼层
看到有人说,串口中断接收一个存进缓存里,等全部数据接收完了,在在主程序循环里处理,
但做485通信都知道,从机需要及时回应主机的,希望大家多耐心解答下困扰我的问题,先谢了

出0入0汤圆

发表于 2012-4-19 22:42:47 | 显示全部楼层
怎么及时也好,你就在主流程那里把一些复杂的函数拆成小部分完成,这样可以及时的

出0入0汤圆

 楼主| 发表于 2012-4-19 23:00:29 | 显示全部楼层
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
做串口发送接收为了解决死等在那里,使用上面两行方法,我就不知具体主程序里怎么做:



出0入0汤圆

发表于 2012-4-19 23:12:39 | 显示全部楼层
做个缓冲区,用中断方式发送。

出0入0汤圆

 楼主| 发表于 2012-4-19 23:18:56 | 显示全部楼层
lollipop 发表于 2012-4-19 23:12
做个缓冲区,用中断方式发送。


这样就是不行呀,假设主机发个地址过来,从机要回应主机呀,
我知道有人就是把地址和数据一起发给从机了,从机全部接收完成后才去处理,是不是需要的数据,

出0入0汤圆

发表于 2012-4-19 23:21:48 | 显示全部楼层
GZLJZ 发表于 2012-4-19 23:18
这样就是不行呀,假设主机发个地址过来,从机要回应主机呀,
我知道有人就是把地址和数据一起发给从机了 ...

你可以在串口的中断服务程序里判断接收到的信息

出0入0汤圆

 楼主| 发表于 2012-4-19 23:25:25 | 显示全部楼层
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
下面程序是不是上面两行的意思,我就相这样做,可惜我看不懂C语言,有好心人转成汇编就好了
#include <REG52.H>

sbit LED = P1^0;
unsigned char UART_buff;
bit New_rec = 0, Send_ed = 1, Money = 0;
//----------------------------------------------
void main (void)
{
    SCON = 0x50;   //串口方式1, 8-n-1, 允许接收.
    TMOD = 0x20;   //T1方式2
    TH1 = 0xFD;    //9600bps@11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;                        
    ES  = 1;       //开中断.
    EA  = 1;

    while(Money == 0);    //等着交费,呵呵,等着接收$.

    while(1)  {
      if ((New_rec == 1) && (Send_ed == 1))  {  //如果收到新数据及发送完毕
        SBUF = UART_buff; //那就发送.
        New_rec = 0;
        Send_ed = 0;
    } }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
    if(RI == 1) {  //如果收到.
      RI = 0;      //清除标志.
      New_rec = 1;
      UART_buff = SBUF;  //接收.
      if(UART_buff == '1')  LED = 1;
      if(UART_buff == '0')  LED = 0;
      if(UART_buff == '$')  Money = 1;
    }
    else  {        //如果送毕.
      TI = 0;      //清除标志.
      Send_ed = 1;
    }
}

出0入0汤圆

发表于 2012-4-19 23:50:13 | 显示全部楼层
要汇编, 你直接编译一下不就得了.

不管 if ((New_rec == 1) && (Send_ed == 1))  中的 && 有没有用错, 这段代码都无法保证接收数据不丢失.

出0入0汤圆

 楼主| 发表于 2012-4-19 23:55:41 | 显示全部楼层
gycsy963 发表于 2012-4-19 23:50
要汇编, 你直接编译一下不就得了.

不管 if ((New_rec == 1) && (Send_ed == 1))  中的 && 有没有用错, 这 ...

对,上面程序好像不是正确的,
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
我就是要板数据处理放在主程序里,中断接收到一个字节就退出,这样就没有在浪费等待时间,
主程序里具体怎么编写呢。

出0入0汤圆

发表于 2012-4-20 00:29:28 | 显示全部楼层
本帖最后由 diannaoza 于 2012-4-20 00:33 编辑

发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
下面程序是不是上面两行的意思,我就相这样做,可惜我看不懂C语言,有好心人转成汇编就好了
#include <REG52.H>

sbit LED = P1^0;
      
unsigned char UART_buff;
    uart_buff  data 60h
bit New_rec = 0, Send_ed = 1, Money = 0;
        new_rec   bit 20h
        send_ed    bit 21h
        money       bit  22h

//----------------------------------------------
void main (void)
{
   clr new_rec
   setb send_ed
    clr money


    SCON = 0x50;   //串口方式1, 8-n-1, 允许接收.
        mov SCON,#0X50
       
    TMOD = 0x20;   //T1方式2
    MOV TMOD,#0X20
   
    TH1 = 0xFD;    //9600bps@11.0592MHz
    MOV TH1,#0FDH
   
    TL1 = 0xFD;
    MOV TL1,#0FDH
   
    TR1 = 1;                        
    SETB TR1
   
    ES  = 1;       //开中断.
    SETB ES
   
    EA  = 1;
        SETB EA
       

    while(Money == 0);    //等着交费,呵呵,等着接收$.
    jnb money,$


    while(1)  {
        while:

      if ((New_rec == 1) && (Send_ed == 1))  {  //如果收到新数据及发送完毕
         
         jnb new_rec while_ex
         jnb send_ed while_ex


         while_enter:
        mov sbuf,uart_buff
        SBUF = UART_buff; //那就发送.

        New_rec = 0;
                 clr new_rec
         
        Send_ed = 0;
                 clr send_ed
       
        while_ex:       
        ljmp while

    } }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
    if(RI == 1) {  //如果收到.
    jnb ri,ri_ex

      RI = 0;      //清除标志.
            clr ri
   
      New_rec = 1;
            setb new_rec
   
      UART_buff = SBUF;  //接收.
            mov uart_buf,sbuf
      
      if(UART_buff == '1')  LED = 1;
                cjne uart_buf,#01h,ri_fn1ex
                setb p1.0
                ljmp ri_et_ex

                ri_fn1ex:
      if(UART_buff == '0')  LED = 0;
                cjne uart_buf,#00h,ri_fn2ex
                clr p1.0
                ljmp ri_et_ex
               
                ri_fn2ex:               
      if(UART_buff == '$')  Money = 1;
                cjne uart_buf,#'$',ri_fn3ex
                setb money               
                ljmp ri_et_ex
                ri_fn3ex:
       
        ri_et_ex:
    ljmp ri_ti_ex
   
    }
    ri_ex:


       
    else  {        //如果送毕.
      TI = 0;      //清除标志.
                clr ti
      Send_ed = 1;
                setb send_ed
    }
        ri_ti_ex:


}

出0入0汤圆

 楼主| 发表于 2012-4-20 00:37:47 | 显示全部楼层
回复11楼,谢谢你花那么多时间修改代码,C语言我是看不懂了,我是想实现下面的意思,数据在主程序里编写的思路,中断接收一个字节立即退出。用个全局变量?表明接收到第几个,再做处理?
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-20 00:13

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

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