修改s3c440普通串口驱动为485驱动

来源:互联网 发布:淘宝视频妹子 编辑:程序博客网 时间:2024/05/16 15:52

我使用te2440板,板自带串口3个,其中一个为485,通用232接口程序已经写好,但是没有485的驱动,好郁闷。

在花了4天不停的rebuild和download后,终于搞定了代码。

在描述如何搞定之前先描述一下485工作原理,

485需要在接收的时候,需要有一个io口使其处于接收状态,在发送的时候需要设定发送io使其处于发送状态。

程序的关键是在接收数据的时候需要一直使RE为0,而在发送时,RE,DE必须保持为1。考虑到,程序的执行时间,最好的就是在发送阶段RE,DE为1,其他时间就是处于接收状态。

而s3c2440的驱动上是以FIFO模式,这样就不能知道其是否处于发送结束状态。也就没法修改RE,DE位,在查了相应资料后,不得已只能采用循环扫描FIFO的TX寄存器了。如果FIFO长度为0则发送结束。

 

这样也就将程序的原理说明了,具体代码实现上,就看PDD代码,发现其采用virtual函数的方式,这也就给了我们只做小小修改的机会了。

首先在基类里面,添加 virtual Init485()=0; virtual Init485Rec()=0;virtual Init485Send()=0;virtual defaul485()=0;

然后在每个串口的具体函数上写具体实现代码。

对于非485的串口,直接写成空函数。即virtual Init485Rec(){}

对于485的,那就需要写成其具体执行命令,程序中Init485,初始GPIO,实现引脚输出,Init485Rec,Init485Send,实现GPIO输出对应值,Init485Rec中需要检测FIFO的状态,再GPIO输出。

 

然后最重要的就是在何时何地调用这些函数了,程序的发送采用中断的方式,就只需要在中断函数XmitInterruptHandler中加入对应函数即可。

具体代码如下。

PREFAST_DEBUGCHK(pBuffLen!=NULL);
    m_HardwareLock.Lock();   
    if (*pBuffLen == 0) {
        EnableXmitInterrupt(FALSE);
        Init485Rec();
    }
    else {
        DEBUGCHK(pTxBuffer);
        PulseEvent(m_XmitFlushDone);
        DWORD dwDataAvaiable = *pBuffLen;
        *pBuffLen = 0;
     Init485Send();
  Rx_Pause(TRUE);
        if ((m_DCB.fOutxCtsFlow && IsCTSOff()) ||(m_DCB.fOutxDsrFlow && IsDSROff())) { // We are in flow off
            DEBUGMSG(ZONE_THREAD|ZONE_WRITE,(TEXT("CPdd16550::XmitInterruptHandler! Flow Off, Data Discard./r/n")));
            EnableXmitInterrupt(FALSE);
        }
        else  {
            DWORD dwWriteSize = GetWriteableSize();
            DEBUGMSG(ZONE_THREAD|ZONE_WRITE,(TEXT("CPdd16550::XmitInterruptHandler! WriteableSize=%x to FIFO,dwDataAvaiable=%x/r/n"),
                    dwWriteSize,dwDataAvaiable));
            for (DWORD dwByteWrite=0; dwByteWrite<dwWriteSize && dwDataAvaiable!=0;dwByteWrite++) {
                m_pReg2440Uart->Write_UTXH(*pTxBuffer);
                pTxBuffer ++;
                dwDataAvaiable--;
            }
            DEBUGMSG(ZONE_THREAD|ZONE_WRITE,(TEXT("CPdd16550::XmitInterruptHandler! Write %d byte to FIFO/r/n"),dwByteWrite));
            *pBuffLen = dwByteWrite;
            EnableXmitInterrupt(TRUE);       
  }

 


        ClearInterrupt(S2440UART_INT_TXD);

  if (m_pReg2440Uart->Read_ULCON() & (0x1<<6))
   while( (m_pReg2440Uart->Read_UFSTAT() >> 0x8 ) & 0x3f );
  Rx_Pause(FALSE);
    }
    m_HardwareLock.Unlock();

 而其中的初始化Init485的调用,可以放在构造函数中,而defaul485,则放在释放函数中。这个比较简单了。