📄 commport.cpp
字号:
// CommPort.cpp: implementation of the CCommPort class.
//
//////////////////////////////////////////////////////////////////////
#include "CommPort.h"
#include <string.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCommPortBasicClass::CCommPortBasicClass()
{
m_PortBasicAddr=0;
m_InterruptNo=0;
m_BeSendingMark=0;
}
CCommPortBasicClass::~CCommPortBasicClass()
{
if(!m_PortBasicAddr) return;
disable();
outportb(m_PortBasicAddr+1,0x0); //禁止端口所有数据中断,不能缺少。
setvect(m_InterruptNo,m_PortOldIntHandle);//恢复原中断
//屏蔽中断IRQ
if(m_InterruptNo>>4)
{
outportb(0x21,inportb(0x21)|~0xFB); //屏蔽中断IRQ2
outportb(0xA1,inportb(0xA1)|(0x1<<(m_InterruptNo&0x07)));
}
else
{
outportb(0x21,inportb(0x21)|(0x1<<(m_InterruptNo&0x07)));
}
enable();
delay(220);
}
//输入参数:端口基地址 端口中断号 期望的波特率 新中断处理函数
void CCommPortBasicClass::OpenCommPort(unsigned short int tPortBasicAddr,unsigned char tInterruptNo,unsigned short int tBaudRate,void interrupt (*tPortNewIntHandle)(...))
{
if(!tPortBasicAddr||!tInterruptNo) return ;
m_PortBasicAddr=tPortBasicAddr;//端口基地址
m_InterruptNo=tInterruptNo; //端口中断号
m_BeSendingMark=0;
disable();
m_PortOldIntHandle=getvect(m_InterruptNo); // 设置中断
setvect(m_InterruptNo,tPortNewIntHandle);
//取消中断IRQ的屏蔽
if(m_InterruptNo>>4)
{ //中断为从片IRQ
outportb(0x21,inportb(0x21)&0xFB); //打开主片IRQ2
outportb(0xA1,inportb(0xA1)&(~(0x1<<(m_InterruptNo&0x07))));//打开从片IRQ
}
else
{//中断为主片IRQ
outportb(0x21,inportb(0x21)&(~(0x1<<(m_InterruptNo&0x07))));//打开主片IRQ
}
//设置波特率为9600=115200/0xC,7200=115200/0x10..
outportb(m_PortBasicAddr+3,0x80); //除数锁存器DLAB置1
outportb(m_PortBasicAddr,(unsigned short int)(115200L/tBaudRate));//0xc=9600,0x10=7200..
outportb(m_PortBasicAddr+1,0X0); //始终为0
outportb(m_PortBasicAddr+3,0x3); //设置数据格式,置DLAB=0:8位数据位,1位停止位,无校验
outportb(m_PortBasicAddr+4,0xB);; //置UART操作方式为中断方式
outportb(m_PortBasicAddr+1,0x0B); //允许发送、接收数据中断
enable();
}
void CCommPortBasicClass::PortIntHandleFunction()
{
char ch;
outportb(m_PortBasicAddr+3,inportb(m_PortBasicAddr+3)&0x7F); //置DLAB=0
for( ; ;)
{
switch(inportb(m_PortBasicAddr+2))
{
case 1://已无其他中断
if(m_InterruptNo>>4) outportb(0xA0,0x20);//向从片ICR送EOI命令
outportb(0x20,0x20);//向主片ICR送EOI命令
return ;
case 2://发送中断
if(SendQueue.GetData(ch)) outportb(m_PortBasicAddr,ch);
else { m_BeSendingMark=0,inportb(m_PortBasicAddr+2);} // 不能缺少
break;
case 4://接收中断
if(inportb(m_PortBasicAddr+5)&0x01) //D0为1,有新数据
ReceiveNewChar(inportb(m_PortBasicAddr)&0xFF);
break;
case 0://MODEM状态变化中断
inportb(m_PortBasicAddr+6); // 不能缺少
break;
default:
break;
}
}
}
void CCommPortBasicClass::ActiveSendInterrupt()
{
if((!m_BeSendingMark)&&(m_PortBasicAddr))
{
char ch;
m_BeSendingMark=1;
SendQueue.GetData(ch);
outportb(m_PortBasicAddr,ch);
}
}
void CCommPortBasicClass::WriteStringToBuffer(char *str, unsigned short Len/*=0*/)
{
if(Len==0) Len=strlen(str);
for(unsigned short int i=0;i<Len;i++) SendQueue+=str[i];
ActiveSendInterrupt();
}
void CCommPortBasicClass::WriteCharToBuffer(char ch)
{
SendQueue+=ch;
ActiveSendInterrupt();
}
int CCommPortBasicClass::ReadChar(char &ch)
{
return RecvQueue.GetData(ch);
}
void CCommPortBasicClass::WriteStringToPort(char *str, unsigned short Len/*=0*/)
{
if(Len==0) Len=strlen(str);
for(unsigned short int i=0;i<Len;i++) WriteCharToPort(str[i]);
}
void CCommPortBasicClass::WriteCharToPort(char ch)
{
while((inportb(m_PortBasicAddr+5)& 0x20)==0) //等待可以发送的信息,等待D5为1
{// 超时处理部分,一般省略
}
outportb(m_PortBasicAddr,ch);
}
void CCommPortBasicClass::ReceiveNewChar(unsigned char ch)
{
RecvQueue.AddData(ch);
}
void CCommPortBasicClass::EmptySendRecvBuffer()
{
SendQueue.EmptyAll();
RecvQueue.EmptyAll();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -