| 
|  |  
| firstsail 高级用户
 
     
 
 
 
 积分 668
 发帖 295
 注册 2005-7-26
 来自 广东深圳
 状态 离线
 | 
| 『楼 主』:
 串行通讯口的实用编程[1]
 
使用 LLM 解释/回答一下 
 
 
#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]
 
使用 LLM 解释/回答一下 
 
 
//这里是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]
 
使用 LLM 解释/回答一下 
 
 
//这里是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 =
 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++;
 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;
 pCommControl->pBufferS = new BYTE;
 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 + 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 = 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 = this->ReceiveData();
 }
 
 return (nCount);
 }
 
 //发送多个字节
 BOOL	CMotorNet::SendBuffer(BYTE* pBuffer, int nCount)
 {
 for (int i = 0; i < nCount; i++)
 {
 if (!this->SendData(pBuffer))
 {
 //在中断模式时,一直等到缓冲区不为空
 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 楼』:
 
 
使用 LLM 解释/回答一下 
 
 
//此文件为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 楼』:
 
 
使用 LLM 解释/回答一下 
 
 
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 楼』:
 
 
使用 LLM 解释/回答一下 
 
 
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 |  |  |