求文档: <<单片机与PLC的串行通讯>>过幼南

2025-01-06 05:01:40
推荐回答(2个)
回答1:

  #include
  #define uchar unsigned char
  #define uint unsigned int
  #define OLEN 32 // size of serial transmission buffer
  idata unsigned char outbuf[OLEN]; //storage for transmission buffer
  unsigned char idata *outlast=outbuf; //最后由中断传输出去的字节位置
  unsigned char idata *putlast=outbuf; //最后放入发送缓冲区的字节位置
  #define ILEN 12 // size of serial receiving buffer
  idata unsigned char inbuf[ILEN];
  unsigned char idata *inlast=inbuf; //最后由中断进入接收缓冲区的字节位置
  unsigned char idata *getlast=inbuf; //最后取走的字节位置
  bit outbufsign0; //最后一个数据覵BUF发完标志 发完=0
  bit outbufsign; //输出缓冲区非空标志 有=1
  bit inbufsign; //接收缓冲区非空标志 有=1
  bit inbufful; //输入缓冲区满标志 满=1
  #define CR putstring("\r\n") //CR=回车换行
  //延时n x 100ns
  void delay(unsigned char d) //在源程序开头定义是否用w77e58或22。1184M晶振
  {unsigned char j;
  do{ d--;

  //110592 & 89c52
  #ifndef cpuw77e58
  #ifndef xtal221184
  j=21; //k=38 cpu80320 100us k=21 cpu 8052
  #else
  j=42;
  #endif
  #else
  #ifndef xtal221184
  j=38;
  #else
  j=76;
  #endif
  #endif

  do {j--;} while(j!=0);
  }
  while(d!=0);
  }
  //放入一个字节到发送缓冲区

  putbyte(char c)
  {uchar i,j;
  ES=0; //暂停串行中断,以免数据比较时出错?
  //if (outlast=putlast)
  while ( (((outlast-putlast)==2) && (outlast > putlast )) || ((outlast < putlast) && (OLEN-(putlast-outlast)==2)))
  {
  ES=1; c++;c--;ES=0;
  //i=(0-TH1);
  do{i--;j=39; do {j--;}while(j!=0); }while(i!=0); //i=39
  }
  *putlast=c; //放字节进入缓冲区
  putlast++; //发送缓冲区指针加一
  if (putlast==outbuf+OLEN) putlast=outbuf; //指针到了顶部换到底部
  outbufsign=1;
  if (!outbufsign0) {outbufsign0=1;TI=1; } //缓冲区开始为空置为有,启动发送
  ES=1;
  }
  //放一串数据到发送缓冲区
  putbytes(unsigned char *outplace,unsigned char j)
  { int i;
  for(i=0;i>4)&0x0f;
  putbyte(hex_[ch]);
  ch=c&0x0f;
  putbyte(hex_[ch]);
  }
  //从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
  uchar getbyte (void)
  { char idata c ;
  while (!inbufsign); //缓冲区空等待
  ES=0;
  c= *getlast; //取数据
  getlast++; //最后取走的数据位置加一
  inbufful=0; //输入缓冲区的满标志清零
  if (getlast==inbuf+ILEN) getlast=inbuf; //地址到顶部回到底部
  if (getlast==inlast) inbufsign=0; //地址相等置接收缓冲区空空标志,再取数前要检
  //该标志
  ES=1;
  return (c); //取回数据
  }
  //接收一行数据,必须定义放数据串的指针位置和
  //大小
  del=0x7f,backspace=0x08,cr=0x0d,lf=0x0a
  void getline (uchar idata *line, unsigned char n)
  { unsigned char cnt = 0; //定义已接收的长度
  char c;
  do {
  if ((c = getbyte ()) == 0x0d) c = 0x00; //读一个字节,如果是回车换成结束符
  if (c == 0x08 || c == 0x7f) //BACKSPACE 和 DEL 的处理
  { if (cnt != 0) //已经输入退掉一个字符
  {cnt--; //总数目减一
  line--; //指针减一
  putbyte (0x08); //屏幕回显的处理
  putbyte (' ');
  putbyte (0x08);
  }
  }
  else
  {
  putbyte (*line = c); //其他字符取入,回显
  line++; //指针加一
  cnt++; //总数目加一
  }
  }
  while (cnt < n - 1 && c != 0x00 && c!=0x1b); //数目到了,回车或ESC停止
  *line = 0; //再加上停止符0
  }
  //人工输入一个字符到输入缓冲区
  putinbuf(uchar c)
  {ES=0; if(!inbufful)
  {*inlast= c; //放入数据
  inlast++; //最后放入的位置加一
  if (inlast==inbuf+ILEN) inlast=inbuf; //地址到顶部回到底部
  if (inlast==getlast) inbufful=1; //接收缓冲区满置满标志
  inbufsign=1;
  }
  ES=1;
  }
  //串口中断处理
  serial () interrupt 4
  {
  if (TI )
  {
  TI = 0;
  if (outbufsign)
  //if (putlast==outlast) outbufsign=0;
  //else
  {
  SBUF=*outlast; //未发送完继续发送
  outlast++; //最后传出去的字节位置加一
  if (outlast==outbuf+OLEN) outlast=outbuf;//地址到顶部回到底部
  if (putlast==outlast) outbufsign=0; //数据发送完置发送缓冲区空标志
  }
  else outbufsign0=0;
  }
  if (RI)
  {
  RI = 0;
  if(!inbufful)
  {
  *inlast= SBUF; //放入数据
  inlast++; //最后放入的位置加一
  inbufsign=1;
  if (inlast==inbuf+ILEN) inlast=inbuf; //地址到顶部回到底部
  if (inlast==getlast) inbufful=1; //接收缓冲区满置满标志

  }
  }
  }
  //串口初始化0xfd=19200,0xfa=9600,0xf4=4800,0xe8=2400,0xd0=1200
  serial_init ()
  {
  SCON = 0x50; // mode 1: 8-bit UART
  TMOD |= 0x20; // timer 1 mode 2: 8-Bit
  PCON |= 0x80; TH1 = 0xfA;//fa, //baud*2
  // 19200 baud
  TR1 = 1; // timer 1
  ES = 1; REN=1; EA=1; SM2=1; //SM2=1时收到的第9位为1才置位RI标志
  TMOD |=0x01; //th1 auto load 2X8,th0 1X16
  TH0=31; TL0=0; //X 32 =1S
  TR0=1; //ET0=1;

  }
  //测试用主函数

  void main(void)
  {char c;
  idata unsigned char free[16];
  unsigned char idata *freep=free;
  serial_init();

  putstring("jdioptuejls;j;klj");
  delay(10);

  while(1)
  {
  putstring("com is ready! ");
  }
  c=getbyte();
  putbyte(0x20);
  puthex(c);
  switch(c)
  {case 'r':
  putbytes(inbuf,ILEN);
  break;
  case 'g':
  getline(freep,10);
  putbyte(0x20);
  putstring(freep);
  break;
  default:
  putbyte(c);
  // }
  }
  }

回答2:

用485连接起来,单片机用接收中断,PLC用XMT和RCV指令。PLC设置通信方式。