原创 中断方式下进行串口通讯的正确方法

2009-11-3 13:51 9317 9 13 分类: MCU/ 嵌入式

中断方式下进行串口通讯的正确方法


    一般普遍的把串口通讯分为查询方式和中断方式。查询方式比较容易理解,各种书籍上都介绍的比较清楚。但中断方式,没有几本书讲得好的,甚至有些例程根本无法实际应用。
    问题有:
1,半中断法。只使用接收中断,不使用发送中断,发送时还是依靠查询中断标志的办法;如下:
  ES = 0;//若是接收使用中断方式,某些单片机需要关中断。但C51不一定需要。这里只是示例。
  SBUF = needsendchar;
  While (!TI);
  TI = 0;
  ES = 1;
这里的问题是:发送数据时需要等待数据发完才能继续其他工作,程序效率降低;发送时需要关中断,影响数据接收。


2,接收中断的处理方法错误。如下:
  中断程序:
  void ser() interrupt 4 {
    RI = 0;
    temp = SBUF;     //读走数据,放入缓存(全局的)变量
    rx_flag = 1; //设置接收标志
  }
  主程序:
  void main(){
    …;//初始化
    While (1) {
      If (rx_flag ==1){//查询接收标志
        rx_flag = 0; //清楚接收标志
        x = temp; //从暂存变量读取数据
        …;//接收处理
      }
      …;  //其它操作
    }
  }
这里的问题是:如果串口接收数据的间隔时间小于“接收处理”和“其它操作”所用的时间时,接收数据会丢失一部分。


    正确使用中断方式处理串口收发应达到以下目的:
1,完全使用中断控制接收和发送,以达到最快的收发速度。
2,接收和发送互不影响,达到全双工通讯效果。
3,应用程序不发生等待,以达到最高运行效率。


正确的中断发送方法如下:
1,建立一个足够大小的环形发送缓冲区,建立一个信号量(用于指示发送的数据量),建立一个发送标志位(用于指示发送状态)。
2,应用程序将数据写入环形发送缓冲区,查询发送接收标志,若不在发送状态,手动触发中断。
3,产生发送中断时,查询信号量,以判别发送缓冲区内是否有数据;若有,置发送标志位,从缓冲区读取数据发送,累减信号量;若无,清除发送标志位。


C51的例程如下:
//变量定义
#define BUF_SIZE 0x10//环形收发缓冲区长度
//发送参数
char tx_circbuf[BUF_SIZE];//环形发送缓冲区
uint8 tx_sem;//信号量
bool tx_run;//发送标志位
uint8 tx_circin;//进环形缓冲区的位置指示
uint8 tx_circout;//出环形缓冲区的位置指示


//发送初始化程序
void tx_init(void){
  //硬件初始化 略
 
  //发送参数初始化
  tx_sem = 0;
  tx_run = False;
  tx_circin = 0;
  tx_circout = 0;
}


//中断程序
void tx_int(void) interrupt 4 {
  if (TI){
    TI = 0;
    if (tx_sem){
      SBUF = tx_circbuf [tx_circout]; // 发送缓冲区中的字符
      if (++tx_circout >= BUF_SIZE) tx_circout = 0;
      tx_sem--;//累减信号量
      tx_run = True;//置发送标志位
    }
    else tx_run = False;//清除发送标志位
  }
}


//发送处理程序,由应用程序调用
//输入:发送数据指针,发送数据长度
void tx_data(char * txbuf,uint8 len){
  while (len){
    tx_circbuf [tx_circin] = *txbuf++;// 存入数据到发送缓冲区
    if (++tx_circin >= BUF_SIZE) tx_circin = 0;
    tx_sem++;//累减信号量
    len--;
    if (tx_run == False)TI=1;//查询发送状态标志。若发送空闲,触发中断,发送数据的工作由中断程序自动完成。
  }
}



正确的中断接收方法如下:
1,建立一个足够大小的环形接收缓冲区,建立一个信号量(用于指示接收的数据量)。
2,发生接收中断时,读出字节放入接收缓冲区,并累加信号量。
3,应用程序查询接收标志,如信号量不为0,则从接收缓冲区读取数据进行处理,累减信号量。


C51的例程如下:
//变量定义
#define BUF_SIZE 0x10//环形收发缓冲区长度
//接收参数
char rx_circbuf[BUF_SIZE];// 环形接收缓冲区
uint8 rx_sem;// 信号量
uint8 rx_circin;//进环形缓冲区的位置指示
uint8 rx_circout;//出环形缓冲区的位置指示


//接收初始化程序
void rx_init(void){
  //硬件初始化 略


  //接收参数初始化
  rx_sem = 0;
  rx_circin = 0;
  rx_circout = 0;
}


//中断程序
void rx_int(void) interrupt 4 {
  if (RI){
    RI = 0;
    rx_circbuf [rx_circin] = SBUF;// 读出字节放入接收缓冲区
    if (++rx_circin >= BUF_SIZE) rx_circin = 0;
    rx_sem++;//累加信号量
  }
}


//接收处理程序,由应用程序调用
//输出:读出数据指针;返回:接收到的数据长度
uint8 rx_data(char * rxbuf){
  uint8 i;
  i = 0;
  while (rx_sem){
    *rxbuf++ = rx_circbuf [rx_circout];// 从接收缓冲区读取数据
    if (++rx_circout >= BUF_SIZE) rx_circout = 0;
    rx_sem--;//累减信号量
    i++;
  }
  return i;
}



上述的收发中断程序在应用中合并在一起,即:
void uart_init(void) interrupt 4 {
  if (TI){
    TI = 0;
    …;
  }
  if (RI){
    RI = 0;
    …;
  }
}
例程中分开表述,只是为了将流程说得更明白些。


上述例程中,未包含环形收发缓冲区溢出状况的处理,需要时自行添加。


上述例程表明了正确使用中断方式处理串口通讯的思路。当然程序还可以有其它的写法,特别是环形缓冲区中数据出入的方法和信号量的用法。如在有操作系统的情况下,上述信号量的使用就可以得到操作系统更好支持。


完全中断方式收发数据总结:
1。数据的收发操作,完全由中断程序自动进行,可以达到最快的收发速度。即,接收时中断程序负责把数据放入缓冲区,数据的处理由应用程序另行处理;发送时应用程序直接将数据放入缓冲区,启动发送中断后,发送的工作由中断程序自动完成。
2。由于发送的工作完全由中断处理,因此,应用程序将数据放入缓冲区后,就可以继续运行其它工作,这种“发了不管”的方式极大地提高程序运行效率。
3。接收数据时,由中断负责将数据放入缓冲区,再由应用程序处理。应用程序轮询及处理的时间长短,不会影响接收,就不会导致数据丢失。
4。由于应用程序中不出现开关中断的操作,因此,发送和接收互不影响,可以达到全双工收发的效果。


期望上述文字能给予大家借鉴,如有差错,望予指正,谢谢。


 

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户211384 2011-5-14 17:23

楼主不好意思,我错了

用户211384 2011-5-14 17:12

楼主,你那发送中断是不是进去一次之后就进不去了啊 tx_run = True,之后要怎么触发中断呢?

用户1566556 2011-2-16 16:50

我用的是MAX485是半双工的芯片,怎么能实现实时的收发?

用户944075 2009-11-2 14:16

写的不错 经验之谈 我们一般都用的是半中断方式 只接收中断,发送没有 呵呵
相关推荐阅读
用户1529524 2011-09-29 00:35
拆解山寨MP5播放器
  拆解山寨MP5播放器   最近新入手一款山寨的MP5播放器. 由于自己也做电子产品设计, 好奇心驱使, 机器到手没几天, 便被拆开查看.        此机前后盖为卡扣设PAN>显示屏安装...
用户1529524 2010-01-20 16:53
应用Δ-Σ ADC时需要注意有效精度
   刚刚阅读了Ti博客的关于Δ-Σ ADC的文章,对Δ-Σ ADC有了更多的了解。结合以前的使用经验,写点值得注意的东西。    Δ-Σ ADC实际应用中,只有实际有效精度才值得采信,使用时必须特别...
用户1529524 2010-01-19 11:04
为包装秤控制器设计而做的算法仿真
08年应邀设计一款包装秤控制器。为了使控制流程更加有效,特地做了2个算法仿真测试程序。其一,全自动组合包装秤算法仿真:    组合包装秤通常有数个计量秤斗。给每个计量秤斗添加物料后,称出各个料斗中物料...
用户1529524 2010-01-16 16:21
温度记录仪
前一段时间,有朋友要求定制几个温度记录仪。因为要得比较急,最后,一个月不到交付了东西。配置3对温度探头接口,连接传感器。一个DB9的RS232接口,用于和计算机通讯,上传温度记录。三个按钮,用于设置、...
用户1529524 2010-01-16 14:42
过手一款Ti原厂开发板-DK-LM3S9B96
最近过手一款Ti原厂的开发板,DK-LM3S9B96,09年新出的,售价425美元。很精致。贴出照片共赏。...
用户1529524 2009-12-05 13:55
实时操作系统应用杂谈(二)
    想要在自己设计的嵌入式系统中使用操作系统,先要配置或者移植操作系统。相关的文集比较多,在这里我就不说了,我还是想多聊些应用方面的东西。    关于任务的建立和运行。    任务的建立是指写一个...
EE直播间
更多
我要评论
4
9
关闭 站长推荐上一条 /3 下一条