当前位置: 代码迷 >> C语言 >> [求助]高手请进!!
  详细解决方案

[求助]高手请进!!

热度:320   发布时间:2005-01-20 10:49:00.0
[求助]高手请进!!
请教高手,如何用c或者c++编写一个程序进行串口通信(单片机与pc机)。

[此贴子已经被作者于2005-1-20 10:50:40编辑过]


搜索更多相关的解决方案: 单片机  串口  pc机  

----------------解决方案--------------------------------------------------------

#include <stdio.h> #include <bios.h> void main(void) { char i=0,title[]="HELLO"; unsigned status; status=_bios_serialcom(_COM_INIT,0,_COM_9600|_COM_CHR8|_COM_STOP1|_COM_NOPARITY); if(status &0x100) while(title[i]) { _bios_serialcom(_COM_SEND,0,title[i]); putchar(title[i]); i++; } } 这是发送的,很简单!!!不过不系统(完善)!! #include <stdio.h> #include <dos.h> #include <bios.h> #include <conio.h> int init_serialport(int base, int dl, int lcr, int ier); void interrupt int_COMM(...); void interrupt (*old_int_COMM)(...); //串口一中的各各控制端口(串口对应的并不是只一个端口而是连续的几个端口,它们分别表示不同的操作) #define RBR_PORT 0x00 /*** receiver buffer register ***/ #define THR_PORT 0x00 /*** transmitter holding register ***/ #define DLL_PORT 0x00 /*** divisor latch (lsb) ***/ #define DLM_PORT 0x01 /*** divisor latch (msb) ***/ #define IER_PORT 0x01 /*** interrupt enable register ***/ #define IIR_PORT 0x02 /*** interrupt id register ***/ #define LCR_PORT 0x03 /*** line control register ***/ #define MCR_PORT 0x04 /*** modem control register ***/ #define LSR_PORT 0x05 /*** line status register ***/ #define MSR_PORT 0x06 /*** modem status register ***/ int gkey;//用来标志是否接收到数据 char key;//记录接受到什么数据 void main(void) { int base,dl,lcr,ier; int mask_val0,mask_val1; base=0x3f8; dl=3; lcr=(_COM_CHR8|_COM_EVENPARITY|_COM_STOP1); ier=3; init_serialport(base,dl,lcr,ier);//这个设置没有问题!!! old_int_COMM=getvect(0x0C); mask_val0=inportb(0x21);//为什么???? mask_val1=inportb(0xa1); clrscr(); disable(); setvect(0x0C,int_COMM); while(!(0x40 & inportb(0x3f8+LSR_PORT))); outportb(0x3f8,'a'); outportb(0xa1,0);//可能有问题!!!!! outportb(0x21,0); enable();

while(bioskey(1)==0) { if(gkey==1) { sound(400); delay(100); nosound(); printf("%c",key); gkey=0; } } disable(); setvect(0x0c,old_int_COMM); outport(0x21,mask_val0); outport(0xa1,mask_val1); enable(); } int init_serialport(int base, int dl, int lcr, int ier) { outp(base+LCR_PORT,0x80);//寄存器3,允许改变波特率 outp(base+DLL_PORT,dl&0x00ff);//寄存器8,波特率除数锁存低字节为dl,波特率为115200/dl outp(base+DLM_PORT,dl>>8);//寄存器8,高位锁存为0 outp(base+LCR_PORT,lcr);//寄存器3,改变奇偶校验,数据位,和停止位 outp(base+MCR_PORT,0x08);//开中断 outp(base+IER_PORT,ier);//寄存器1,每次从端口接受(发送)发生一次中断。 return 0; } void interrupt int_COMM(...) { unsigned i; i=inportb(0x3f8+0x02);

if (i&0x04) { //recieved ready //printf("a"); gkey=1; key=inportb(0x3f8); } outportb(0x20,0x20); } //串口一接收数据 这是接收的,不过要看懂有点难度,因为有些东西是和硬件有关的!!!


----------------解决方案--------------------------------------------------------
还有记住在新的中断程序中不可以用有关DOS重载(具体是什么我也不明白)的函数(为什么《C语言高级程序设计》中有,没记住!),所以                  printf()函数不可以直接的写在中断程序中的。

[此贴子已经被作者于2005-1-20 17:23:03编辑过]



----------------解决方案--------------------------------------------------------
下位机的程序呢?

要求能中断接收和回送收到的数据!
----------------解决方案--------------------------------------------------------

我毕业设计中的演示软件: 你可以分析一下: #include <dos.h> #include <bios.h> #include <stdio.h> #include <math.h> #include <conio.h> #include <sys/timeb.h> #include <stdlib.h>

#ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif /* registers in UART */ #define k_F1 15104 /* 键盘码用于键盘扫描*/ #define k_F2 15360 #define k_y 5497 #define k_Y 5465 #define k_esc 283

#define SER_RBF 0 /* the read buffer*/ #define SER_THR 0 /* the write buffer*/ #define SER_IER 1 /* the int. enable register*/ #define SER_IIR 2 /* the int. identification register*/ #define SER_LCR 3 /* control data config. and divisor latch*/ #define SER_MCR 4 /* modem control reg.*/ #define SER_LSR 5 /* line status reg.*/ #define SER_MSR 6 /* modem status of cts, ring etc.*/ #define SER_DLL 0 /* the low byte of baud rate divisor*/ #define SER_DLH 1 /* the hi byte of divisor latch*/

/* bit patterns for control registers */

#define SER_BAUD_1200 96 /*baud rate divisors for 1200 baud - 19200*/ #define SER_BAUD_2400 48 #define SER_BAUD_9600 12 #define SER_BAUD_19200 6

#define SER_GP02 8 /* enable interrupt */

#define COM_1 0x3F8 /* base port address of port 0*/ #define COM_2 0x2F8 /* base port address of port 1*/

#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*/

unsigned 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*/ int flagcom; int total[8];

void interrupt far Serial_Isr(__CPPARGS) { /*// this is the ISR (Interrupt Service Routine) for the com port. It is very // simple. When it gets called, it gets the next character out of the receive // buffer register 0 and places it into the software buffer. Note: C takes care // of all the register saving and house work. Cool huh!*/ serial_lock = 1; /*/ lock out any other functions so the buffer doesn't get corrupted*/ ser_ch = inp(open_port + SER_RBF); /*/ place character into next position in buffer*/ if(++ser_end > SERIAL_BUFF_SIZE-1) ser_end = 0; /*/ wrap buffer index around*/ ser_buffer[ser_end] = ser_ch; /*/ move character into buffer*/ ++char_ready; outp(PIC_ICR,0x20); /*/ restore PIC*/ serial_lock = 0; /*/ undo lock*/ }

int Ready_Serial() { /*/ this functions returns true if there are any characters waiting and 0 if the buffer is empty*/ return(char_ready); }

int Serial_Read() { /*/ this function reads a character from the circulating buffer and returns it to the caller*/ int ch; while(serial_lock){} /*/ wait for isr to end*/ if (ser_end != ser_start) /*/ test if there is a character(s) ready in buffer*/ { if(++ser_start > SERIAL_BUFF_SIZE-1) ser_start = 0; /*/ wrap buffer index if needed*/ ch = ser_buffer[ser_start]; /*/ get the character out of buffer*/ if (char_ready > 0) --char_ready; /*/ one less character in buffer now*/ return(ch); /*/ send data back to caller*/ } /*/ end if a character is in buffer*/ else return 0x00; /*/ buffer was empty return a NULL i.e. 0*/ }

void Serial_Write(unsigned char ch) { /*/ this function writes a character to the transmit buffer, but first it // waits for the transmit buffer to be empty. note: it is not interrupt // driven and it turns of interrupts while it's working*/ while(!(inp(open_port + SER_LSR) & 0x20)) {} /*/ wait for transmit buffer to be empty*/ asm cli /*/ turn off interrupts for a bit*/ outp(open_port + SER_THR, ch); /*/ send the character*/ asm sti /*/ turn interrupts back on*/ }

void Open_Serial(int port_base, int baud, int configuration) { /*/ this function will open up the serial port, set it's configuration, turn // on all the little flags and bits to make interrupts happen and load the // ISR*/ open_port = port_base; /* save the port for other functions*/ outp(port_base + SER_LCR, SER_DIV_LATCH_ON); /* first set the baud rate. turn on divisor latch registers*/ outp(port_base + SER_DLL, baud); /* send low and high bytes to divsor latches*/ outp(port_base + SER_DLH, 0); outp(port_base + SER_LCR, configuration); /* set the configuration for the port*/ outp(port_base + SER_MCR, SER_GP02); /* enable the interrupts*/ outp(port_base + SER_IER, 1); /*/ hold off on enabling PIC until we have the ISR installed*/ if (port_base == COM_1) { Old_Isr = getvect(INT_SER_PORT_0); setvect(INT_SER_PORT_0, Serial_Isr); } else { Old_Isr = getvect(INT_SER_PORT_1); setvect(INT_SER_PORT_1, Serial_Isr); } old_int_mask = inp(PIC_IMR); /* enable interrupt on PIC*/ outp(PIC_IMR, (port_base==COM_1) ? (old_int_mask & 0xEF) : (old_int_mask & 0xF7 )); }

void Close_Serial(int port_base) { /* this function closes the port which entails turning off interrupts and // restoring the old interrupt vector*/ outp(port_base + SER_MCR, 0); /*/ disable the interrupts*/ outp(port_base + SER_IER, 0); outp(PIC_IMR, old_int_mask ); /* reset old isr handler*/ if (port_base == COM_1) { setvect(INT_SER_PORT_0, Old_Isr); } else { setvect(INT_SER_PORT_1, Old_Isr); } }

void delayx(int clicks) { unsigned int far *clock=(unsigned int far*)0x0000046cL; unsigned int now; now=*clock; while(abs(*clock-now)<clicks){} }

int connect_com(void) { unsigned char ch=0x00; unsigned char askmcu=0x66; int flag1; struct timeb tsend,tack; flag1=0; printf("\n Now checking com,Waiting..."); ftime(&tsend); while(!flag1) { Serial_Write(askmcu); delayx(1); ch=Serial_Read(); if(ch==0x66) { flag1=1;} else { ftime(&tack); if((tack.time-tsend.time)>10) flag1=2; } } if(flag1==1) { printf("\nConnected!\n"); return 1; } else { printf("\nTime out!\n"); return 0; } }

void welcome(void) {

unsigned char ask1; clrscr();

printf("\n\n\n Welcome to Serial Demo by YangShuo!\n\n\n"); printf("\n First you must input Serial No.(1:com1,2:com2):"); scanf("%d%*c",&flagcom); while(flagcom!=1&&flagcom!=2) scanf("%d%*c",&flagcom); if(flagcom==1) Open_Serial(COM_1,SER_BAUD_9600,SER_PARITY_NONE | SER_BITS_8 | SER_STOP_1); else Open_Serial(COM_2,SER_BAUD_9600,SER_PARITY_NONE | SER_BITS_8 | SER_STOP_1); clrscr();

printf("\n\n Press anykey to check com\n"); getch(); while(!connect_com()) { printf("\nSorry! Can't connect to mcu! Retry?(n/N:exit,other:continue):"); ask1=getch(); if(ask1=='n'||ask1=='N') { printf("\n\nProgram Exit!"); exit(1); } }

}

void draw_adc(void) { int i; window(1,1,80,25); textbackground(0); clrscr(); printf("\n\n\n\n\n "); for(i=0;i<8;i++) { printf(" ADC_%i",i+1); } printf("\nData: \nTotal: "); }

void mcu_set(void) { int i; unsigned char td,ts; int keyid; int flag_1=1,flag_2;

printf("\n Are you sure to change time?"); while(flag_1) { if(bioskey(1)) { keyid=bioskey(0); flag_1=0; if(keyid==k_Y||keyid==k_y) flag_2=1; else flag_2=0; } } if(flag_2) { printf("\n\n Input td and ts:"); scanf("%d %d",&td,&ts); Serial_Write(td); delay(1); Serial_Write(ts); } draw_adc(); ser_end=ser_start; for(i=0;i<8;i++) total[i]=0;

} void put_n_win(int i,unsigned char d,int t) { window(12+8*i,7,18+8*i,8);

clrscr(); cprintf("%i",d); gotoxy(1,2); cprintf("%i",t); }

void main(void) {

int i; int keyid; int flag_1=1; int flag_fn=1; unsigned char num; unsigned char rch; welcome(); for(i=0;i<8;i++) total[i]=0; draw_adc(); sleep(1); ser_end=ser_start; while(flag_1) { if(bioskey(1)) { keyid=bioskey(0); switch(keyid) { case k_F1: flag_fn=1; break; case k_F2: flag_fn=2; break; case k_esc: flag_1=0; break; } } if(flag_1&&flag_fn==1) mcu_set(),flag_fn=2; if(flag_1&&flag_fn==2) { rch=Serial_Read(); if(rch!='\0') { num=rch; ++total[num-1]; rch=Serial_Read(); put_n_win(num-1,rch,total[num-1]); } }

} if(flagcom==1) Close_Serial(COM_1); else Close_Serial(COM_2); printf("\n\n\n\n\n Thank you used! (By Yang Shuo!)\n"); sleep(2); }


----------------解决方案--------------------------------------------------------
对于上面的程序是我的毕业设计(基于单片机的数据采集系统)中的通信演示程序,可以在tc下运行,串口的操作次序为:
首先:调用Open_Serial()函数打开串口,它具体的调用方法看看程序就知道了。
然后,就可以用Serial_Read()(从串口读数据)和Serial_Write()(向串口写数据)这两个函数对单片机操作了。
最后,调用Close_Serial()函数关闭串口。
所以你只需要弄明白Open_Serial(),Serial_Read(),Serial_Write()和Close_Serial()这四个函数就可以了。
上面的程序包含了完善了超时检测,从连等功能
----------------解决方案--------------------------------------------------------
  相关解决方案