您的位置:首页 > 其它

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

2010-05-10 16:52 232 查看
我使用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,则放在释放函数中。这个比较简单了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: