📄 rs232.c
字号:
/*///////////////////////////////////////////////////////////
//COMRXTX.CPP for asyn serial communication (RX/TX)
//edited by Xiong Guangming and Gong Jianwei
//Turbo C++3.0
////////////////////////////////////////////////////////////*/
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#define BUFFLEN 1024
#define BASELEN 3
#define LINES 5
short bExit_Flag=0;
/*/COM1产生的硬件中断号为IQR4,对应的中断向量为为0CH
//打开COM1*/
void OpenPort()
{
InitCOM(); /*/初始化串口*/
/*/读入由参数给定的中断向量值,并将它作为中断函数的远地址*/
asyncoldvect=getvect(cominterrupt);
disable(); /*/关中断 (在安装中断以前,最好用disable ( )函数关闭中断)*/
inportb(combase);
inportb(combase+6);
inportb(combase+3);
inportb(combase+2);
outportb(combase+4,0x08);
outportb(combase+1,0x01);
if(comirq>7)
{
outportb(0x21,inportb(0X21)&0xfb);/*//打开主片IRQ2*/
outportb(0xA1,inportb(0XA1)&(0xfe<<(comirq-8)));/*/打开从片IRQ*/
}
else
outportb(0x21,inportb(0X21)&(0xfe<<comirq));/*/打开主片IRQ*/
setvect(cominterrupt,asyncint);
enable(); /*/*开中断*/
}
int irq_setup(unsigned base)
{
/*/ Returns -1 if not found -- otherwise returns interrupt level*/
char ier, mcr, imrm, imrs, maskm, masks, irqm, irqs;
disable(); /*/ disable all CPU interrupts*/
ier = inportb(base+1); /*/ read IER*/
outportb(base+1,0); /*/* disable all UART ints*/
while (!(inportb(base+5)&0x20)); // wait for the THR to be empty
mcr = inportb(base+4); /*/ read MCR*/
outportb(base+4,0x0F); /*/ connect UART to irq line*/
imrm = inportb(0x21); /*/ read contents of master ICU mask register*/
imrs = inportb(0xA1); /*/ read contents of slave ICU mask register*/
enable();
if (irqs&0x80) /*/ slave interrupt occured*/
return (irqs&0x07)+8;
if (irqm&0x80) /*/ master interrupt occured*/
return irqm&0x07;
return -1;
};
/*/中断服务程序,从COM1接收数据
//注意在TC2.0下,下面函数的...要去掉*/
void interrupt far asyncint(...)
{
//unsigned char ch;
Buffer[buffin++] = inportb(combase);/*/ 读字符到缓冲区*/
if (buffin >= BUFFLEN) /*/ 缓冲区满*/
buffin=0; /*/ 指针复位*/
outportb(0x20,0x20);
outportb(0xA0,0x20);
}
void ClosePort(void) /*/关闭中断*/
{
disable();
outportb(combase+1,0x00);
outportb(combase+4,0x00);
if(comirq>7)
{
outportb(0x21,inportb(0X21)|~(0xfb));/*/关闭主片IRQ*/
outportb(0xA1,inportb(0XA1)|~(0xfe<<(comirq-8)));/*/关闭从片IRQ*/
}
else
outportb(0X21,inportb(0X21)&~(0xfe<<comirq));/*/关闭主片IRQ*/
enable();
setvect(cominterrupt,asyncoldvect);
}
void InitCOM()/*/ 对COM1串口初始化,设置串口参数*/
{
outportb(combase+3,0x80); /*/将设置波特率*/
/* 设置波特率,低位在前、高位在后;(部分波特率器参数如下)
波特率 分频器H 分频器L
...
4800 00 18H
7200 00 10H
9600 00 0CH
....
*/
outportb(combase,0x0C); /*/波特率为9600bps*/
outportb(combase+1,0x00);
/*设置停止位、奇偶校验位、等
D7:为1表示设置波特率;为0,其他;
D6:为1,是,强迫在数据线上输出逻辑0;为0,则否;
D5:1,校验位可变;0,不变;
D4D3:×0,无校验位;01,奇校验位;11,偶校验位;
D2:0,1个停止位;1,1.5个停止位;
D1D0:00,5位数据位;01,6位数据位;10,7位数据位;11,8位数据位;
*/
outportb(combase+3,0x03); /*/8个数据位,1个停止位、无奇偶校验*/
outportb(combase+4,0x08|0x0b);
outportb(combase+1,0x01);
}
unsigned char read_char(void)
{
unsigned unch;
if(buffout != buffin)
{
unch = Buffer[buffout];
buffout++;
if(buffout >= BUFFLEN)
buffout=0;
return(unch);
}
else
return(0xff);
}
/* send char 发送字符函数 */
void send_char(unsigned char unch)
{
while ( ((inp( combase + 5)) & 0x40 ) == 0); /*/和0x40相与 可取出D6位进行判断*/
outportb(combase , unch);
}
int uart_detect(unsigned base)
{
/*/ Returns 0 if no UART detected
// int olddata=inportb(base+4);*/
outportb(base+4, 0x10);
if ((inportb(base+6) & 0xf0)) return 0;
return 1;
};
int base_check(char *base)
{
int len=0,n;
char c;
/*/检查长度*/
while(*(base+len)!='\0')
len++;
if (len>BASELEN)
{
fprintf(stdout, "\nThe length of port address shouldn't be larger than %d.",BASELEN);
return 0;
}
/*/检查合法性*/
for (n=0;n<len;n++)
{
c=*(base+n);
if (((c>=48 && c<=57)||(c>=65 && c<=70)||(c>=97 && c<=102))!=1)
{
fprintf(stdout, "\nInvalid port address.");
return 0;
}
}
return 1;
}
void TestSerial()
{
int unChar,rChar=0xff,c=0;
int sx,sy,rx,ry,zx,zy;
/*/测试端口*/
fprintf(stdout, "\n");
/*/界面*/
fprintf(stdout, "\n\nData send:\n");
XPOS_START=wherex();
YPOS_START=wherey();
fprintf(stdout,"\n\n\n\n\n\nData received:" );
rx=XPOS_START;
ry=YPOS_START+LINES+2;
zx=XPOS_START;
zy=YPOS_START+LINES+10;
gotoxy(XPOS_START,YPOS_START);
unChar=0x21;
while (1)
{
/*/打印发送字符*/
gotoxy(sx,sy);
fprintf(stdout,"%c",unChar);
sx=wherex();
sy=wherey();
send_char(unChar);
delay(50);
/*/打印接收字符*/
rChar = read_char();
gotoxy(rx,ry);
if (rChar!=0xff)
fprintf(stdout,"%c",rChar);
else
{
fprintf(stdout,"COM is not connected.");
printf( "\a" );
break;
}
rx=wherex();
ry=wherey();
/*/打印提示信息*/
gotoxy(zx,zy);
if (unChar==rChar)
fprintf(stdout,"Succeed!");
else
{
fprintf(stdout,"Error!");
printf( "\a" );
}
/*/超过范围回到原始坐标点*/
if (sy>=YPOS_START+LINES)
{
sx=XPOS_START;
rx=XPOS_START;
for(sy=YPOS_START;sy<=YPOS_START+LINES;sy++)
{
gotoxy(sx,sy);
clreol();
}
for(ry=YPOS_START+LINES+2;ry<=YPOS_START+2*LINES+1;ry++)
{
gotoxy(rx,ry);
clreol();
}
sy=YPOS_START;
ry=YPOS_START+LINES+2;
}
unChar++;
if (unChar>0x7e)
unChar=0x21;
/*/键盘处理 */
if (kbhit())
c=getch();
if (c==0x1B )
{
bExit_Flag = 1;
break;
}
if (c==0x09 )
break;
}
ClosePort(); /*/关闭串口*/
}
/*/以下为主函数*/
main(int argc, char *argv[] )
{
unsigned char unChar;
short bExit_Flag=0;
int sx,sy,rx,ry,i;
int a,checkirq;
struct text_info winstatus;
gettextinfo(&winstatus);
/*/初始化端口*/
/*while (irq>15 || irq<3)
{ fprintf(stdout, "\nInput error.Please input a number between 3 and 15:");
fflush(stdin);
scanf("%d",&irq);
}*/
if (argc!=3)
{
fprintf(stdout, "\nTest command format is :"
"\nfilename serialport_address serialport_intvector "
"\nExample: rs232 3f8 4 "
"\nCOM1 : 3F8 4 "
"\nCOM2 : 2F8 3 "
"\nCOM3 : 3E8 7 "
"\nCOM4 : 2E8 5 ");
return -1;
}
if(base_check(argv[1])==0)
return -1;
combase=strtol(argv[1],NULL,16);
comirq=strtol(argv[2],NULL,10);
if(comirq>15 || comirq<3)
{
fprintf(stdout, "\nIRQ must be a number between 3 and 15:");
return -1;
}
/*checkirq=irq_setup(combase);
if (comirq!=checkirq)
{
fprintf(stdout, "\nInput error!IRQ is %d.",checkirq);
return -1;
}*/
clrscr();
switch(comirq)
{
case 3: cominterrupt=0x0b;
break;
case 4: cominterrupt=0x0c;
break;
case 5: cominterrupt=0x0d;
break;
case 6: cominterrupt=0x0e;
break;
case 7: cominterrupt=0x0f;
break;
case 8: cominterrupt=0x70;
break;
case 9: cominterrupt=0x71;
break;
case 10: cominterrupt=0x72;
break;
case 11: cominterrupt=0x73;
break;
case 12: cominterrupt=0x74;
break;
case 13: cominterrupt=0x75;
break;
case 14: cominterrupt=0x76;
break;
case 15: cominterrupt=0x77;
break;
}
OpenPort();
//开始测试
fprintf(stdout, "\nAddress %x , IRQ%d testing.Press [ESC] to quit.\n",combase,comirq);
fprintf(stdout, "\n\nReady to Receive DATA\n"
"press [ESC] to quit...\n\n");
fprintf(stdout, "\nPress keyboard to transmit data to PC"
"\nReceive data from PC\n\n"
"\nSTART_TEST:\n");
do {
if (kbhit())
{
unChar=getch();
/* Look for an ESC key */
switch (unChar)
{
case 0x1B: /*/ESC的ASCII值为27*/
bExit_Flag = 1; /* Exit program */
break;
/*/You may want to handle other keys here*/
}
if(!bExit_Flag)
send_char(unChar); /*/发送键入的字符*/
}
unChar = read_char(); /*/从缓冲区中读数*/
delay(100);
if (unChar != 0xff)
{
fprintf(stdout,"%2x ",unChar);
}
} while (!bExit_Flag);
ClosePort(); /*/关闭串口*/
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -