|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『楼 主』:
串行通讯口的实用编程[1]
#include <Stdio.h>
#include <Stdlib.h>
#include <bios.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#include <symbol.h>
#include <DownComm.h>
int main()
{
BYTE byCh;
char buf[256];
CMotorNet mMotorNet; //使用通讯口COM1,波特率9600,8位数据位,1位起始位,1位停止位,无奇偶校验,查询方式
mMotorNet.Init(0x2F8, 9600, 8, 1, 1, NO_PARITY, FALSE); //如果中断方式, FALSE改为TRUE即可。
//发送一个字节
byData = 'W'
mMotorNet.SendData(byData);
//发送一个串
::_fstrcpy(buf, "This is WinSail V2.0!");
mMotorNet.SendBuffer(buf, _strlen(buf) + 1);
//接收一个数据
byCh = mMotorNet.ReceiveData();
if (byCh == 0 && GetLastCommError() == COMM_ERROR_CODE_TIME)
{
//这里没有读到数据
}
else
{
//这里读到了数据
}
//接收一个串,超时为165mS(=3 * 55mS)
int nCount = mMotorNet.ReceiveData(buf, 256, 3);
if (nCoun == 0)
{
//这里完全没有数据
}
else if (nCount != 256)
{
//这里不足256字节的数据
}
else
{
//这里读足了256字节数据
}
//接收8个字节的串,有超时处理
BOOL bSuccess = TRUE;
for (int i = 0; i < 8; i++)
{
if (!mMotorNet.WaitCommData(3)) //3 * 55mS超时
{
bSuccess = FALSE;
break;
}
buf[i] = mMotorNet.ReceiveData();
}
if (bSuccess)
{
//成功读到8个字节
}
else
{
//没有读到8个字节
}
//接收8个字节的串,无超时处理
for (int i = 0; i < 8; i++)
{
while (!mMotorNet.IsCommData())
{
}
buf[i] = mMotorNet.ReceiveData();
}
return(0);
}
|
|
2008-9-25 17:49 |
|
|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『第
2 楼』:
串行通讯口的实用编程[2]
//这里是DownComm.h文件
#ifndef _DOWN_COMMx_H_
#define _DOWN_COMMx_H_
#define COMM_ERROR_SUCCESS 0
#define COMM_ERROR_TIME -1
#define COMM_ERROR_USER -2
#define COMM_ERROR_CHECK -3
#define COMM_ERROR_BUSY -4
#define COMM_ERROR_DEFAULT -5
#define COMM_ERROR_OVER -6
#define COMM_ERROR_ADDRESS -7
#define COMM_ERROR_FORMAT -8
#define COMM_ERROR_ANSWER -9
#define COMM_ERROR_FILE -0xA
#define COMM_ERROR_READY -0xB
#define COMM_ERROR_CRAFT -0xC
#define COMM_ERROR_AGAIN -0xD
#define COMM_ERROR_BUFFER_FULL -0xE
#define CBR_50 50lu
#define CBR_110 110lu
#define CBR_300 300lu
#define CBR_600 600lu
#define CBR_1200 1200lu
#define CBR_2400 2400lu
#define CBR_4800 4800lu
#define CBR_9600 9600lu
#define CBR_14400 14400lu
#define CBR_19200 19200lu
#define CBR_38400 38400lu
#define CBR_56000 56000lu
#define CBR_57600 57600lu
#define CBR_115200 115200lu
#define CBR_128000 128000lu
#define CBR_256000 256000lu
#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define MARKPARITY 3
#define SPACEPARITY 4
#define ONESTOPBIT 0
#define ONE5STOPBITS 1
#define TWOSTOPBITS 2
#define DTR_CONTROL_DISABLE 0x00
#define DTR_CONTROL_ENABLE 0x01
#define DTR_CONTROL_HANDSHAKE 0x02
#define RTS_CONTROL_DISABLE 0x00
#define RTS_CONTROL_ENABLE 0x01
#define RTS_CONTROL_HANDSHAKE 0x02
#define RTS_CONTROL_TOGGLE 0x03
#define COMM_DB25_TXD 2 //数据发送端,输出
#define COMM_DB25_RXD 3 //数据接收端,输入
#define COMM_DB25_RTS 4 //请求发送(计算机要求发送数据),输出
#define COMM_DB25_CTS 5 //清除发送(MODEM准备接收数据),输入
#define COMM_DB25_DSR 6 //数据设备准备就绪,输入
#define COMM_DB25_SG 7 //信号地
#define COMM_DB25_DCD 8 //数据载波检测,输入
#define COMM_DB25_DTR 20 //数据终端准备就绪(计算机),输出
#define COMM_DB25_RI 22 //响铃指示,输入
#define COMM_DB9_TXD 3 //数据发送端,输出
#define COMM_DB9_RXD 2 //数据接收端,输入
#define COMM_DB9_RTS 7 //请求发送(计算机要求发送数据),输出
#define COMM_DB9_CTS 8 //清除发送(MODEM准备接收数据),输入
#define COMM_DB9_DSR 6 //数据设备准备就绪,输入
#define COMM_DB9_SG 5 //信号地
#define COMM_DB9_DCD 1 //数据载波检测,输入
#define COMM_DB9_DTR 4 //数据终端准备就绪(计算机),输出
#define COMM_DB9_RI 9 //响铃指示,输入
#define COMM_REGISTER_THR 0
#define COMM_REGISTER_RBR 0
#define COMM_REGISTER_BAUDL 0
#define COMM_REGISTER_BAUDH 1
#define COMM_REGISTER_IER 1
#define COMM_REGISTER_IIR 2
#define COMM_REGISTER_FCR 2
#define COMM_REGISTER_LCR 3
#define COMM_REGISTER_MCR 4
#define COMM_REGISTER_LSR 5
#define COMM_REGISTER_MSR 6
#define COMM_REGISTER_SR 7
typedef struct tagCOMMCONTROL
{
int nIRQ;
int nBase;
int nErrorCode;
void interrupt (*pOldFc) (...);
DWORD dwBaud;
WORD wDataBit;
WORD wStartBit;
WORD wStopBit;
WORD wParity;
BYTE* pBufferR; //输入缓冲区
int nSizeR; //输入缓冲区的尺寸
int nTailR; //输入缓冲区的尾指针
int nHeadR; //输入缓冲区的头指针
BOOL bFullR; //输入缓冲区的标志
BYTE* pBufferS; //输出缓冲区
int nSizeS; //输出缓冲区的尺寸
int nTailS; //输出缓冲区的尾指针
int nHeadS; //输出缓冲区的头指针
BOOL bFullS; //输出缓冲区的标志
}COMMCONTROL, *LPCOMMCONTROL;
class CMotorNet
{
private:
BOOL m_bInterrupt;
int m_nIRQ;
int m_nErrorCode;
private:
COMMCONTROL* GetCommControl();
void CloseInterrupt();
public:
void ChangeParity(WORD wParity);
void InitComm(int nBase, DWORD dwBaud, WORD wDataBit = 8, WORD wStartBit = 1,
WORD wStopBit = 1, WORD wParity = NOPARITY, BOOL bInterrupt = FALSE);
public:
BOOL IsCommData();
BOOL IsBusy();
BOOL WaitCommData(DWORD dwWait);
BYTE ReceiveData();
BOOL SendData(BYTE nCh);
int ReceiveBuffer(BYTE* pBuffer, int nCount, DWORD dwTimeOut = 0lu);
BOOL SendBuffer(BYTE* pBuffer, int nCount);
void ClearBufferR();
void ClearBufferS();
public:
int GetLastCommError(){return(m_nErrorCode);};
void SetLastCommError(int nErrorCode){m_nErrorCode=nErrorCode;}
void ClearLastCommError(){m_nErrorCode=COMM_ERROR_SUCCESS;}
public:
CMotorNet();
~CMotorNet();
};
#endif
[ Last edited by firstsail on 2008-9-25 at 05:55 PM ]
|
|
2008-9-25 17:51 |
|
|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『第
3 楼』:
串行通讯口的实用编程[3]
//这里是DownComm.Cpp文件
#include <string.h>
#include <dos.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys\\stat.h>
#include <io.h>
#include <conio.h>
#include <bios.h>
#include <symbol.h> //此文件可在“WinSail V2.0下载后获得”
#include <DownComm.h>
#define COMM_INTERRUPT_BUFFER_SIZE 1024
#define MEMORY_TIME_ADDRESS 0x46CL
#define COMM_TIME_DELAY 4L
COMMCONTROL Afx_CommControl3={3, 0x3F8, COMM_ERROR_SUCCESS, NULL};
COMMCONTROL Afx_CommControl4={4, 0x2F8, COMM_ERROR_SUCCESS, NULL};
//这是COMM口中断模式时的中断调用公共函数
void COMM_PublicInterruptFc (COMMCONTROL* pCommControl)
{
BYTE byData,byLin, byIIR;
int nCommBase = pCommControl->nBase;;
//Read and discard interrupt
byData = inportb(nCommBase + COMM_REGISTER_LSR);
//get interrupt status
byIIR = inportb(nCommBase + COMM_REGISTER_IIR);
//is interrupt?
if (!!(byIIR & 0x1))
{
return;
}
byData = ((byIIR >> 1) & 0x3);
if (byData == 0x2) //receive
{
if (!pCommControl->bFullR)
{
pCommControl->pBufferR[pCommControl->nTailR] =
inportb(nCommBase + COMM_REGISTER_RBR);
pCommControl->nTailR++;
if (pCommControl->nTailR >= pCommControl->nSizeR)
{
pCommControl->nTailR = 0;
}
if (pCommControl->nTailR == pCommControl->nHeadR)
{
pCommControl->bFullR = TRUE;
}
}
}
else if (byData == 0x1) //send
{
if (pCommControl->nHeadS != pCommControl->nTailS ||
pCommControl->bFullS)
{
outportb(nCommBase + COMM_REGISTER_RBR,
pCommControl->pBufferS[pCommControl->nHeadS]);
pCommControl->nHeadS++;
if (pCommControl->nHeadS >= pCommControl->nSizeS)
{
pCommControl->nHeadS = 0;
}
pCommControl->bFullS = FALSE;
}
//Is empty?
if (pCommControl->nHeadS == pCommControl->nTailS)// && !pCommControl->bFullW)
{
byLin = inportb(nCommBase + COMM_REGISTER_LCR);
byLin &= 0x7F;
outportb(nCommBase + COMM_REGISTER_LCR, byLin);
//force interrupt for send only
outportb(nCommBase + COMM_REGISTER_IER, 0x1);
}
pCommControl->bFullS = FALSE;
}
else if (byData == 0x0) //Model status interrupt
{
}
else if (byData == 0x3) //receive line status
{
}
return;
}
//IRQ3中断函数
void interrupt CMotorNet_NewInterruptFc3 (...)
{
asm mov ax, seg Afx_CommControl3
asm mov ds, ax
::COMM_PublicInterruptFc (&Afx_CommControl3);
outportb(0x20, 0x20);
return;
}
//IRQ4中断函数
void interrupt CMotorNet_NewInterruptFc4 (...)
{
asm mov ax, seg Afx_CommControl3
asm mov ds, ax
::COMM_PublicInterruptFc (&Afx_CommControl4);
outportb(0x20, 0x20);
return;
}
//获得通讯控制包结构指针
COMMCONTROL* CMotorNet::GetCommControl()
{
if (m_nIRQ == 3)
{
return (&Afx_CommControl3);
}
else
{
return (&Afx_CommControl4);
}
}
//CMotorNet类的构造函数
CMotorNet::CMotorNet()
{
m_bInterrupt = FALSE;
m_nIRQ = 3;
m_nErrorCode = COMM_ERROR_SUCCESS;
}
//CMotorNet类的析构函数
CMotorNet::~CMotorNet()
{
this->CloseInterrupt();
}
//在中断模式时,将中断模式转查询模式
void CMotorNet::CloseInterrupt()
{
BYTE byData;
COMMCONTROL* pCommControl = this->GetCommControl();
asm pushf
asm cli
if (m_bInterrupt)
{
//mask irq
byData = inportb(0x21);
byData |= (1 << m_nIRQ);
outportb(0x21, byData);
//clear IER access bit,disable 8250 interrupt
byData = inportb(pCommControl->nBase + COMM_REGISTER_LCR);
byData &= 0x7F;
outportb(pCommControl->nBase + COMM_REGISTER_LCR, byData);
outportb(pCommControl->nBase + COMM_REGISTER_IER, 0x0);
//other
inportb(pCommControl->nBase + COMM_REGISTER_RBR);
inportb(pCommControl->nBase + COMM_REGISTER_LSR);
inportb(pCommControl->nBase + COMM_REGISTER_IIR);
inportb(pCommControl->nBase + COMM_REGISTER_IER);
inportb(pCommControl->nBase + COMM_REGISTER_MSR);
//disable 8250 RTS, DTR, ...
outportb(pCommControl->nBase + COMM_REGISTER_MCR, 0);
outportb(pCommControl->nBase + COMM_REGISTER_MCR, 0);
if (pCommControl->pOldFc != NULL)
{
::_dos_setvect(8 + m_nIRQ, pCommControl->pOldFc);
pCommControl->pOldFc = NULL;
}
pCommControl->nHeadR = pCommControl->nHeadS = 0;
pCommControl->nTailR = pCommControl->nTailS = 0;
pCommControl->nSizeR = pCommControl->nSizeS = 0;
pCommControl->bFullR = pCommControl->bFullS = FALSE;
DELETE(pCommControl->pBufferR);
DELETE(pCommControl->pBufferS);
pCommControl->nErrorCode = COMM_ERROR_SUCCESS;
}
m_bInterrupt = FALSE;
asm popf
return;
}
//改变奇偶校验方式,特别适用于RS485传输时的“地址”和“数据”传输
void CMotorNet::ChangeParity(WORD wParity)
{
asm pushf
asm cli
COMMCONTROL* pCommControl = this->GetCommControl();
BYTE byAttrib = (BYTE)pCommControl->wAttrib;
byAttrib &= 0x7F;
if (wParity == NOPARITY) //B5,B4,B3 = xx0
{
byAttrib &= ~(1<<3); byAttrib &= ~(1<<4); byAttrib &= ~(1<<5);
}
else if(wParity == ODDPARITY) //B5,B4,B3 = 001
{
byAttrib |= (1<<3); byAttrib &= ~(1<<4); byAttrib &= ~(1<<5);
}
else if (wParity == EVENPARITY) //B5,B4,B3 = 011
{
byAttrib |= (1<<3); byAttrib |= (1<<4); byAttrib &= ~(1<<5);
}
else if (wParity == MARKPARITY) //B5,B4,B3 = 101
{
byAttrib |= (1<<3); byAttrib &= ~(1<<4); byAttrib |= (1<<5);
}
else if (wParity == SPACEPARITY) //B5,B4,B3 = 111
{
byAttrib |= (1<<3); byAttrib |= (1<<4); byAttrib |= (1<<5);
}
outportb(pCommControl->nBase + COMM_REGISTER_LCR, byAttrib);
pCommControl->wParity = byAttrib;
asm popf
return;
}
//串行口初始化
void CMotorNet::InitComm(int nBase,DWORD dwBaud,WORD wDataBit,
WORD wStartBit,WORD wStopBit,WORD wParity, BOOL bInterrupt)
{
BYTE byIRQMask;
m_nErrorCode = COMM_ERROR_SUCCESS;
if (m_bInterrupt)
{
this->CloseInterrupt();
}
//Modify IRQ
if (nBase == 0x3F8 || nBase == 0x3E8) m_nIRQ = 4; //Com1
if (nBase == 0x2F8 || nBase == 0x2E8) m_nIRQ = 3; //Com2
COMMCONTROL* pCommControl = this->GetCommControl();
//force interrupt
outportb(nBase + COMM_REGISTER_IER, 0x00);
//Set IRQ disable
byIRQMask = inportb(0x21);
outportb(0x21, byIRQMask | (1 << m_nIRQ));
//Modify Data Bit
if(wDataBit < 5u || wDataBit > 8u)
{
wDataBit = 8;
}
//Modify StartBit
wStartBit = 1;
//Modify StopBit
if (wStopBit != ONESTOPBIT &&
wStopBit != ONE5STOPBITS &&
wStopBit != TWOSTOPBITS)
{
wStopBit = ONESTOPBIT;
}
//Save Comm Attrib
pCommControl->nBase = nBase;
pCommControl->dwBaud = dwBaud;
pCommControl->wDataBit = wDataBit;
pCommControl->wStartBit = wStartBit;
pCommControl->wStopBit = wStopBit;
pCommControl->wParity = wParity;
m_bInterrupt = bInterrupt;
//Write Baud
outportb(nBase + COMM_REGISTER_LCR, 0x80); //baud-rate enable
outportb(nBase + COMM_REGISTER_BAUDL, LOBYTE((115200L/ dwBaud)));
outportb(nBase + COMM_REGISTER_BAUDH, HIBYTE((115200L/ dwBaud)));
//Calc LCR Value
BYTE byAttrib = 0u;
if (wDataBit==5) {byAttrib &= ~(1<<1); byAttrib &= ~(1<<0);}//00
if (wDataBit==6) {byAttrib &= ~(1<<1); byAttrib |= (1<<0);}//01
if (wDataBit==7) {byAttrib |= (1<<1); byAttrib &= ~(1<<0);}//10
if (wDataBit==8) {byAttrib |= (1<<1); byAttrib |= (1<<0);}//11
if (wStopBit == ONESTOPBIT) byAttrib &= ~(1<<2);
if (wStopBit == ONE5STOPBITS) byAttrib |= (1<<2);
if (wStopBit == TWOSTOPBITS) byAttrib |= (1<<2);
if (wParity == NOPARITY)
{
byAttrib &= ~(1<<3); byAttrib &= ~(1<<4); byAttrib &= ~(1<<5);
}
else if(wParity == ODDPARITY)
{
byAttrib |= (1<<3); byAttrib &= ~(1<<4); byAttrib &= ~(1<<5);
}
else if (wParity == EVENPARITY)
{
byAttrib |= (1<<3); byAttrib |= (1<<4); byAttrib &= ~(1<<5);
}
else if (wParity == MARKPARITY)
{
byAttrib |= (1<<3); byAttrib &= ~(1<<4); byAttrib |= (1<<5);
}
else if (wParity == SPACEPARITY)
{
byAttrib |= (1<<3); byAttrib |= (1<<4); byAttrib |= (1<<5);
}
//write start bit, stop bit, parity
outportb(nBase + COMM_REGISTER_LCR, byAttrib);
//Moden control 00000110B
outportb(nBase + COMM_REGISTER_MCR, 0x03);
if (bInterrupt)
{
COMMCONTROL* pCommControl = this->GetCommControl();
this->CloseInterrupt();
m_bInterrupt = TRUE;
asm pushf
asm cli
//Malloc buffer for read and write
pCommControl->nIRQ = m_nIRQ;
pCommControl->nBase = nBase;
pCommControl->nErrorCode = COMM_ERROR_SUCCESS;
pCommControl->pBufferR = new BYTE[COMM_INTERRUPT_BUFFER_SIZE];
pCommControl->pBufferS = new BYTE[COMM_INTERRUPT_BUFFER_SIZE];
pCommControl->nHeadR = pCommControl->nHeadS = 0;
pCommControl->nTailR = pCommControl->nTailS = 0;
pCommControl->nSizeR = pCommControl->nSizeS = COMM_INTERRUPT_BUFFER_SIZE;
pCommControl->bFullR = pCommControl->bFullS = FALSE;
asm cli
//get old vect
pCommControl->pOldFc = ::_dos_getvect(m_nIRQ + 8);
//Set Interrupt Fc
if (m_nIRQ == 3)
{
::_dos_setvect(m_nIRQ + 8, CMotorNet_NewInterruptFc3);
}
else
{
::_dos_setvect(m_nIRQ + 8, CMotorNet_NewInterruptFc4);
}
asm cli
//Set IRQ Enable
byIRQMask = inportb(0x21);
outportb(0x21, byIRQMask & (~(1 << m_nIRQ)));
//discard LSR
inportb(nBase + COMM_REGISTER_LSR);
//discard MSR
inportb(nBase + COMM_REGISTER_MSR);
//discard RBR
inportb(nBase + COMM_REGISTER_RBR);
//LCR Bit7->0
byAttrib = inportb(nBase + COMM_REGISTER_LCR);
byAttrib &= 0x7F;
outportb(nBase + COMM_REGISTER_LCR, byAttrib);
//permit interrupt for receive data ,00000001B
outportb(nBase + COMM_REGISTER_IER, 0x1);
//Model control,00001100B
outportb(nBase + COMM_REGISTER_MCR, 0xB);
//FIFO control,00000000B
outportb(nBase + COMM_REGISTER_FCR, 0x0);
asm popf
}
}
//中断模式时,用于清空输入缓冲区
void CMotorNet::ClearBufferR()
{
asm pushf
asm cli
COMMCONTROL* pCommControl = this->GetCommControl();
pCommControl->nHeadR = pCommControl->nTailR = 0;
pCommControl->bFullR = FALSE;
asm popf
}
//中断模式时,用于清空输出缓冲区
void CMotorNet::ClearBufferS()
{
asm pushf
asm cli
COMMCONTROL* pCommControl = this->GetCommControl();
pCommControl->nHeadS = pCommControl->nTailS = 0;
pCommControl->bFullS = FALSE;
asm popf
}
//判断是否有数据可读
BOOL CMotorNet::IsCommData()
{
COMMCONTROL* pCommControl = this->GetCommControl();
if (!m_bInterrupt)
{
return((inportb(pCommControl->nBase + COMM_REGISTER_LSR)&0x01));
}
else
{
if (pCommControl->nHeadR != pCommControl->nTailR ||
pCommControl->bFullR)
{
return (TRUE);
}
}
return(FALSE);
}
//在规定的时间内等待数据的到来,
BOOL CMotorNet::WaitCommData(DWORD dwWait)
{
DWORD far *pdwMemoryTime = (DWORD far *)MEMORY_TIME_ADDRESS;
DWORD dwTime = *pdwMemoryTime;
//This maybe dead lock, you need modify code!!!
while (!this->IsCommData())//(inportb(m_nCommBase+5) & 0x01))
{
if (*pdwMemoryTime - dwTime >= dwWait)
{
return(FALSE);
}
}
return(TRUE);
}
//接收一个字节
BYTE CMotorNet::ReceiveData()
{
m_nErrorCode = COMM_ERROR_SUCCESS;
if (!this->WaitCommData(COMM_TIME_DELAY))
{
m_nErrorCode = COMM_ERROR_TIME;
return(0);
}
COMMCONTROL* pCommControl = this->GetCommControl();
if (m_bInterrupt)
{
asm pushf
asm cli
BYTE byData = pCommControl->pBufferR[pCommControl->nHeadR];
pCommControl->nHeadR = pCommControl->nHeadR + 1;
if (pCommControl->nHeadR >= pCommControl->nSizeR)
{
pCommControl->nHeadR = 0;
}
pCommControl->bFullR = FALSE;
asm popf
return(byData);
}
else
{
return(inportb(pCommControl->nBase));
}
}
//发送一个字节
BOOL CMotorNet::SendData(BYTE nCh)
{
COMMCONTROL* pCommControl = this->GetCommControl();
if (!m_bInterrupt)
{
while (this->IsCommData())
{
this->ReceiveData();
}
DWORD far *pdwMemoryTime=(DWORD far *)MEMORY_TIME_ADDRESS;
DWORD dwTime = *pdwMemoryTime;
//DWORD dwCount=0;
while (!(inportb(pCommControl->nBase + COMM_REGISTER_LSR) & 0x20))
{
if (*pdwMemoryTime - dwTime > COMM_TIME_DELAY) //100
{
m_nErrorCode = COMM_ERROR_TIME;
return(FALSE);
}
}
outportb(pCommControl->nBase,nCh);
}
else
{
if (pCommControl->bFullS)
{
return (FALSE);
}
asm pushf
asm cli
pCommControl->pBufferS[pCommControl->nTailS] = nCh;
pCommControl->nTailS = pCommControl->nTailS + 1;
if (pCommControl->nTailS >= pCommControl->nSizeS)
{
pCommControl->nTailS = 0;
}
if (pCommControl->nTailS == pCommControl->nHeadS)
{
pCommControl->bFullS = TRUE;
}
//permit interrupt for receive and send data ,00000011B
outportb(pCommControl->nBase + COMM_REGISTER_IER, 0x3);
asm popf
}
return(TRUE);
}
//接收多个字节
int CMotorNet::ReceiveBuffer(BYTE* pBuffer, int nCount, DWORD dwTimeOut)
{
for (int i = 0; i < nCount; i++)
{
if (!this->WaitCommData(dwTimeOut))
{
return (i);
}
pBuffer[i] = this->ReceiveData();
}
return (nCount);
}
//发送多个字节
BOOL CMotorNet::SendBuffer(BYTE* pBuffer, int nCount)
{
for (int i = 0; i < nCount; i++)
{
if (!this->SendData(pBuffer[i]))
{
//在中断模式时,一直等到缓冲区不为空
if (m_bInterrupt && this->GetCommControl()->bFullS)
{
i--;
continue;
}
return (FALSE);
}
}
return (TRUE);
}
//判断总线是否忙
//常用于RS485发送端,一般情况下如果忙,须清空输入缓冲区
BOOL CMotorNet::IsBusy()
{
this->ClearLastCommError();
return (this->IsCommData());
}
|
|
2008-9-25 17:52 |
|
|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『第
4 楼』:
//此文件为WinSail V2.0下载后的“功能类_CMotorNet类串行通讯详细设计.DOC”文件
2 类简介
类名为CMotorNet,头文件是“DownComm.h”。
3 类成员函数
3.1 IsCommData()
原型:BOOL IsCommData();
作用:判断是否有数据可读
入口参数:无
出口参数:无
返回值:有数据可读返回TRUE,否则返回FALSE。
3.2 IsBusy()
原型:BOOL IsBusy();
作用:判断是否有数据可读,与IsCommData()函数作为相同
入口参数:无
出口参数:无
返回值:有数据可读返回TRUE,否则返回FALSE。
3.3 WaitCommData()
原型:BOOL WaitCommData(DWORD dwWait);
作用:在指定的时间内等待有数据可读
入口参数:DWORD dwWait ---- 时间计数值,以55mS为单位
出口参数:无
返回值:成功返回TRUE,否则返回FALSE
3.4 SendData()
原型:BOOL SendData(BYTE byCh);
作用:发送一个字节
入口参数:BYTE byCh ---- 需发送的字节
出口参数:无
返回值:成功发送返回TRUE,否则返回FALSE
3.5 ReceiveData()
原型:BYTE ReceiveData();
作用:接收一个字节
入口参数:无
出口参数:无
返回值:成功返回数据值;否则返回0,并置通讯错误代码为COMM_ERROR_TIME
3.6 ReceiveBuffer()
原型:int ReceiveBuffer(BYTE* pBuffer, int nCount ,DWORD dwTimeOut = 0lu);
作用:接收多个字节
入口参数: int nCount----------需读取的字节数
DWORD dwTimeOut-----超时时间,以55mS为单位
出口参数:BYTE* pBuffer-------缓冲区首地址
返回值:返回接收的字节数
3.7 Void SendBuffer()
原型:void Re();
作用:发送多个字节
入口参数:无
出口参数:无
返回值:无
3.8 Void ClearBufferR()
原型:void ClearBufferR();
作用:在中断模式下,清除接收缓冲区
入口参数:无
出口参数:无
返回值:无
3.9 Void ClearBufferS()
原型:void ClearBufferS();
作用:在中断模式下,清除发送缓冲区
入口参数:无
出口参数:无
返回值:无
3.10 ChangeParity()
原型:void ChangeParity(WORD wParity);
作用:修改奇偶校验属性
入口参数:WORD wParity --- 奇偶校验属性,见InitComm()函数
出口参数:无
返回值:无
3.11 Void InitComm()
原型:void InitComm(int nBase, DWORD dwBaud, WORD wDataBit = 8, WORD wStartBit = 1,
WORD wStopBit = 1, WORD wParityStyle = NOPARITY, BOOL bInterrupt = FALSE);
作用:初始化通迅口
入口参数:int nBase --- 通讯口在基地址
COM1 = 0x3F8 COM2 = 0x2F8
COM3 = 0x3E8 COM4 = 0x2E8
DWORD dwBaud-----波特率,其值如下
CBR_50 50波特率
CBR_110 110波特率
CBR_300 300波特率
CBR_600 600波特率
CBR_1200 1200波特率
CBR_2400 2400波特率
CBR_4800 4800波特率
CBR_9600 9600波特率
CBR_14400 14400波特率
CBR_19200 19200波特率
CBR_38400 38400波特率
CBR_56000 56000波特率
CBR_57600 57600波特率
CBR_115200 115200波特率
CBR_128000 128000波特率
CBR_256000 256000波特率
WORD wDataBit---------数据位,值为5,6,7,8
WORD wStartBit--------起始位,值固定为“1”
WORD wStopBit---------停止位,取值如下
ONESTOPBIT 1位停止位
ONE5STOPBITS 1.5位停止位
TWOSTOPBITS 2位停止位
WORD wParityStyle-----奇偶校验
NOPARITY 无校验
ODDPARITY 奇校验
EVENPARITY 偶校验
MARKPARITY 校验位永为“1”
SPACEPARITY 校验位永为“0”
BOOL bInterrupt-------中断模式,TRUE为中断模式,FALSE为查询模式
出口参数:无
返回值:无
3.12 int GetLastCommError()
原型:int GetLastCommError();
作用:获得通讯错误代码
入口参数:无
出口参数:无
返回值:通讯错误代码。如果没有通讯错误,返回COMM_ERROR_SUCCESS
3.13 void SetLastCommError ()
原型:void SetLastCommError (int nErrorCode);
作用:设置通讯错误代码
入口参数:int nErrorCode--------错误代码
出口参数:无
返回值:无
3.14 Void ClearLastCommError ()
原型:int GetLastCommError();
作用:清除通讯错误代码
入口参数:无
出口参数:无
返回值:无
[ Last edited by firstsail on 2008-9-25 at 06:20 PM ]
|
|
2008-9-25 18:00 |
|
|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『第
5 楼』:
1.2 RS232的寄存器
RS232共有12个寄存器
序号 地址 名称 信号方向
1 Base + 0 发送保持寄存器 只写
2 Base + 0 接收数据寄存器 只读
3 Base + 0 除数锁存寄存器(LSB),波特率低八位 可读写
4 Base + 1 除数锁存寄存器(MSB),波特率高八位 可读写
5 Base + 1 IER----中断启用寄存器 只读
6 Base + 2 IIR----中断标识寄存器 只读
7 Base + 2 FCR----FIFO寄存器 只写
8 Base + 3 LCR----线路控制寄存器 可读写
9 Base + 4 MCR----MODEM控制寄存器 可读写
10 Base + 5 LSR----线路状态寄存器 只读
11 Base + 6 MSR----MODEM状态寄存器 只读
12 Base + 7 暂时存储寄存器 可读写
IER = base + 1, 中断启用寄存器
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____允许接收数据就绪中断,置1时允许接收到数据时产生中断
| | | | | | |_________允许发送保持器空中断,置1时允许发送保持寄存器空时产生中断
| | | | | |_____________允许接收线路状态中断,即置1时将在LSR变化时产生中断
| | | | |_________________允许MODEM状态中断, 即置1时将在MSR变化时产生中断
| | | |_____________________进入睡眠模式(16750)
| | |_________________________进入低功耗模式(16750)
| |_____________________________未使用
|_________________________________未使用
IIR = base + 2, 中断识别寄存器,只读属性
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____指示是否有中断发生
| | | | | | | 0:有中断发生
| | | | | | | 1:无中断发生
| | | | | | |
| | | | | |___\_________标识具体的中断类型,中断具有优先级,LSR最高,MSR最低
| | | | | 00:MODEL状态中断(CTS/RI/DTR/DCD)
| | | | | 01:发送保持寄存器空中断
| | | | | 10:接收数据就绪中断
| | | | | 11:接收线路状态中断
| | | | |_________________超时中断(16550/16750)
| | | |_____________________未使用
| | |_________________________允许64字节FIFO(16550/16750)
| |
|___\_____________________________00:无FIFO(此时是8250/16450芯片)
01:允许FIFO,但不可用
11:允许FIFO
FCR = base + 2, FIFO控制寄存器,只写属性
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____允许FIFO
| | | | | | |_________清除接收FIFO
| | | | | |_____________清除发送FIFO
| | | | |_________________DMA模式选择
| | | |_____________________未使用
| | |_________________________允许64字节FIFO
| |
|___\_____________________________00:1Byte产生中断
01:4Byte产生中断
11:8Byte产生中断
11:14Byte产生中断
LCR = base + 3, 线路控制寄存器,可读/写
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |
| | | | | | |___\_____00:5位数据位
| | | | | | 01:6位数据位
| | | | | | 10:7位数据位
| | | | | | 11:8位数据位
| | | | | |_____________0->1位停止位;1->2位停止位(6,7,8);1->1.5位停止位(5)
| | | | |
| | | | |
| | |___\___\_________________XX0:无校验
| | 001:奇校验
| | 011:偶校验
| | 101:奇偶保持为1
| | 111:奇偶保持为0
| |_____________________________设置间断,0-禁止,1-设置
|_________________________________0:允许访问接收/发送及中断允许寄存器
1:允许访问波特率因子寄存器
MCR = base + 4, MODEM控制寄存器,可读/写
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____设置DSR
| | | | | | |_________设置RTS
| | | | | |_____________辅助输出1
| | | | |_________________辅助输出2
| | | |_____________________环路测试
| | |_________________________自动流量控制(仅16750)
| |_____________________________未使用
|_________________________________未使用
LSR = base + 5, 线路状态寄存器,只读
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____接收数据就绪
| | | | | | |_________超越错
| | | | | |_____________奇偶错
| | | | |_________________帧格式错
| | | |_____________________间断
| | |_________________________发送保持寄存器空
| |_____________________________发送移位寄存器空
|_________________________________FIFO中接收数据错误
MSR = base + 6, MODEM状态寄存器,只读
B7, B6, B5, B4, B3, B2, B1, B0
| | | | | | | |_____CTS已改变
| | | | | | |_________DSR已改变
| | | | | |_____________RI已改变
| | | | |_________________DCD已改变
| | | |_____________________CTS有效
| | |_________________________DSR准备就绪
| |_____________________________响铃指示
|_________________________________载波检测
1.3 波特率的计算
是用1.8432MHz时钟经过16分频的时钟(115200Hz)作为被除数,波特率作为除数,余数写入除数锁存寄存器中。
BYTE wDivL = LOBYTE(115200L/(DWORD)wBaud);
BYTE wDivH = HIBYTE(115200L/ (DWORD)wBaud);
|
|
2008-9-25 18:02 |
|
|
firstsail
高级用户
积分 668
发帖 295
注册 2005-7-26 来自 广东深圳
状态 离线
|
『第
6 楼』:
DOS系统最多支持4个通讯口,分别为COM1、COM2、COM3、COM4。基地址分别对应于0x3F8、0x2F8、0x3E8、0x2E8。
RS232电缆一般是DB25或DB9物理接口,其意义如下:
DB25 DB9 信号名称 方向 含义
2 3 TXD 输出 数据发送端
3 2 RXD 输入 数据接收端
4 7 RTS 输出 请求发送(计算机要求发送数据),低电平有效
5 8 CTS 输入 清除发送(MODEM准备接收数据),低电平有效
6 6 DSR 输入 数据设备准备就绪,低电平有效
7 5 GND 信号地
8 1 DCD 输入 数据载波检测,低电平有效
20 4 DTR 输出 数据终端准备就绪(计算机),低电平有效
22 9 RI 输入 响铃指示
在RS323电缆中,随着电缆长度的增加,信号遇到的电容就越多,从而使得数据的高速传输变得不可靠。并不是说在通讯时所有的管脚都被用上,这依赖于软件设计,但最简单的采用三线互联,RXD<—>TXD、TXD<—>RXD,GND<-->GND。
|
|
2008-9-25 18:24 |
|
|
lonm
新手上路
积分 12
发帖 6
注册 2008-8-2
状态 离线
|
|
2009-9-18 12:45 |
|
|
netreg
初级用户
积分 134
发帖 17
注册 2004-10-25
状态 离线
|
|
2009-11-16 17:46 |
|
|