⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ser_232.cpp

📁 利用c实现单板机上串口的程序。单板机底层的串口驱动程序。
💻 CPP
字号:
/*
			 LDS-1310 工装测试程序
*/
#include "dos.h"
#include "bios.h"
#include "stdio.h"
#include "time.h"
#include "stdlib.h"

#define BASE_ADDR1    0x320         //基地址
#define BASE_ADDR2    0x340
#define BASE_ADDR3    0x240
#define BASE_ADDR4    0x380
#define RBR           0x0000
#define THR           0x0000
#define DLL           0x0000
#define DLM           0x0001
#define IER           0x0001
#define FCR           0x0002
#define IIR           0x0002
#define LCR           0x0003
#define MCR           0x0004
#define LSR           0x0005
#define MSR           0x0006
#define SCR           0x0007

#define SEND_NUM      2             //串口发送的BYTE数
#define SEND_NUM_MASTER    2
#define SEND_NUM_PC     66


#define I8259 0x21
#define T8259 0xa1

#define IRQ3  3
#define IRQ4  4
#define IRQ7  7
#define IRQ8  0
#define IRQ9  1
#define IRQ10 2
#define IRQ11 3
#define IRQ12 4
#define IRQ13 5
#define IRQ14  6
#define IRQ15  7


#ifdef __cplusplus
	 #define  __CPPARGS...
#else
	 #define __CPPARGS
#endif

void all_deal();
void init_ram();
void init_int();
int  read_peizhi();
void init_com_all();
void init_com1(unsigned int address_port);
void init_com_other(unsigned int address_port);
void test_send_com_all();
void interrupt test_rec_com_all(__CPPARGS);
void test_send_com1(unsigned int address_port,unsigned int port);
void test_send_com_other(unsigned int address_port,unsigned int port);
void test_rec_com1(unsigned int address_port,unsigned int port);
void test_rec_com_other(unsigned int address_port,unsigned int port);
void test_send_com_master(int address_port);
void input_master_buff();
void test_rec_all(int address_port);
void ser_232();
void RestoreCom();
void rec_other();

int com_err_time[16];               //各串口出错次数
unsigned char peizhi[30];         //配置:1--站号,2--波特率,3--数
int state[4];                    //  四个串口状态
int send_buff_master[10];        //主485发送缓存区
int send_point_master;           //主485发送指针
int send_buff[20];               //各子485发送缓存区
int send_point[16];              //各子485发送指针
int rec_point[16];              //各子485接收指针
int rec_buff[16][20];           //各子485接收缓存区

struct  time tnew;
unsigned char sec_old;
int sec_task;
int station_code;
int send_code;                  //向各子485发送的数据
int ser_flag;



void ser_232()
{
int i,k;
unsigned char value,t,t1;
//读配置文件
      if(read_peizhi()==0) {
	  printf("'peizhi.txt' is not exist!");
	  return;
	  }
      init_ram();
      init_int();//中断和串口初始化
       value=0;
      for(;;){
	  if(bioskey(1)){
	      value=bioskey(0);
	      if(value=='?') {
		RestoreCom();
		break;
		}
	   }


	  enable();
	  gettime(&tnew);
	  if(tnew.ti_hund!=sec_old){
	      sec_old=tnew.ti_hund;
	      sec_task++;
		}

	  if(sec_task>=10){                                     // 1秒任务
	      sec_task=0;
	      input_master_buff();                              //填主485缓存区
		    }

	  test_send_com_master(0x320);  //发送主485缓存区数据
	  test_send_com_all();                  //测试发送各串口数据
//	  rec_other();

      }
}

void interrupt (*oldintcom0)(__CPPARGS);
void interrupt (*oldintcom1)(__CPPARGS);
void interrupt (*oldintcom2)(__CPPARGS);
void interrupt (*oldintcom3)(__CPPARGS);


//中断初始化
void init_int()
{
int i;
unsigned char en;
unsigned char MIRQ[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f} ;
//第一块 串口IRQ3
//		en=inp(I8259);
//		en |=~MIRQ[IRQ3];
		delay(1);
		disable();
		oldintcom0 = _dos_getvect(0x0b);
		_dos_setvect(0x0b,test_rec_com_all);
		en = inp(I8259);
		en &= MIRQ[IRQ3];
		outp(I8259,en);

//第二块 串口IRQ4
//		en=inp(I8259);
//		en |=~MIRQ[IRQ4];
		delay(1);
		oldintcom1 = _dos_getvect(0x0c);
		_dos_setvect(0x0c,test_rec_com_all);
		en = inp(I8259);
		en &= MIRQ[IRQ4];
		outp(I8259,en);


//第三块 串口IRQ7
//		en = inp(I8259);
//		en |= ~MIRQ[IRQ7];
		delay(1);
		oldintcom2 = _dos_getvect(0x0f);
		_dos_setvect(0x0f,test_rec_com_all);
		en = inp(I8259);
		en &= MIRQ[IRQ7];
		outp(I8259,en);


//第四块 串口IRQ12
//		en = inp(T8259);
//		en |= ~MIRQ[IRQ12];
		delay(1);
		oldintcom3 = _dos_getvect(0x74);
		_dos_setvect(0x74,test_rec_com_all);
		en = inp(T8259);
		en &= MIRQ[IRQ12];
		outp(T8259,en);
		init_com_all();
		enable();
}


//恢复串口原中断向量
void RestoreCom()
{
	disable();
	_dos_setvect(0x0b,oldintcom0);
	_dos_setvect(0x0c,oldintcom1);
	_dos_setvect(0x0f,oldintcom2);
	_dos_setvect(0x74,oldintcom3);

	enable();
	}


//初始化
void  init_ram()
{
int i;

      for(i=0;i<4;i++){
	  state[i]=0;
	  }
      for(i=0;i<16;i++){
	  send_point[i]=0;                //各CPU发送指针
	  }
      send_buff[0]=0;                     //串口号
      send_buff[1]=1;                     //发送数据
      station_code=1;
      send_code=0x10;
      ser_flag=0;
      input_master_buff();
}


//填主485发送缓存区
void input_master_buff()
{
int i,j;

//接收站号与发送站号是否相同,接收数据与发送数据是否相同,
   if((rec_buff[0][0]==station_code)&&(rec_buff[0][1]==send_code)){
	   printf("OK MASTER REC_STATION%d=%x,",station_code,rec_buff[0][0]);             //打印接收字符
	   printf("%x",rec_buff[0][1]);
	   printf(" error=%x",com_err_time[station_code]);
	   printf("\n");
	   printf("\n");
			}
   else{                                                                        //有一个不等则出错
	  if(ser_flag!=0){
	      printf("Err MASTER REC_STATION%d=",station_code);
	      for(i=0;i<rec_point[0];i++){
		      printf("%x,",rec_buff[0][i]);
			}
	      com_err_time[station_code]++;                     //相应串口接收出错次数+1
	      printf(" error=%x",com_err_time[station_code]);
	      printf("\n");
	      printf("\n");

			}
		    }
   ser_flag=0xaa;
   station_code++;                                              //站号+1
   if(station_code>=4){                               //>串口总数,站号=2
	station_code=1;

	send_code++;
	if(send_code>=0xf0) send_code=0x10;
	 for(i=0;i<16;i++){                                             //清各从485接收缓存区
		for(j=0;j<3;j++){
			 rec_buff[i][j]=0xff;
			}
		 }
	 }

   send_buff_master[0]=station_code;                            //填发送站号
   send_buff_master[1]=send_code;                               //填发送码值
   send_point_master=0;                                         //清主485发送指针
   for(i=0;i<16;i++){                                           //清各从485接收指针
      rec_point[i]=0;
      }

   for(i=0;i<16;i++){                                           //清各从485发送指针
      send_point[i]=0xff;
      }
}


