hard_sio.c
来自「串口芯片驱动程序 驱动芯片为16C554。」· C语言 代码 · 共 354 行
C
354 行
//========================================================//
// Code Infomation: //
// This module defines the uart hard //
// process functions for Board_DSP of MAIN_CONTROL //
// devices named 管理板CPU //
// Version: v1.01 //
// Programmer: Lejianxin //
// Date: Begined from 2005.02 //
// Last modified at //
// Copyright(c) 2002-2004 Shenzhen NARI Co. //
//========================================================//
/* 程序修改记录(最新的放在最前面): *
* <修改日期>, <修改人员>: <修改功能概述> *
*========================================================*
2.01 2005-02-28 10:25 Lejianxin modify
*========================================================*/
#include "Macro.h"
#include "Variable.h"
#include "Function.h"
#include "Hardware.h"
#include "Sio_16C554.h"
#include "CPU_S3C44B0x.h"
BOOLEAN Hard_Uart_Init( BYTE byPortNo )
{
tagPPortSet ptPortSet;
tagPParamSio ptParamSio;
tagWord_Byte2 tDevisor;
BYTE byLCR, byIndex;
LPSTR pAddr;
byIndex = byPortNo - CN_PORT_BASE_SIO;
if( byIndex >=CN_NUM_PORT_SIO ) return FALSE;
ptPortSet = g_ptPortSet[CN_PORT_BASE_SIO+byIndex];
g_tPortVal[byPortNo].wResetTimes++;
ptParamSio = (tagPParamSio)(ptPortSet->dwParam);
// the devisor value is different due to the frequency
switch( ptPortSet->byBaudRate )
{
case EN_COM_BAUD_300 : tDevisor.wWord = 384; break; // 300
case EN_COM_BAUD_600 : tDevisor.wWord = 192; break; // 600
case EN_COM_BAUD_1200 : tDevisor.wWord = 96; break; // 1200
case EN_COM_BAUD_2400 : tDevisor.wWord = 48; break; // 2400
case EN_COM_BAUD_4800 : tDevisor.wWord = 24; break; // 4800
case EN_COM_BAUD_9600 : tDevisor.wWord = 12; break; // 9600
case EN_COM_BAUD_19200 : tDevisor.wWord = 6; break; // 19200
case EN_COM_BAUD_38400 : tDevisor.wWord = 3; break; // 38400
case EN_COM_BAUD_57600 : tDevisor.wWord = 2; break; // 57600
case EN_COM_BAUD_115200: tDevisor.wWord = 1; break; // 115200
default : tDevisor.wWord = 12; break; // 9600
}
byLCR = 0x80 | ((ptParamSio->byDataBit - 5) & 0x03); // Data's Bit-Length
if( 2 ==ptParamSio->byStopBit ) byLCR = byLCR | 0x04; // Stopping Bit-Length
if( 1 ==ptParamSio->byParity ) byLCR = byLCR | 0x08; // odd Parity & Parity enabled
else if( 2 ==ptParamSio->byParity ) byLCR = byLCR | 0x18; // even Parity & Parity enabled
pAddr = (LPSTR)(ptPortSet->dwAddBase);
*(pAddr + CN_SIO_IER) = 0x00; // 关闭中断
*(pAddr + CN_SIO_FCR) = 0x06;
*(pAddr + CN_SIO_LCR) = byLCR;
*(pAddr + CN_SIO_DLL) = tDevisor.cByte[0];
*(pAddr + CN_SIO_DLM) = tDevisor.cByte[1];
byLCR = byLCR & 0x7F;
*(pAddr + CN_SIO_LCR) = byLCR;
*(pAddr + CN_SIO_FCR) = 0x81;
*(pAddr + CN_SIO_MCR) = 0x03;
if( CN_PORT_RS485 ==ptPortSet->byPortType ) *(pAddr + CN_SIO_MCR) = 0x01;
*(pAddr + CN_SIO_IER) = 0x01; // 仅开接收中断
return TRUE;
}
BOOLEAN Hard_Uart_TxStartup( BYTE byPortNo )
{
tagPPortSet ptPortSet;
tagPSendCtrl ptSendCtrl;
BYTE bySetIER, byIndex;
LPSTR pAddr;
byIndex = byPortNo - CN_PORT_BASE_SIO;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
if( M_GET_BIT( g_tDbgCtrl.dwParam[byPortNo], EN_DBG_MSG_SEND) )
{ // message-watching
ptSendCtrl = &(g_tPortVal[byPortNo].tSendCtrl);
Dbg_SavePortMsg( byPortNo, EN_DBG_MSG_SEND, ptSendCtrl->wSendLen, ptSendCtrl->bySendBuf );
}
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
if( CN_PORT_RS485 ==ptPortSet->byPortType )
{ // 如果是485口,则切换为发送模式
*(pAddr + CN_SIO_MCR) = 0x02;
}
pAddr = (LPSTR)(pAddr + CN_SIO_IER );
bySetIER = *pAddr;
*pAddr = bySetIER & 0xFD; // Clear TX-INT: 1111-1101
*pAddr = bySetIER | 0x02; // Enable TX-INT: make sure to have TX-INT-pluse
return( TRUE );
}
BYTE Hard_Uart_GetIIR( BYTE byIndex )
{
tagPPortSet ptPortSet;
LPSTR pAddr;
BYTE byPortNo;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
byPortNo = CN_PORT_BASE_SIO + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
return( *(pAddr + CN_SIO_IIR) );
}
BYTE Hard_Uart_GetLSR( BYTE byIndex )
{
tagPPortSet ptPortSet;
LPSTR pAddr;
BYTE byPortNo;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
byPortNo = CN_PORT_BASE_SIO + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
return( *(pAddr + CN_SIO_LSR) );
}
BYTE Hard_Uart_GetMSR( BYTE byIndex )
{
tagPPortSet ptPortSet;
LPSTR pAddr;
BYTE byPortNo;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
byPortNo = CN_PORT_BASE_SIO + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
return( *(pAddr + CN_SIO_MSR) );
}
void Hard_Uart_SetMCR( BYTE byIndex, BYTE byMCR )
{
tagPPortSet ptPortSet;
LPSTR pAddr;
BYTE byPortNo;
if( byIndex >=CN_NUM_PORT_SIO ) return;
byPortNo = CN_PORT_BASE_SIO + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
*(pAddr + CN_SIO_MCR) = byMCR;
return;
}
BYTE Hard_Uart_Fifo_Read( BYTE byIndex )
{
LPSTR pAddrLSR, pAddrRBR;
tagPRecvCtrl ptRecvCtrl;
BYTE byPortNo, byLen, byTempBuf[32], *pbyRecvBuf;
WORD wWrite, wRead;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
byPortNo = CN_PORT_BASE_SIO + byIndex;
ptRecvCtrl = &g_tPortVal[byPortNo].tRecvCtrl;
pbyRecvBuf = ptRecvCtrl->byRecvQue;
wWrite = ptRecvCtrl->wRecvWrite;
wRead = ptRecvCtrl->wRecvRead;
if( wWrite >=CN_VOL_BUF_RECV )
{
wWrite = 0;
wRead = 0;
}
byLen = 0;
pAddrLSR = (LPSTR)(g_ptPortSet[byPortNo]->dwAddBase + CN_SIO_LSR);
pAddrRBR = (LPSTR)(g_ptPortSet[byPortNo]->dwAddBase + CN_SIO_RBR);
while( 0 !=(*pAddrLSR & 0x01) )
{
pbyRecvBuf[wWrite] = *pAddrRBR;
byTempBuf[byLen] = pbyRecvBuf[wWrite];
wWrite++;
if( wWrite >=CN_VOL_BUF_RECV ) wWrite = 0;
if( wWrite ==wRead ) // Receive Buffer overflow!!!
{
wRead++;
if( CN_VOL_BUF_RECV <=wRead ) wRead = 0;
//Fun_Msg( COM_BUFFER_OVERFLOW, byPortNo );
}
byLen++;
if( byLen >=32 ) break; // prevent from infinite cycle
}
ptRecvCtrl->wRecvWrite = wWrite;
ptRecvCtrl->wRecvRead = wRead;
Time_TimerBReset( &ptRecvCtrl->tTimerRecv ); // clear the timer
// message-watching
if( M_Dbg_RawDataRecv( byPortNo) )
{
Dbg_SavePortMsg( byPortNo, EN_DBG_DATA_RECV, byLen, byTempBuf );
}
return byLen;
}
BYTE Hard_Uart_Fifo_Write( BYTE byIndex )
{
tagPSendCtrl ptSendCtrl;
BYTE byPortNo, byLSR, byLen, byLoop, *pbySendBuf;
WORD wRead, wTimeout;
LPSTR pAddr, pAddrThr;
if( byIndex >=CN_NUM_PORT_SIO ) return 0;
byPortNo = CN_PORT_BASE_SIO + byIndex;
pAddr = (LPSTR)(g_ptPortSet[byPortNo]->dwAddBase );
byLSR = *(pAddr + CN_SIO_LSR);
if( 0 ==(byLSR & 0x20) ) return 0; // THR not empty!
ptSendCtrl = &g_tPortVal[byPortNo].tSendCtrl;
wRead = ptSendCtrl->wSendRead;
if( (wRead >=CN_VOL_BUF_SEND) || ((wRead >=ptSendCtrl->wSendLen)&&(wRead!=0)) ) // ERROR
{
ptSendCtrl->wSendLen = 0;
ptSendCtrl->wSendRead = 0;
ptSendCtrl->wSendFlag = CN_STATUS_SEND_IDLE;
Time_TimerBStop ( &ptSendCtrl->tTimerAbandon );
Time_TimerBReset( &ptSendCtrl->tTimerLineIdle ); // 用Reset便于不同规约使用不同的空闲间隔
}
if( CN_STATUS_SEND_BUSY !=ptSendCtrl->wSendFlag )
{
// 本报文已经发送完,关闭发送中断
*(pAddr+CN_SIO_IER) = *(pAddr+CN_SIO_IER) & 0xFD; // 1111-1101
// 如果是485口, 则在发送完最后一字节后切换为接收模式
if( CN_PORT_RS485 ==g_ptPortSet[byPortNo]->byPortType )
{
wTimeout = 0;
while( (*(pAddr+CN_SIO_LSR)&0x40) != 0x40 )
{
wTimeout++;
if( 0 ==wTimeout ) break;
}
*(pAddr + CN_SIO_MCR) = 0x01; // 切换到接收
}
return 0;
}
byLen = 0;
pAddrThr = pAddr + CN_SIO_THR; // the addr of 16C554 TX-buffer
pbySendBuf = &ptSendCtrl->bySendBuf[wRead]; // the start position to be sent
if( (wRead+12) <ptSendCtrl->wSendLen )
{
byLen = 12;
ptSendCtrl->wSendRead = wRead + byLen;
// Time_TimerBReset( &ptSendCtrl->tTimerAbandon );
}else
{
byLen = ptSendCtrl->wSendLen - wRead;
ptSendCtrl->wSendLen = 0;
ptSendCtrl->wSendRead = 0;
ptSendCtrl->wSendFlag = CN_STATUS_SEND_IDLE;
Time_TimerBStop ( &ptSendCtrl->tTimerAbandon );
Time_TimerBReset( &ptSendCtrl->tTimerLineIdle ); // 用Reset便于不同规约使用不同的空闲间隔
}
for( byLoop=0; byLoop<byLen; byLoop++ )
{
*pAddrThr = pbySendBuf[byLoop];
}
// message-watching
if( M_Dbg_RawDataSend( byPortNo) )
{
Dbg_SavePortMsg( byPortNo, EN_DBG_DATA_SEND, byLen, pbySendBuf );
}
return byLen;
}
void Hard_Uart_IntProcess( BYTE byIndex )
{
LPSTR pAddr;
BYTE byIIR, byTemp, byPortNo;
if( byIndex >=CN_NUM_PORT_SIO ) return;
byPortNo = CN_PORT_BASE_SIO + byIndex;
pAddr = (LPSTR)(g_ptPortSet[byPortNo]->dwAddBase );
byIIR = *(pAddr + CN_SIO_IIR) & 0x0F;
if( (0x04==byIIR) || (0x0C==byIIR) ) // RI
{
Hard_Uart_Fifo_Read( byIndex );
byIIR = *(pAddr + CN_SIO_IIR) & 0x0F;
}
if( 0x02 == byIIR ) // TI
{
Hard_Uart_Fifo_Write( byIndex );
byIIR = *(pAddr + CN_SIO_IIR) & 0x0F;
}
if( 0x06 ==byIIR ) // ERROR: Read LSR to clear
{
byTemp = *(pAddr + CN_SIO_LSR);
// Hard_Uart_Get_LSR( byIndex );
// Hard_Uart_Init( byIndex + CN_PORT_BASE_SIO );
// Com_ClearRevParaBuffer( byIndex + CN_PORT_BASE_SIO );
}
return;
}
void Sys_LedRUN( void )
{
DWORD dwValReg;
M_CPU_REG_READ( CN_CPU_PDATC, dwValReg );
dwValReg = dwValReg ^ CN_LED_RUN_ON; // 取反
M_CPU_REG_WRITE( CN_CPU_PDATC, dwValReg );
return;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?