一直想将串口编程整理一下,一来分享给想了解串口编程的爱好者,二来防止梳理一下对COM的认识,^_^。
以前在网上也查询了很多相关的串口编程,居多的是在Windos环境,使用VC,VB编写的,也有在DOS下编写,但是看了很久的代码,揣摩很久,有的地方还不明白。这次我分享的是DOS下的COM操作,下面是我编写验证OK的Code。
编译环境:MS-DOS 7.1 +Borland C3.1
通过一个例子来说明吧,实现在DOS环境下,将DOS下的文件通过串口传送到其它终端设备(如:另一PC:Personal Computer)。
DOS(PC) <---------(COM)-------> Windows(PC) 实现不同OS之间传送,Windows接收到数据可以依据规则做相应的处理,暂时不考虑数据的冗余校验(CRC)。
Code:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
unsigned char *cy_receive_buf; //文件字符
int lenchar=0;//文件字符的长度
/*=========================================================================*/
//1.初始化串口函数
/*initial COM */
/*Ex:InitCom(C1,0x0C,0x0B) --COM1,9600pbs,8bit Data,1 Stop Bit,odd Check*/
void InitCom(int Port,char BaudRate,char bits)
{
outportb(Port + 1, 0); /* Turn off interrupts - Port*/
outportb(Port + 3, 0x80); /* SET DLAB ON */
outportb(Port + 0, BaudRate); /* Set Baud rate-Low 8 Byte */
outportb(Port + 1, 0x00); /* Set Baud rate -High 8 Byte */
outportb(Port + 3, bits); /* 8 Bits, No Parity, 1 Stop Bit */
}
/*=========================================================================*/
//2.发送数据函数
// Send Data Function,Data 为字节
int Send(int Port,char Data)
{
unsigned char status = inportb(Port + 5); /* Check Line Status */
unsigned int count = 2000;
while(!(status & 0x20) && (count > 0))
{
count --;
status = inportb(Port + 5);
}
if(count > 0)
{
outportb(Port + 0, Data);
return 0;
}
else
{
printf("COM Send Data Error!\n");
return -1;
}
}
/*=========================================================================*/
//3.接收数据
//Receive Data Function
int Receive(int Port)
{
char *pd;
unsigned char status = inportb(Port + 5); /* Check Line Status */
if(status & 0x01)
{
*pd = inportb(Port + 0); /* Read */
//printf(" %x \n",*pData);
return *pd;
}
return 0;
}
/*=========================================================================*/
//4.Help
void Help(void)
{
printf("Syntax error :\n");
printf("Usage : send |
printf("
printf("
printf("
printf("
printf("
printf("
printf("
printf("Example : send C1 \\C123NB6.008==> Use COM1 Up log File C123NB6.008\n" );
exit(-1);
}
/*=========================================================================*/
/*=========================================================================*/
//5.Main Function
int main(int argc,char **argv)
{
int i,Port;
FILE *fp; //For Open Log File ,文件指针
char ch; // Read Log File
int wFileLen; //读取文件长度
char *CName; //Use Which Com Port
char *FName ; //For LogFile Name
//char Path[50]="C:\\Borlandc\\bin\\"; //For Log File Path
char *PathFile; //For Link Path +FileName
char buffer[MAXPATH];
getcwd(buffer, MAXPATH); //获取当前路径
if (argc <2 )
{
Help();
return -1;
}
if (strcmp( argv[1],"/?")==0)
{
Help();
return -1;
}
if (strcmp( argv[1],"?")==0)
{
Help();
return -1;
}
if((strcmp(argv[1],"C1") != 0) && (strcmp(argv[1],"C2") != 0) && (strcmp(argv[1],"C3") != 0) && (strcmp(argv[1],"C4") != 0))
{
Help();
return -1;
}
if (argc >3)
{
Help();
return -1;
}
//第一个参数是COM PortID,第二个参数是要传送的文件名
if (argc >= 2)
{
//COM PortID
//printf("Which COM Port Used:%s\n",argv[1]);
CName=argv[1];
if (strcmp(CName,"C1")==0)
Port=0x3F8;
if(strcmp(CName,"C2")==0)
Port=0x2F8;
if(strcmp(CName,"C3")==0)
Port=0x3E8;
if(strcmp(CName,"C4")==0)
Port=0x2E8;
if(strcmp(CName,"C5")==0)
Port=0x2E0;
if(strcmp(CName,"C6")==0)
Port=0x2F8;
//要传送的文件名称
//printf(" LogFile Name is:%s\n",argv[2]);
FName=argv[2];
}
//For Debug调试使用
// printf("Port is %d \n",Port);
//printf("Path is :%s\n",buffer);
//路径加文件名称
PathFile=strcat(buffer,FName);
//For Debug调试使用
//printf("Path and File Name is :%s\n",PathFile);
// getch();
//读取要传送的文件
if((fp=fopen(PathFile,"rb"))==NULL) //Read Only
{
printf("Open Log File Error!\n");
exit(-1);
}
//文件读取成功,获取文件内容长度
//printf("File length :%ld\n",filelength(fileno(fp)));
wFileLen=filelength(fileno(fp));
//对内容做CRC16校验的话,要在发送的内容上加入2位校验位
//重新定义数组的大小为文件大小加2(校验位的高低位)
//不考虑校验值的情况,取消下一步
//cy_receive_buf = (unsigned char*)calloc(wFileLen+2,sizeof(char));
cy_receive_buf =(unsigned char*)calloc(wFileLen+0,sizeof(char));
ch=fgetc(fp);
//printf("COM Initialize... \n");
InitCom(Port,0x0C, 0x03);//9600bps,8位数据位,0x03无校验,1为停止位
delay(50);
while(ch!=EOF)
{
//putchar(ch);//输出显示,方便调试
//crc_chec_fuc(ch) ;
//Send(Port,ch);
cy_receive_buf[lenchar]=ch;
lenchar++;
//delay(5);
ch=fgetc(fp);
}
printf("\n");
//计算读取字符串的CRC值
//暂时不做CRC
//Calculate_CRC(cy_receive_buf,wFileLen);
//getch();
//printf("\n");
//获取要发送字符串的CRC高位和低位
//cy_receive_buf[wFileLen+0]=get_Hvalue(CRC) ;
//cy_receive_buf[wFileLen+1]=get_Lvalue(CRC);
//显示获取的高低位的值
//printf("CRCH is %x\n",cy_receive_buf[wFileLen+0]);
//printf("CRCL is %x\n",cy_receive_buf[wFileLen+1]);
// getch();
//开始上传读取的文件的内容
//printf(" Log File Uploading ....\n");
//移除校验的高低字节(2位)
//for(i=0;i
//For Debug 显示发送的字符
// printf("%02X ",cy_receive_buf[i]);
delay(1);
//getch();
Send(Port,cy_receive_buf[i]);
}
//发送完成后发送一个特殊字符,告知接收到该字符
//为发送完成标志,这个字符由上位机处理(Windos PC )
Send(Port,'§');
fclose(fp);
return 0;
}
此代码编译验证PASS,可以发送文件内容,可以使用串口调试工具测试。
接收的数据可以在上位机上处理成自己需要的字符串。如果有任何疑问,可以联系我讨论。