//功能:读配置
//返回:=1读成功  =0读失败
int  read_peizhi()
{
FILE *fp;
unsigned char buffer[30];
int i,k;

    fp=fopen("peizhi.txt","rb");
    if(fp!=NULL){
	  //获得文件名
	  fgets(buffer,10,fp);
	  k=0;
	  peizhi[0]=0;                                   //站号
	  for(i=0;i<10;i++){
	     if((buffer[i]>=0x30)&&(buffer[i]<0x3a)){
		 peizhi[0]=peizhi[0]*10+(buffer[i] & 0x0f);
		 k++;
		  }
	      else{
		  if(k>=1) break;
			}
	      }

	  fgets(buffer,10,fp);
	  k=0;
	  peizhi[1]=0;                           //波特率
	  for(i=0;i<10;i++){
	     if((buffer[i]>=0x30)&&(buffer[i]<0x3a)){
		 peizhi[1]=peizhi[1]*10+(buffer[i] & 0x0f);
		 k++;
		  }
	      else{
		  if(k>=1) break;
			}
	      }
	  fgets(buffer,10,fp);
	  k=0;
	  peizhi[2]=0;                               //四串口卡的个数
	  for(i=0;i<10;i++){
	     if((buffer[i]>=0x30)&&(buffer[i]<0x3a)){
		 peizhi[2]=peizhi[2]*10+(buffer[i] & 0x0f);
		 k++;
		  }
	      else{
		  if(k>=1) break;
			}
	      }

	  fgets(buffer,10,fp);
	  k=0;
	  peizhi[3]=0;                               //以太个数
	  for(i=0;i<10;i++){
	     if((buffer[i]>=0x30)&&(buffer[i]<0x3a)){
		 peizhi[3]=peizhi[3]*10+(buffer[i] & 0x0f);
		 k++;
		  }
	      else{
		  if(k>=1) break;
			}
	      }

	  fgets(buffer,10,fp);
	  k=0;
	  peizhi[4]=0;                               //以太个数
	  for(i=0;i<10;i++){
	     if((buffer[i]>=0x30)&&(buffer[i]<0x3a)){
		 peizhi[4]=peizhi[4]*10+(buffer[i] & 0x0f);
		 k++;
		  }
	      else{
		  if(k>=1) break;
			}
	      }
	  fclose(fp);
	  if((peizhi[1]>12) || (peizhi[1]<1)) peizhi[1]=3;      //波特率超范围
	  return 1;
     }
    else{                                       //读配置文件出错
	return 0;
	    }
}

//初始化各串
void init_com_all()
{
      state[0]=0xaa;                            //置投运标志
      init_com1(0x320);                         //初始化第一犻串口
}


/*baud,8,无,1*/
/*address_port--地址 */
void init_com1(unsigned int address_port)
{
int baud,i,t1;
int value;
      baud=0x180;
      for(i=0;i<peizhi[1]-1;i++){
	    baud=baud/2;
	}
/*串0--4800 8 none 1*/
      value=0x83;
      outportb(address_port+LCR,value);
      value=baud%0x100;
      outportb(address_port+DLL,value);
      value=baud/0x100;
      outportb(address_port+DLM,value);
      value=0x03;
      outportb(address_port+LCR,value);
//      outportb(address_port+IIR,0xff);
      outportb(address_port+MCR,0x08);
  	  value=0x01;
      outportb(address_port+IER,value);                  //允许接受中断

/*其它三个串    */
      for(i=1;i<4;i++){
	  value=0x83;
	  outportb(address_port+i*8+LCR,value);
	  value=baud%0x100;
	  outportb(address_port+i*8+DLL,value);
	  value=baud/0x100;
	  outportb(address_port+i*8+DLM,value);
	  value=0x03;
	  outportb(address_port+i*8+LCR,value);
//	  outportb(address_port+i*8+IIR,0x01);
	  outportb(address_port+i*8+MCR,0x08);
	  value=0x01;
	  outportb(address_port+i*8+IER,value);                  //允许接受中断
      }

}


