51单片机第15步_串口多机通讯使用CRC8校验

本章重点介绍串口多机通讯使用CRC8校验

数据格式:"$123xxxx*crc8\r\n";

如:"$1234567890ABCDEF*06\r\n"

如:"$1231234567890*31\r\n"

crc8是CRC校验值,为十六进制的ASCII码,不包含'$'和校验值前面的那个'*'

#include <REG51.h>    //包含头文件REG51.h,使能51内部寄存器;

#include <intrins.h>  //包含头文件intrins.h,要放在stdio.h的头文件之前;

//使能函数: _nop_();  相当于汇编的NOP指令;

//使能函数: bit  _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value=1,返回1,否则返回0;

//使能函数: _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向右循环移动n位,然后将其

//值返回;

//相当于汇编的RR A命令;

//使能函数: _iror_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,向右循环移动n位,然后将

//其值返回;

//使能函数: _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向右循环移动n位,然后将

//其值返回;

//使能函数: _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向左循环移动n位,然后将其

//值返回;

//使能函数: _irol_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,向左循环移动n位,然后将

//其值返回;

//使能函数: _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向左循环移动n位,然后将

//其值返回;

//以上的循环左移和循环右移,同C语言的左移和右移是不同的,使用时要小心;

#include <string.h>

#define OSC_FREQ     11059200L

//#define BAUD_115200  256 - (OSC_FREQ/192L)/115200L   //

//#define BAUD_38400   256 - (OSC_FREQ/192L)/38400L    //

#define BAUD_Time 1

#if(BAUD_Time==1)

//若波特率加倍,则使用下面参数;

#define BAUD_57600   256 - (OSC_FREQ/192L)/57600L    //255

#define BAUD_28800   256 - (OSC_FREQ/192L)/28800L    //254

#define BAUD_19200   256 - (OSC_FREQ/192L)/19200L    //253

#define BAUD_14400   256 - (OSC_FREQ/192L)/14400L    //252

#define BAUD_9600    256 - (OSC_FREQ/192L)/9600L     //250

#define BAUD_4800    256 - (OSC_FREQ/192L)/4800L     //244

#define BAUD_2400    256 - (OSC_FREQ/192L)/2400L     //232

#define BAUD_1200    256 - (OSC_FREQ/192L)/1200L     //208

#else

//若波特率不加倍,则使用下面参数;

#define BAUD_9600    256 - (OSC_FREQ/384L)/9600L

#define BAUD_4800    256 - (OSC_FREQ/384L)/4800L

#define BAUD_1200    256 - (OSC_FREQ/384L)/1200L

#endif

#define receive_buffer_size  30

unsigned char receive_buffer[receive_buffer_size];

bit Start_Flag,Receive_End_Flag;

unsigned char next_in;

//unsigned char crc8;

//函数功能:将y的第i_bit位,设置为1;

unsigned char bit_set( unsigned char y,unsigned char i_bit)

{ unsigned char temp;

  temp=1<<i_bit;

  y=temp|y;

  return(y);

}

//函数功能:将y的第i_bit位,设置为0;

unsigned char bit_clear(char y,char i_bit)

{ char temp;

  temp=1<<i_bit;

  temp=~temp;

  y&=temp;

  return(y);

}

//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;

bit bit_test(char test_data,char test_bit)

{ char temp;

  bit bit_value;

  temp=test_data;

  temp=temp>>test_bit;

  if( (temp&0x01)==0x01 ) bit_value=1;

  else bit_value=0;

  return(bit_value);

}

//函数功能:产生8位的CRC校验值;

unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)

{ unsigned char *current_data;

  unsigned char  crc_byte;

  unsigned int  byte_counter;

  unsigned char  bit_counter;

  current_data = ptr;

  crc_byte = *current_data++;

  for(byte_counter=0; byte_counter < (length-1); byte_counter++)

    { for(bit_counter=0; bit_counter < 8; bit_counter++)

        { if( !bit_test(crc_byte,7) )

      {  crc_byte=crc_byte<<1;

    bit_test( *current_data, 7 - bit_counter ) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);

             continue;

            }

          crc_byte <<= 1;

          bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);

          crc_byte ^= pattern;

        }

      current_data++;

    }

  for(bit_counter=0; bit_counter < 8; bit_counter++)

    { if(!bit_test(crc_byte,7))

        { crc_byte <<= 1;

          continue;

        }

      crc_byte <<= 1;

      crc_byte ^= pattern;

    }

  return(crc_byte);

}

//函数功能:将'0'~'9','A'~'F'的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;

unsigned char ASCII_To_HEX(unsigned char ASCII )

{ unsigned char temp;

  if(ASCII<='9') temp=ASCII-'0';

  else temp=ASCII-0x37;

  return(temp);

}

//函数功能:从串口读入一个字符;

char getc()

{ char c;

  while (!RI);

  c = SBUF;

  RI = 0;

  return (c);

}

//函数功能:从串口输出一个字符;

void putc(char c)

{ SBUF=c;

  while (!TI);

  TI = 0;

}

//函数功能:接收和发送中断服务函数;

//数据格式:"$123xxxx*crc8\r\n";

//如:"$1234567890ABCDEF*06\r\n"

//如:"$1231234567890*31\r\n"

//crc8是CRC校验值,为十六进制的ASCII码,不包含'$'和校验值前面的那个'*'

void isr_UART(void) interrupt 4 using 0

{ unsigned char temp,crc8,crc_data;

  if( RI&&(!Receive_End_Flag) ) //处理接收数据;

    { temp=getc(); //从串口接收一个字节;

  receive_buffer[next_in]=temp;

  putc(temp);//调试时,使用;

  temp=next_in; //保存下标值;

  next_in++;    //修改下标值;

  if(temp<3) //比对从机地址是否为"$123"

    { if( Start_Flag )

    { if( (temp==0)&&(receive_buffer[0]!='1') ) next_in=0;

      if( (temp==1)&&(receive_buffer[1]!='2') ) next_in=0;

      if( (temp==2)&&(receive_buffer[2]!='3') ) next_in=0;

}

  else

    { if(receive_buffer[0]=='$') Start_Flag=1;

   next_in=0;

}

}

  else

    { if( (receive_buffer[temp-1]=='\r')&&(receive_buffer[temp]=='\n') ) //接收到"\r\n"

    { crc8=generate_8bit_crc( receive_buffer,temp-4,1); //计算接收到数据的CRC8校验值;

  crc_data=ASCII_To_HEX(receive_buffer[temp-3]);

  crc_data=(crc_data<<4)&0xf0; //获取CRC校验值的高4位值;

  temp=ASCII_To_HEX(receive_buffer[temp-2]); //获取CRC校验值的低4位值;

              crc_data=crc_data+temp; //获取接收到的CRC校验值;

  if(crc8==crc_data) //若CRC校验值正确,则执行下面语句;

    { Receive_End_Flag=1;

}

  next_in=0; //接收完成;

  Start_Flag=0;  //为下次接收起始标志做备;

}

}

      if(next_in>=receive_buffer_size)

    { next_in=0; //接收数据太长,取消接收;

  Start_Flag=0;  //为下次接收起始标志做备;

}

}

}

//函数功能:若接收到的数据有效,则打印出来;

void Print_Receive_data()

{ unsigned char i;

  i=0;   

  if(Receive_End_Flag)

    { while(receive_buffer[i]!='\n')

    { putc(receive_buffer[i]);

  i++;

}

  putc(receive_buffer[i]); //打印'\n';

  Receive_End_Flag=0;

    }

}

//函数功能:初始化串口,设置波特率为9600bps@11.0592MHz,使能接收,使用8位UART;

void Serial_Port_Initialization()

{ PCON = 0x80;

  SCON=0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI

             //SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;

     //REN=1,使能接收;

  TMOD&=0x0f;

  TMOD|= 0x20;

//定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00

      //GATE=0,TR置1便可以启动Timer;GATE=1,TR置1,且INT脚输入高电平,才可以启动Timer;

     //M11:M10=10,选择方式2,8位自动重装载; 

  TH1=BAUD_9600;  //TH1:  reload value for 9600 baud @11.0592MHz;

  TL1=TH1;

  TR1=1;   //启动Timer1;

  TI=0;    //为下次发送做准备;

  RI=0;

  next_in=0;

  Start_Flag=0;

  Receive_End_Flag=0; //将接收完成标志设置为0;

  ES=1; //使能串口接收和发送中断;

  EA=1; //开总中断 

}

//函数功能: Delay 50us

void delay_50us(unsigned char _50us)

{ while(_50us--)

{ _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

  _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

    }

}

void main(void)

{

  Serial_Port_Initialization(); //初始化串口,设置波特率9600bps@11.0592MHz,使能接收,使用8位UART;

  for(;;)

    {  Print_Receive_data();  //若接收到的数据有效,则打印出来;

      delay_50us(20);    //延时1ms;

   }

}

/*

//函数功能:将hex8的低4位(0~9,a~f)转换为'0'~'9','A'~'F'输出;

unsigned char HEX_To_ASCII(unsigned char hex8 )

{unsigned char temp;

 temp=hex8;

 temp=(unsigned char)(temp&0x0f); //求低4位值;

 if(temp<0x0a) temp+=0x30;  //将低4位值(在0~9中)转换为ASCII码;

 else temp+=0x37;           //将低4位值(在a~f中)转换为大写字母的ASCII码;

 return(temp);

}

//函数功能:将'0'~'9','A'~'F'的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;

unsigned char ASCII_To_HEX(unsigned char ASCII )

{ unsigned char temp;

  if(ASCII<='9') temp=ASCII-'0';

  else temp=ASCII-0x37;

  return(temp);

}

//函数功能:将y的第i_bit位,设置为1;

unsigned char bit_set( unsigned char y,unsigned char i_bit)

{ unsigned char temp;

  temp=1<<i_bit;

  y=temp|y;

  return(y);

}

//函数功能:将y的第i_bit位,设置为0;

unsigned char bit_clear(char y,char i_bit)

{ char temp;

  temp=1<<i_bit;

  temp=~temp;

  y&=temp;

  return(y);

}

//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;

bit bit_test(char test_data,char test_bit)

{ char temp;

  bit bit_value;

  temp=test_data;

  temp=temp>>test_bit;

  if( (temp&0x01)==0x01 ) bit_value=1;

  else bit_value=0;

  return(bit_value);

}

//函数功能:产生8位的CRC校验值;

unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)

{ unsigned char *current_data;

  unsigned char  crc_byte;

  unsigned int  byte_counter;

  unsigned char  bit_counter;

  current_data = ptr;

  crc_byte = *current_data++;

  for(byte_counter=0; byte_counter < (length-1); byte_counter++)

    { for(bit_counter=0; bit_counter < 8; bit_counter++)

        { if( !bit_test(crc_byte,7) )

    {

  crc_byte=crc_byte<<1;

  bit_test( *current_data, 7 - bit_counter ) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);

              continue;

            }

          crc_byte <<= 1;

          bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);

          crc_byte ^= pattern;

        }

      current_data++;

    }

  for(bit_counter=0; bit_counter < 8; bit_counter++)

    { if(!bit_test(crc_byte,7))

        { crc_byte <<= 1;

          continue;

        }

      crc_byte <<= 1;

      crc_byte ^= pattern;

    }

  return(crc_byte);

}

//函数功能:将y的第i_bit位,设置为1;调用方式: sbit_set(&x,i);

void bit_set( unsigned char *y,unsigned char i_bit)

{ unsigned char temp;

  temp=1<<i_bit;

  y[0]=temp|y[0];

}

//函数功能:将y的第i_bit位,设置为0;调用方式: sbit_clear(&x,i);

void bit_clear(char *y,char i_bit)

{ char temp;

  temp=1<<i_bit;

  temp=~temp;

  y[0]&=temp;

}

//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;

void bit_test(char test_data,char test_bit,unsigned char *return_value)

{ char temp;

  //bit bit_value;

  temp=test_data;

  temp=temp>>test_bit;   

  if( (temp&0x01)==0x01 ) return_value[0]=1;

  else return_value[0]=0;

  //return(bit_value);

}

//函数功能:产生8位的CRC校验值;

void generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char *return_value )

{ unsigned char tenp_value;

  unsigned char *current_data;

  unsigned char  crc_byte;

  unsigned int  byte_counter;

  unsigned char  bit_counter;

  unsigned char pattern=0x01;

  current_data = ptr;

  crc_byte = *current_data++;

  for(byte_counter=0; byte_counter < (length-1); byte_counter++)

    { for(bit_counter=0; bit_counter < 8; bit_counter++)

        { bit_test( crc_byte,7,&tenp_value );

  //if( !bit_test(crc_byte,7) )

  if(tenp_value==0)

    {

  crc_byte=crc_byte<<1;

  bit_test( *current_data, 7 - bit_counter,&tenp_value );

  //bit_test( *current_data, 7 - bit_counter ) ? bit_set(crc_byte,0) : bit_clear(crc_byte,0);

  if(tenp_value==1) bit_set(&crc_byte,0);

  else bit_clear(&crc_byte,0);

              continue;

            }

          crc_byte <<= 1;

  bit_test( *current_data, 7 - bit_counter,&tenp_value );

          //bit_test(*current_data, 7 - bit_counter) ? crc_byte=bit_set(crc_byte,0) : bit_clear(crc_byte,0);

  if(tenp_value==1) bit_set(&crc_byte,0);

  else bit_clear(&crc_byte,0);

          crc_byte ^= pattern;

        }

      current_data++;

    }

  for(bit_counter=0; bit_counter < 8; bit_counter++)

    { bit_test( crc_byte,7,&tenp_value );

  //if(!bit_test(crc_byte,7))

  if(tenp_value==0)

        { crc_byte <<= 1;

          continue;

        }

      crc_byte <<= 1;

      crc_byte ^= pattern;

    }

  return_value[0]=crc_byte;

  //return(crc_byte);

}

*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/759933.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AIGC】AnimateAnyone:AI赋予静态照片生命力的魔法

摘要&#xff1a; 在人工智能技术的不断进步中&#xff0c;AnimateAnyone项目以其创新性和易用性脱颖而出&#xff0c;成为GitHub上备受瞩目的AI项目之一。由阿里巴巴智能计算研究院开发的这一技术&#xff0c;允许用户通过提供一张静态照片&#xff0c;快速生成动态角色。本文…

SpringBoot(一)创建一个简单的SpringBoot工程

Spring框架常用注解简单介绍 SpringMVC常用注解简单介绍 SpringBoot&#xff08;一&#xff09;创建一个简单的SpringBoot工程 SpringBoot&#xff08;二&#xff09;SpringBoot多环境配置 SpringBoot&#xff08;三&#xff09;SpringBoot整合MyBatis SpringBoot&#xff08;四…

docker安装rocketMq5x以上的版本

1.背景 安装RocketMQ 5.x以上的版本主要是因为新版本引入了许多性能优化、新功能以及对已有特性的增强&#xff0c;这些改进可以帮助提升消息队列系统的稳定性和效率。 1.性能提升&#xff1a;RocketMQ 5.x版本通常包括了对消息处理速度、吞吐量和延迟的优化&#xff0c;使得系…

在Linux (Ubuntu 16) 下安装LabVIEW

用户尝试在Ubuntu 16操作系统上安装LabVIEW&#xff0c;但找不到合适的安装文件来支持Ubuntu。已经下载了运行时文件&#xff0c;并尝试将.rpm包转换为.deb包并安装在Ubuntu上。然而&#xff0c;安装完成后&#xff0c;没有在应用程序中看到LabVIEW的图标。 用户希望能够在Ubu…

Spring MVC中的DispatcherServlet、HandlerMapping和ViewResolver的作用

在Spring MVC框架中&#xff0c;DispatcherServlet、HandlerMapping和ViewResolver是核心组件&#xff0c;它们各自承担着不同的角色和任务&#xff1a; 1.DispatcherServlet&#xff1a;它是Spring MVC生命周期中的前端控制器&#xff0c;负责接收HTTP请求并将它们分发给相应的…

【OpenREALM学习笔记:13】pose_estimation.cpp和pose_estimation.h

UML Class Diagram 图中红色框为头文件中所涉及到的函数、变量和结构体 核心函数 PoseEstimation::process() 其核心作用为执行位姿估计的处理流程&#xff0c;并返回是否在此循环中进行了任何处理。 在这个函数中判断并完成地理坐标的初始化或这地理坐标的更新。 这里需要…

论文阅读_基本于文本嵌入的信息提取

英文名&#xff1a;Embedding-based Retrieval with LLM for Effective Agriculture Information Extracting from Unstructured Data 中文名&#xff1a;基于嵌入的检索&#xff0c;LLM 从非结构化数据中提取有效的农业信息 地址: https://arxiv.org/abs/2308.03107 时间&…

昇思25天学习打卡营第04天|数据集 Dataset

数据是深度学习的基础&#xff0c;高质量的数据输入将在整个深度神经网络中起到积极作用。MindSpore提供基于Pipeline的数据引擎&#xff0c;通过数据集&#xff08;Dataset&#xff09;和数据变换&#xff08;Transforms&#xff09;实现高效的数据预处理。其中Dataset是Pipel…

【linux】网络基础(1)

文章目录 网络基本概念网络的定义网络的类型局域网&#xff08;LAN&#xff09;广域网&#xff08;WAN&#xff09; 网络协议OSI七层模型TCP/IP模型TCP/IP模型的结构 网络传输的基本流程计算机与计算机之间的通信计算机的信息处理封装报头 网络基本概念 网络的定义 1.网络是指…

1.搭建篇——帝可得后台管理系统

目录 前言项目搭建一、搭建后端项目1.初始化项目Maven构建 2.MySQL相关导入sql配置信息 3. Redis相关启动配置信息 4.项目运行 二、 搭建前端项目1.初始化项目2.安装依赖3.项目运行 三、问题 前言 提示&#xff1a;本篇讲解 帝可得后台管理系统 项目搭建 项目搭建 一、搭建后…

【2024-热-办公软件】ONLYOFFICE8.1版本桌面编辑器测评

在今日快速发展的数字化办公环境中&#xff0c;选择一个功能全面且高效的办公软件是至关重要的。最近&#xff0c;我有幸体验了ONLYOFFICE 8.1版本的桌面编辑器&#xff0c;这款软件不仅提供了强大的编辑功能&#xff0c;还拥有众多改进&#xff0c;让办公更加流畅和高效。在本…

DCS-11双位置继电器 DC220V 板前接线带底座 约瑟 JOSEF

系列型号&#xff1a; DCS-11双位置继电器&#xff1b; DCS-12双位置继电器&#xff1b; DCS-13双位置继电器&#xff1b; ​用途 RXMVB2(DCS-10)系列双位置继电器用于需要大容量双稳态触点的工业控制和其它一般控制场合。 特点 体积小&#xff0c;拆装方便&#xff0c;能安…

Halcon 椭圆

一 椭圆 方差的概念: 例1 两人的5次测验成绩如下&#xff1a;X&#xff1a; 50&#xff0c;100&#xff0c;100&#xff0c;60&#xff0c;50 E(X)72&#xff1b;Y&#xff1a; 73&#xff0c; 70&#xff0c; 75&#xff0c;72&#xff0c;70 E(Y)72。平均成绩相同&#xff0c…

[Cloud Networking] OSPF

OSPF 开放式最短路径优先&#xff08;Open Shortest Path First&#xff09;是一种动态路由协议&#xff0c;它属于链路状态路由协议&#xff0c;具有路由变化收敛速度快、无路由环路、支持变长子网掩码和汇总、层次区域划分等优点。 1 OSPF Area 为了适应大型网络&#xff0…

类似李跳跳的软件有什么,强烈推荐所有安卓手机安装!!!

今天阿星分享一款让安卓手机更顺滑的神器——智慧岛。你问我李跳跳&#xff1f;由于大家都知道的原因&#xff0c;那是个曾经让广告无处遁形的神兵利器&#xff0c;可惜现在它已经退休了。不过别担心&#xff0c;智慧岛接过了接力棒&#xff0c;继续为我们的安卓体验保驾护航。…

vue3 全局引入 onMounted, reactive, ref 的插件全局引入

webpack 的引入 npm install -D unplugin-auto-import const AutoImport require(unplugin-auto-import/webpack).default;configureWebpack: {devtool: source-map,module: {rules: [{test: /\.mjs$/,include: /node_modules/,type: javascript/auto}],}, plugins: [Aut…

【C++深度探索】继承机制详解(一)

hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1…

【高中数学/基本不等式】已知:x,y皆为正实数,且2xy+x+6y=6 求:x+2y的最小值

【题目】 已知&#xff1a;x,y皆为正实数&#xff0c;且2xyx6y6 求&#xff1a;x2y的最小值 【解答】 解法一&#xff1a;因为2xyx6y6 可转换为(x3)(2y1)-36 得到(x3)(2y1)9 而x2yx3-32y1-1 (x3)(2y1)-4 >2*根号下[(x3)(2y1)]-4 2*3-4 2 解法二&#xff1a…

Powershell 简易爬虫,提取种子网站的磁力链接

目录 一. 需求二. 分析2.1 思路分析2.2 技术点 三. 代码四. 效果 一. 需求 ⏹有网站如下所示&#xff0c;先要求从按照关键词搜索到的网页中&#xff0c;提取出所有的磁力链接。 二. 分析 2.1 思路分析 打开网页之后&#xff0c;从网页中先提取出所有的标题相关的url然后再打…

sqlmap注入详解

免责声明:本文仅做分享... 目录 1.介绍 2.特点 3.下载 4.帮助文档 5.常见命令 指定目标 请求 HTTP cookie头 HTTP User-Agent头 HTTP协议的证书认证 HTTP(S)代理 HTTP请求延迟 设定超时时间 设定重试超时 设定随机改变的参数值 利用正则过滤目标网址 避免过多的…