中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
作者:
标题: 串行通讯口的实用编程[1] 上一主题 | 下一主题
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
状态 离线
『第 7 楼』:  

UP UP UP

2009-9-18 12:45
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
netreg
初级用户




积分 134
发帖 17
注册 2004-10-25
状态 离线
『第 8 楼』:  

UP UP UP

2009-11-16 17:46
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: