修改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,则放在释放函数中。这个比较简单了。
在花了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,则放在释放函数中。这个比较简单了。
相关文章推荐
- Linux内核修改:将2440串口UART2(红外端口)更成普通串口驱动
- 修改2410的linux串口驱动,使其支持RS485
- Linux-2.6.32.2内核在mini2440上的移植(十八)---将UART2更成普通串口驱动
- Linux-2.6.32.2内核在mini2440上的移植(十八)---将UART2更成普通串口驱动
- Zigbee网关 Zstack增加串口功能1-修改底层驱动MT/MT_UART.c
- 【引用】Linux-2.6.32.2内核在mini2440上的移植(十八)---将UART2更成普通串口驱动
- JZ2440移植Linux3.4.2之将UART2更成普通串口驱动
- 修改SMDK6410的调试串口为普通串口(wince系统)
- 修改2416其他3个串口为普通串口并激活使用
- 修改SMDK6410的调试串口为普通串口(wince系统)
- 修改SMDK6410的调试串口为普通串口(wince系统)
- 修改2410的linux串口驱动,使其支持RS485
- 海思3518c普通串口更换485通讯(启用rtsn管脚)-内核代码修改
- 2440开发板将串口2的修改为普通串口
- NUC100RE3AN串口驱动库修改
- RT5350 openwrt将ttyS1修改为控制端口,ttyS0为普通串口
- linux2.6.32.2内核把mini2440的UART2改为普通的串口驱动
- mini2440 串口1通信串口改调试串口及6410将com0修改为普通串口
- TQ2440中如何把串口0由调试串口修改为普通串口?