一个c语言的串口通信程序范例
标签: 分类: 技术笔记
c语言
串口通信
通信程序
it
最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#define COM232 0x2f8
#define COMINT 0x0b
#define MaxBufLen 500
#define Port8259 0x20
#define EofInt 0x20
static int comportaddr;
static char intvectnum;
static unsigned char maskb;
static unsigned char Buffer[MaxBufLen];
static int CharsInBuf,CircIn,CircOut;
static void (interrupt far *OldAsyncInt)();
static void interrupt far AsyncInt(void);
void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) {
unsigned char High,Low;
int f;
comportaddr=ComPortAddr;
intvectnum=IntVectNum;
CharsInBuf=0;CircIn=0;CircOut=0;
f=(Baud/100);
f=1152/f; High=f/256;
Low=f-High*256;
outp(ComPortAddr+3,0x80);
outp(ComPortAddr,Low);
outp(ComPortAddr+1,High);
Data=(Data-5)|((Stop-1)*4);
if(Parity==2) Data=Data|0x18;
else if(Parity==1) Data=Data|0x8;
outp(ComPortAddr+3,Data);
outp(ComPortAddr+4,0x0a);
outp(ComPortAddr+1,0x01);
disable();
OldAsyncInt=getvect( IntVectNum );
setvect( IntVectNum, AsyncInt );
enable();
maskb=inp(Port8259+1);
if(IntVectNum==0x0c)outp(Port8259+1,maskb&0xef); else outp(Port8259+1,maskb&0xf7); }
static void interrupt far AsyncInt(void) {
disable();
if(CharsInBuf<MaxBufLen)
Buffer[CircIn]=inp(comportaddr);
if(CircIn<MaxBufLen-1) CircIn++;
else CircIn=0;
if(CircIn==CircOut) CircOut++;
else CharsInBuf++;
enable();
outp(Port8259,EofInt);
}
void Restore(void)
{
setvect(intvectnum,OldAsyncInt);
outp(Port8259+1,maskb);
}
int GetCharInBuf(unsigned char *Char) {
int Flag;
Flag=-1;
if(CharsInBuf>0)
{
(*Char)=Buffer[CircOut];
if(CircOut<MaxBufLen-1)CircOut++; else CircOut=0;
CharsInBuf--;
Flag=0;
}
return Flag;
}
int SendChar(unsigned char Char)
{
if((inp(comportaddr+5)&0x20)==0) return -1; outp(comportaddr,Char);
return 0;
}
main()
{
int i,c;
unsigned char InChar;
Init_COM(COM232,COMINT,1200,8,1,0); while(1)
{
if(kbhit())
{if((InChar=getch())==27)break; else while(SendChar(InChar)); }
if(GetCharInBuf(&InChar)==0)
printf("%c",InChar);
}
Restore();
}
接收程序:
#include <dos.h>
#include <fstream.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define RXD 0 //接收
#define TXD 0 //发送
#define LSB 0 //波特率调节低8位
#define MSB 1 //波特率调节高8位
#define IER 1 // 中断起用寄存器
#define IIR 2 //中断标识寄存器
#define LCR 3 //线路控制寄存器
#define MCR 4 //调制解调器控制寄存器 #define LSR 5 //线路状态寄存器
#define MSR 6 //调制解调器状态寄存器 #define IERV 1
#define OUT2 0x08
#define ERTS 2
#define EDTR 1
#define EMPTY 0X20
#define READY 0X30
#define ICREG 0X20
#define IMASKREG 0X21
#define EOI 0X20
#define WAITCOUNT 5000
#define BUFFLEN 2048 //用于存储字符的数组的界 #define ALTE 0X12
#define ALTQ 0X10
#define SER_BAUD_1200 96
#define SER_BAUD_2400 48
#define SER_BAUD_9600 0x0C
#define SER_BAUD_19200 6
#define SER_STOP_1 0 /*/ 1 stop bit per character*/ #define SER_STOP_2 4 /*/ 2 stop bits per character*/ #define SER_BITS_5 0 /*/ send 5 bit characters*/
#define SER_BITS_6 1 /*/ send 6 bit characters*/ #define SER_BITS_7 2 /*/ send 7 bit characters*/ #define SER_BITS_8 3 /*/ send 8 bit characters*/ #define SER_PARITY_NONE 0 /*/ no parity*/ #define SER_PARITY_ODD 8 /*/ odd parity*/ #define SER_PARITY_EVEN 24 /*/ even parity*/ int port; int ComNum; unsigned portaddr; unsigned portf; unsigned int baudtable[]={0x180,0xc0,0x60,0x30,0x18,0x0c,0x06}; unsigned char paritytable[]={0x08,0x18,0x00,0x28,0x38}; unsigned char buffer[BUFFLEN];//recv buf int buffin=0; int buffout=0; int incount=0; int outcount=0; void interrupt(*vect_com)(...); void putb(unsigned char ch)//write a char to the recvbuf 将中断得到的数据写到缓冲区 { int temp; temp=buffin; if(++buffin==BUFFLEN) buffin=0; if(buffin!=buffout) {buffer[buffin]=ch; // printf("bufferin[%d]=%c",buffer[buffin]); // getch(); } else buffin=temp; }; unsigned char getb()//read a char from the recvbuf { if(buffout!=buffin) { if(++buffout==BUFFLEN) buffout=0; //printf("bufferout[%d]=%c",buffout,buffer[buffout]); return(buffer[buffout]); } else return(0xff); };
/*unsigned char sender( unsigned char ch) { outportb(portaddr2+TXD,ch); printf("\nsender outportdata=%c\n",ch); outcount++; return(1); }; */ void interrupt receiver(...) { unsigned char ch; ch=inportb(portaddr+RXD); putb(ch); incount++; //记录接收了多少个数据。 outportb(ICREG,EOI); }; void SerInit(int baud,int configuration) { disable(); outportb(portaddr+LCR,0x80); outportb(portaddr+LSB,baud); outportb(portaddr+MSB,0x00); outportb(portaddr+LCR,configuration); enable(); }; void SerOpen(void) { vect_com=getvect(portf+8); disable(); inportb(portaddr+RXD); inportb(portaddr+MSR); inportb(portaddr+LSR); inportb(portaddr+IIR); outportb(portaddr+IER,IERV); outportb(portaddr+MCR,OUT2|ERTS|EDTR); outportb(IMASKREG,inportb(IMASKREG)&(~(1<<portf))); setvect(portf+8,receiver); enable(); }; void SerClose(void) { disable(); outportb(portaddr+IER,0); outportb(portaddr+MCR,0);
outportb(IMASKREG,inportb(IMASKREG)|(1<<portf));
enable();
setvect(portf+8,vect_com);
};
void Getportaddr(int port)
{
switch (port)
{
case 0: portaddr=0x3F8; break;
case 1: portaddr=0x2F8; break;
case 2: portaddr=0x3E8; break;
case 3: portaddr=0x2E8; break;
}
portf=(port==0)?4:3;
};
void Int()
{
unsigned char key,key2;
port=ComNum-1;
if(peek(0x40,port*2)==0)
{
printf("have no special com .\n");
exit(1);
}
else
{
printf("The used port is :COM%d\n",ComNum);
};
Getportaddr(port); // 得到串口地址
SerInit(SER_BAUD_9600,SER_PARITY_EVEN| SER_BITS_8 | SER_STOP_1); //初始化串口,设置波特率等
SerOpen();
do
{
if(kbhit())
{
key2=getch();
if(key2==27){ break;}
};
key=getb();
if(key!=0xff)
{
printf("%x\t",key);
FILE *fp;
fp=fopen("C:\\Receivedata.dat","ab"); //可选择接收数据的存放文件路径和文件名 if(fp==NULL) printf("File open error!"); // fputc(key,fp); fwrite(&key,sizeof(unsigned char),1,fp); fclose(fp); } }while (key2!=27); SerClose(); // printf("%d char has been received\n",incount); // printf("%d char has been sended\n",outcount); // printf("\nsum=%d \n",sum); } void main()//com1 receive { printf("Please input the receive COMnum:(1~4)\n"); cin>>ComNum; printf("the current com set is:9600,even, data bits 8, stop 1,"); Int(); printf("\n\nOVER\n"); exit(0); }; --------------- 发送文件程序 #include <dos.h> #include <bios.h> #include <stdio.h> #include <math.h> #include <conio.h> #include <graphics.h> #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif #define SER_RBF 0 #define SER_THR 0 #define SER_IER 1 #define SER_IIR 2 #define SER_LCR 3 #define SER_MCR 4 #define SER_LSR 5 #define SER_MSR 6 #define SER_DLL 0 #define SER_DLH 1
#define SER_BAUD_1200 96 #define SER_BAUD_2400 48 #define SER_BAUD_9600 12 #define SER_BAUD_19200 6 #define SER_GP02 8 #define COM_1 0x3F8 #define COM_2 0x2F8 /*/ base port address of port 1*/ #define COM_3 0x3E8 #define COM_4 0x2E8 #define SER_STOP_1 0 /*/ 1 stop bit per character*/ #define SER_STOP_2 4 /*/ 2 stop bits per character*/ #define SER_BITS_5 0 /*/ send 5 bit characters*/ #define SER_BITS_6 1 /*/ send 6 bit characters*/ #define SER_BITS_7 2 /*/ send 7 bit characters*/ #define SER_BITS_8 3 /*/ send 8 bit characters*/ #define SER_PARITY_NONE 0 /*/ no parity*/ #define SER_PARITY_ODD 8 /*/ odd parity*/ #define SER_PARITY_EVEN 24 /*/ even parity*/ #define SER_DIV_LATCH_ON 128 /*/ used to turn reg 0,1 into divisor latch*/ #define PIC_IMR 0x21 /*/ pic's interrupt mask reg.*/ #define PIC_ICR 0x20 /*/ pic's interupt control reg.*/ #define INT_SER_PORT_0 0x0C /*/ port 0 interrupt com 1 & 3*/ #define INT_SER_PORT_1 0x0B /*/ port 0 interrupt com 2 & 4*/ #define SERIAL_BUFF_SIZE 128 /*/ current size of circulating receive buffer*/ void interrupt far (*Old_Isr)(__CPPARGS); /*/ holds old com port interrupt handler*/ char ser_buffer[SERIAL_BUFF_SIZE]; /*/ the receive buffer*/ int ser_end = -1,ser_start=-1; /*/ indexes into receive buffer*/ int ser_ch, char_ready=0; /*/ current character and ready flag*/ int old_int_mask; /*/ the old interrupt mask on the PIC*/ int open_port; /*/ the currently open port*/ int serial_lock = 0; /*/ serial ISR semaphore so the buffer*/ /*/ isn't altered will it is being written*/ /*/ to by the ISR*/ /*-------------写串口-----------------*/ void interrupt far Serial_Isr(__CPPARGS) { serial_lock = 1; ser_ch = inp(open_port + SER_RBF); if (++ser_end > SERIAL_BUFF_SIZE-1) ser_end = 0; ser_buffer[ser_end] = ser_ch; ++char_ready; outp(PIC_ICR,0x20); serial_lock = 0;
} int Ready_Serial() { return(char_ready); } /*--------------读串口--------------*/ int Serial_Read() { int ch; while(serial_lock){} if (ser_end != ser_start) { if (++ser_start > SERIAL_BUFF_SIZE-1) ser_start = 0; ch = ser_buffer[ser_start]; printf("%x",ch); if (char_ready > 0) --char_ready; return(ch); } else return(0); } /*--------------写串口-----------------*/ Serial_Write(char ch) { while(!(inp(open_port + SER_LSR) & 0x20)){} asm cli outp(open_port + SER_THR, ch); asm sti } /*-----------初始化串口---------------*/ Open_Serial(int port_base, int baud, int configuration) { open_port = port_base; disable(); outp(port_base + SER_LCR, SER_DIV_LATCH_ON); outp(port_base + SER_DLL, baud); outp(port_base + SER_DLH, 0); outp(port_base + SER_LCR, configuration); outp(port_base + SER_MCR, SER_GP02); outp(port_base + SER_IER, 1); if (port_base == COM_1 || port_base==COM_3) {
Old_Isr = _dos_getvect(INT_SER_PORT_0); _dos_setvect(INT_SER_PORT_0, Serial_Isr); printf("\nOpening Communications Channel Com Port #1/3...\n"); } else { Old_Isr = _dos_getvect(INT_SER_PORT_1); _dos_setvect(INT_SER_PORT_1, Serial_Isr); printf("\nOpening Communications Channel Com Port #2/4...\n"); } old_int_mask = inp(PIC_IMR); outp(PIC_IMR, (port_base==COM_1) ? (old_int_mask & 0xEF) : (old_int_mask & 0xF7 )); enable(); } /*-------------关闭串口--------------*/ Close_Serial(int port_base) { outp(port_base + SER_MCR, 0); outp(port_base + SER_IER, 0); outp(PIC_IMR, old_int_mask ); if (port_base == COM_1) { _dos_setvect(INT_SER_PORT_0, Old_Isr); printf("\nClosing Communications Channel Com Port #1.\n"); } else { _dos_setvect(INT_SER_PORT_1, Old_Isr); printf("\nClosing Communications Channel Com Port #2.\n"); } } /*-------------发送应用----------------*/ void main(int argc,char *argv[]) { char ch,press; int done=0; FILE *fp; argc=2; //argv[1]="c:\\comfile.c"; if(argc<2) { printf("\nUsage:display filename.wav!!!"); // exit(1); }
if((fp=fopen(argv[1],"r+b"))==NULL)
{
printf("cannot open the file\n");
// exit(0);
}
fseek(fp, 0, SEEK_SET);
Open_Serial(COM_1,SER_BAUD_9600,SER_PARITY_EVEN|
SER_STOP_1);
printf("com:1;bps:9600;parity:even;bits:8;stop bit:1");
printf("press any key to begin sending");
getch();
//Serial_Write(''); //该语句可用于发送单个字符
while(!done&&ch != EOF) //发送文件开始
{
ch = fgetc(fp);
//if(ch==EOF) Serial_Write(27);
Serial_Write(ch);
delay(30);
if (kbhit())
{
press=getch();
if (press==27)
{
Serial_Write(27);
done=1;
}
}
}
Close_Serial(COM_1);
fclose(fp);
}
下面介绍最重要的MFC: SER_BITS_8 |
CWnd:窗口,它是大多数“看得见的东西”的父类(Windows里几乎所有看得见的东西都是一个窗口,大窗口里有许多小窗口),比如视图CView、框架窗口CFrameWnd、工具条CToolBar、对话框CDialog、按钮CButton,etc;一个例外是菜单(CMenu)不是从窗口派生的。 CDocument文档,负责内存数据与磁盘的交互。最重要的是OnOpenDocument(读入),OnSaveDocument(写盘),Serialize(读写)
CView视图,负责内存数据与用户的交互。包括数据的显示、用户操作的响应(如菜单的选取、鼠标的响应)。最重要的是OnDraw(重画窗口),通常用CWnd::Invalidate()来启动它。另外,它通过消息映射表处理菜单、工具条、快捷键和其他用户消息。
CDialog对话框
CWinApp应用程序类。似于C中的main函数,是程序执行的入口和管理者,负责程序建立、消灭,主窗口和文档模板的建立。最常用函数InitInstance():初始化。
CGdiObject及子类,用于向设备文本画图。它们都需要在使用前选进DC。
CPen笔,画线
CBrush刷子,填充
CFont字体,控制文字输出的字体
CBitmap位图
CPalette调色板
CRgn区域,指定一块区域可以用于做特殊处理。
CFile文件。最重要的不外是Open(打开),Read(读入),Write(写)
CString字符串。封装了C中的字符数组,非常实用。
CPoint点,就是(x,y)对
CRect矩形,就是(left,top,right,bottom)
CSize大小,就是(cx,cy)对(宽、高)
includeltreg52hgt包含头文件头文件一般不需改动头文件包含特殊功能寄存器的定义defineucharunsigned…
writeincludeltstdiohgtincludeltstdlibhgtincludeltsystypeshgtincludeltsyssta…
includeltSTC12C5A60S2hgtincludeltdelayhgtdefineXTAL320xx000CUP晶振频…
用Win32API实现串行通信20xx7975618PCVCNETwangxi阅读次数11366给大家说明一下我用word编辑的时…
includeltstdiohgtincludeltstringhgtincludeltdoshgtincludeltstdarghgtinclude…