//主485发送程序
void test_send_com_master(int address_port)
{
int t,aa,i,t1;
	    if(send_point_master<SEND_NUM_MASTER){                //判断是否发送完毕
	      t=inport(address_port+LSR);
	      if((t& 0x20)==0x20){
		  aa=send_buff_master[send_point_master];
		outp(address_port+THR,aa&0xff);
		if(send_point_master==0){
			 printf("If you input'?',Quit\n");
			 printf("Mastersend=");                 //显示发送字符
			 for(i=0;i<SEND_NUM_MASTER;i++){
				printf("%x,",send_buff_master[i]);
				}
			 printf("\n");  //一个命令发送完
			 }
		   send_point_master++;                          //发送指针+1
		      }
		}
}

//各从485发送程序
void test_send_com_all()
{
     test_send_com1(BASE_ADDR1,0);                      //串口一发送程序
}

//address_port--口地址,port--口号
void test_send_com1(unsigned int address_port,unsigned int port)
{
int t,i,j;
int aa;

      for(i=1;i<4;i++){
	  if(send_point[4*port+i]<SEND_NUM){
	      rec_point[4*port+i]=0;
	      t=inport(address_port+i*8+LSR);
	      if((t& 0x20)==0x20){
		  aa=rec_buff[4*port+i][send_point[4*port+i]];
		  send_point[4*port+i]++;                       //发送指针+1
		  outp(address_port+i*8+THR,aa);
		  if(send_point[4*port+i]==SEND_NUM){
			 printf("station%d send=",4*port+i);             //显示发送字符
			 for(j=0;j<SEND_NUM;j++) printf("%x,",rec_buff[4*port+i][j]);             //显示发送字符
			 printf("\n");
			   }
		      }
		}
	  }

}

//各串口接收程序
void interrupt test_rec_com_all (__CPPARGS)
{
      disable();
      test_rec_all(BASE_ADDR1);                         //主485接收程序
      test_rec_com1(BASE_ADDR1,0);                      //串口一从485接收程序
      rec_other();
      outp(0x20,0x20);                                  // 串口中断结束
      outp(0xa0,0x20);
      enable();
}

//主485接收程序
void test_rec_all(int address_port)
{
int t;
int aa;

      t=inport(address_port+LSR);
      if((t & 01)){
	    aa=inport(address_port+RBR) & 0xff;
	    if(aa>0xf0) return;
	    rec_buff[0][rec_point[0]]=aa;
	    rec_point[0]++;
	    }
} 

//串口一从485接收程序
// 输入:address_port--口起始地址,port--串口号
void test_rec_com1(unsigned int address_port,unsigned int port)
{
int i,t;
int aa;

       for(i=1;i<4;i++){
	      t=inport(address_port+8*i+LSR);
	      if((t & 01)){
		  aa=inport(address_port+8*i+RBR)&0xff;
		  if(aa>0xf0) continue;
		  if(rec_point[4*port+i]==0){
			if(aa!=(4*port+i)){
			    continue;
			       }
			    }
		  rec_buff[4*port+i][rec_point[4*port+i]]=aa;
		  rec_point[4*port+i]++;
		  if(rec_point[4*port+i]>=SEND_NUM_MASTER){
			send_point[4*port+i]=0;
			    }
			}
	      }
}

void rec_other()    //对硬中断时没有响应的采用扫描方式(软中断)接收。
{int i0,i1,i2,i3;
 i0=inport(0x320+LSR)&0x01;
 i1=inport(0x328+LSR)&0x01;
 i2=inport(0x330+LSR)&0x01;
 i3=inport(0x338+LSR)&0x01;
 if(i0||i1||i2||i3)
   test_rec_com_all();
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -