高效FIFO串口双机通信在ARM7上的实现


高效FIFO串口双机通信在ARM7上的实现
S3C44B0X(时钟频率为60 MHz)的UART单元提供2个独立的异步串行I/O口,每个通信口均可工作于中断或DMA模式。即UART能产生内部中断请求或DMA请求,在CPU和串行I/O口之间传送数据。它支持高达115.2 Kb/s的传输速率,每1个UART通道包含了2个16位的分别用于接收和发送信号的先进先出(FIFO)通道。S3C44B0X UART包括可编程波特率、红外发送/接收、1个开始位、1个或2个停止位、5/6/7/8位数据宽度和奇偶校验。每个UART包含1个波特率发生器、接收器、发送器和控制单元,其构成如图1所示[1]。 
1  FIFO概述
1.1 FIFO概念
  先入先出FIFO(First In First Out),即先被写入到FIFO的数据将会先被读出。它是一片用来缓存数据的存储单元,可以把需要处理的数据先暂存在这片存储单元中,在数据量达到一定数量时再集中处理,以提高系统性能。FIFO可以集成在芯片中,而当系统需要的缓冲区较大时,也可以用单独的RAM实现。S3C44B0X串口收发器包含了16 B的FIFO和数据移位器,将要传输的数据写进FIFO,然后赋值到发送移位器,最后从发送的引脚移位发送出去,达到利用FIFO缓冲区高效通信的目的。
1.2  FIFO意义
    FIFO是数据传输系统中极其重要的一环,特别是在2个处于不同时钟域的系统接口部分,FIFO的合理使用,不但能使接口处数据传输的输入输出速率进行有效的匹配,不使数据发生复写、丢失和读入无效数据的情况,而且还会有效地提高系统中数据的传输效率。使用FIFO进行串口通信,较之传统的串口通信有更高的效率。它将要发送和已经接收的数据集中起来进行操作,避免了频繁的总线操作,减轻了CPU的负担。因此,使得基于FIFO方式的串口通信目前应用十分广泛。
1.3  FIFO中断请求
  S3C44B0X的UART有7个状态(Tx/Rx/Error)信号:溢出错误、奇偶错误、帧错误、断点条件、接收FIFO/Buffer数据准备就绪、发送FIFO/Buffer空和发送移位寄存器空,这些状态信号由相应的UART状态寄存器(UTRSTATn/UERSTATn)声明[1]。
  当处于接收错误状态时,如果在控制寄存器(UCONn)中接收错误状态中断使能位被置为1,则溢出错误、奇偶校验错误、帧错误及断点错误,每1个作为1种错误状态都可发出错误中断请求。当1个接收错误状态中断请求被发现时,引起中断请求信号会被读UERSTATn所识别。如果控制器中的接收模式被选定为中断模式,则当接收器从接收移位寄存器向接收FIFO传输数据时,会激活接收FIFO的可引起接收中断的“满”状态信号。同样,如果控制器中的发送模式被选定为中断模式,则当发送器从发送FIFO向发送移位寄存器传输数据时,可引起发送中断的发送FIFO“空”状态信号被激活。如表1所示。

2  FIFO串口通信的实现
  FIFO重启时,输入和输出的指针都指向FIFO中的第1个存储位置。对FIFO的每次写入操作会使输入指针指向FIFO的下1个存储位置,相应地每次读取操作会使FIFO的输出指针指向FIFO的上1个存储位置。若指针需要从最后1个存储位置移动到第1个存储位置,则FIFO会自动实现这一过程而不需要任何对指针的重启操作。FIFO内部除了包含输入和输出端口之外,通常还有其他状态标志输出,如空状态和满状态。当FIFO已空或者已满时,空状态和满状态标志位就会有相应的输出,即当FIFO已空时不能进行读取操作,当FIFO已满时不能进行写入操作[2]。
2.1  配置特殊寄存器
   为了使目标系统能正常工作,必须配置相关的寄存器,如I/O口寄存器、串口控制寄存器和串口源/目的寄存器等。S3C44B0X有2个串口,这里以串口0为例,进行相关寄存器的配置。
  /*I/O口配置,定义各相关引脚功能和上拉电阻状态 */
  rPCONC |=0xf0000000;
  rPUPC |=0xc000;
  rPCONE=(rPCONE &0x3ffeb)|0x28;
  rPUPE |=0x6; 
  rPCONF=(rPCONF &0x3ff)+0x124800;
  rPUPF |=0x1e0;
  /* 定义串口0工作寄存器组 */
  rULCON0=0x3; //正常模式,无奇偶校验,1位停止位,8位数据位
   rUCON0=0x245;    //Rx为边沿触发,Tx为电平触发,禁
            //止超时中断,产生接收错误中断,普通传送、
           //发送与接收为中断或轮询模式
  rUFCON0=(2<<6)|(1<<4)|(6)|1; //FIFO启动需先复位
     rUBRDIV0=(mclk/(baud*16));  //mclk为60000000,baud为115200
2.2  FIFO串口发送模块
    串口数据发送帧格式是可编程的,它包含1个开始位,5~8个数据位,1个可选的奇偶位和1~2个停止位,这些都可以通过线控制寄存器(UCONn)来设置。发送器也能够产生发送中止条件。中止条件迫使串口输出保持在逻辑0状态,这种状态保持超过1个传输帧的时间长度。通常在1帧传输数据完整地传输完之后,再通过这个全0状态将中止信号发送给对方。中止信号发送之后,传送数据将持续地放入到输出FIFO中。要发送的数据被存放在定义的字符串指针uart0TxStr 中,串口发送模块通过读该字符串中的字符进行数据发送,核心源代码如下:
void __irq Uart0_TxFifoInt(void)
{
  /* 判断FIFO发送缓冲区是否为满或字符串结束 */
  while( !(rUFSTAT0 & 0x200) && (*uart0TxStr !='/0'))
  {
  rUTXH0=*uart0TxStr++;
  for(i=0;i<700;i++);  //延迟,防止FIFO误写
  }
  rI_ISPC=BIT_UTXD0;
  if(*uart0TxStr == '/0')
  {    
              rINTMSK |= BIT_UTXD0; 
              rI_ISPC=BIT_UTXD0; 
      }
}
2.3  FIFO串口接收模块
  接收的数据帧格式与发送一样都是可编程的。它包括了1个起始位,5~8个数据位,1个可选的奇偶校验位和1~2个停止位,这些都可以通过线控制寄存器(UCONn)来设置。接收器还可以检测到溢出错误、奇偶校验错误、帧错误和中止状况,每种情况下都会将1个错误标志置位。
   (1)溢出错误表示新的数据已经覆盖了旧的数据,因为旧的数据没有及时被读入。
  (2)奇偶校验错误表示接收器检测到了意料之外的奇偶校验结果。
  (3)帧错误表示接收到的数据没有有效的停止位。
   (4)中止状况表示RxDn的输入被保持为0状态超过了1个帧传输的时间[3]。
   (5)在FIFO模式下接收FIFO不为空,但接收器已经在3个字时间内没有接收到任何数据,就认为发生了接收超时状况。
   接收模块将数据从接收移位寄存器中读出后,首先被存储到接收缓存数组keyBuf[ ]中。变量keyBufWrPt和keyBufRdPt指向缓存数组中当前写数据和读数据,当接收模块往缓存数组中写入1个字节后,keyBufWrPt加1;当Uart_IntGetKey从缓存数组中读出1个字节后,keyBufRdPt加1。两变量最大值为KEY_LEN,超过最大值时置零。接收模块的核心代码如下[4]:
/* 接收模块将移位寄存器中的数据读出到接收缓存数组中 */
void __irq Uart0_RxFifoInt(void)
  {
     rI_ISPC=BIT_URXD0;
  if(rUFSTAT0==0)
  Uart_Printf("time out/n");
     while( (rUFSTAT0&0xf) >0 )     //循环直到FIFO
                //发送缓冲区为空
        {
      keyBuf[keyBufWrPt++]=rURXH0;   //读取接收缓冲区数据存入缓存数组
      if(keyBufWrPt==KEY_BUFLEN)
         keyBufWrPt=0;
  }
}
/* 定义1个函数从接收缓存数组中读取数据 */
char Uart_IntGetkey(void)
{
   if(keyBufRdPt==KEY_BUFLEN)
   keyBufRdPt=0;
        while(keyBufWrPt==keyBufRdPt);//等待直到FIFO被触发
     return keyBuf[keyBufRdPt++];
}
2.4 FIFO容错模块
   除了接收FIFO寄存器之外,UART还具有1个状态FIFO。状态FIFO表示了在FIFO寄存器中,哪一个数据被毫无错误地接收。假设UART的FIFO连续接收到A、B、C、D、E字符,并且在接收B字符时发生了帧错误(即该字符没有停止位),在接收D字符时发生了奇偶校验错。虽然UART错误发生了,但不会产生错误中断,因为含有错误的字符还没有被CPU读取。当字符被读出时错误中断才会发生,而且只有在读出URXHn和UERSTATn寄存器后,FIFO错误状态寄存器才会被清除[5]。容错模块核心代码如下[6]。
void __irq Uart0_RxFifoErrorInt(void)
{
   rI_ISPC=BIT_UERR01;
     Uart_Printf("UERSTAT0=0x%x/n",rUERSTAT0& 0xf);
     while( (rUFSTAT0&0xf) >0 )
  {
       keyBuf[keyBufWrPt++]=rURXH0;
          if(keyBufWrPt==KEY_BUFLEN);
       keyBufWrPt=0;
         }
}
3  实验结果
   本实验在S3C44B0X和ADS1.2平台上实现,取得了预期的效果。在同等条件下(忽略温度、电压等外部因素变化),在带FIFO(FIFO)和不带FIFO(Non-FIFO)时发送和接收所花时间如表2所示。

  以传输4 KB数据为例,由表2可知,使用FIFO时,发送和接收分别节省0.547 076 s和0.042 832 s时间。假定传输1 bit的数据用时为θs,传输数据量为n,则可知使用FIFO和不使用FIFO两种情况下的用时差为15nθ/16s。由此可见,当传输数据量n越大时,采用FIFO的串口传输模式的用时越少、优越性越明显。这也显示了FIFO在串口传输较大数据量的工程应用中的重要性和必要性。
  在串口通信应用越来越广的背景下,提高串口通信速度显得格外重要。本文以S3C44B0X微处理器为平台,介绍的基于FIFO的串口双机通信的原理和实现方法,该方法同时也适用于其他配置FIFO缓冲区的微处理器,具有很强的适用性和通用性,在学习、研究的同时,也为工程应用中的串口通信提供了参考模型。

你可能感兴趣的:(UART学习,存储,编程,工作,平台,c)