用户工具

站点工具


icore4t_45

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
icore4t_45 [2020/09/26 19:46]
zgf 创建
icore4t_45 [2022/04/01 10:54] (当前版本)
sean
行 1: 行 1:
 +|  **银杏科技有限公司旗下技术文档发布平台** ​ ||||
 +|技术支持电话|**0379-69926675-801**|||
 +|技术支持邮件|Gingko@vip.163.com|||
 +^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
 +|  V1.0  |  2020-9-26 ​ |  zgf  |  初次建立 ​ | 
  
 +===== 实验四十五:Modbus TCP通信实验——电源监控 =====
  
-实验四十五:Modbus TCP通信实验——电源监控 +==== 一、 实验目的与意义 ​==== 
-一、 实验目的与意义 + 
-1、 了解Modbus TCP通讯协议 +  ​- ​了解Modbus TCP通讯协议 
-2、 了解Modbus TCP与TCP协议的关系 +  ​- ​了解Modbus TCP与TCP协议的关系 
-3、 掌握Modbus Poll的使用方法 +  ​- ​掌握Modbus Poll的使用方法 
-4、 掌握KEIL MDK 集成开发环境使用方法 +  ​- ​掌握KEIL MDK 集成开发环境使用方法 
-二、 实验设备及平台 +==== 二、 实验设备及平台 ​==== 
-1、 iCore4T 双核心板及底板 + 
-2、 JLINK(或相同功能)仿真器 +  - iCore4T 双核心板及底板 
-3、 以太网通讯线缆 +  ​- ​JLINK(或相同功能)仿真器 
-4、 Keil MDK 开发平台 +  ​- ​以太网通讯线缆 
-5、 装有WIN XP(及更高版本)系统的计算机 +  ​- ​Keil MDK 开发平台 
-三、 实验原理 +  ​- ​装有WIN XP(及更高版本)系统的计算机 
-1. Modbus _TCP简介 +==== 三、 实验原理 ​==== 
-Modbus通信协议由Modicon公司于1979年发明的,是全球最早用于工业现场的总线规约。它是一种主从通讯方式,采用服务器和客户机的模式记性通讯。Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本,其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三种。本实验主要针对Modbus TCP进行的一个数据通讯实验。 + 
-Modbus TCP协议基于TCP协议实现,其数据帧包含于TCP数据之中,本文以数据读取及其应答为例对Modbus TCP进行读取。数据读取请求报文格式如表1所示。 +=== 1.Modbus _TCP简介 ​=== 
-表1 Modbus TCP数据读取请求报文 + 
-事务处理标识 协议标识 报文长度 设备标识 功能码 起始地址 寄存器数量 +  ​* ​Modbus通信协议由Modicon公司于1979年发明的,是全球最早用于工业现场的总线规约。它是一种主从通讯方式,采用服务器和客户机的模式记性通讯。Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本,其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三种。本实验主要针对Modbus TCP进行的一个数据通讯实验。 
-2byte 2byte 2byte 1byte 1byte 2 byte 2 byte +  ​* ​Modbus TCP协议基于TCP协议实现,其数据帧包含于TCP数据之中,本文以数据读取及其应答为例对Modbus TCP进行读取。数据读取请求报文格式如表1所示。 
-事务处理标识符:两个字节,一般每次通讯后将加1,从而区别不同的通讯数据报文。 +  ​* ​表1 Modbus TCP数据读取请求报文 
-协议标识符:两个字节,Modbus TCP标识符为0x0000。 + 
-数据长度:两个字节,标识后面的数据量的大小,数据长度以字节为单位。 +|事务处理标识 |协议标识 |报文长度 |设备标识 |功能码 |起始地址 |寄存器数量| 
-设备标识:用以标识连接在串行线或者网络上的远程服务端的地址。 +|2byte |2byte |2byte |1byte |1byte |2 byte |2 byte
-功能码:一般为读取的寄存器的类型。 + 
-起始地址:寄存器的起始地址。 +  ​* ​事务处理标识符:两个字节,一般每次通讯后将加1,从而区别不同的通讯数据报文。 
-寄存器数量:要读取寄存器的数量。 +  ​* ​协议标识符:两个字节,Modbus TCP标识符为0x0000。 
-数据读取应答报文格式如表2所示。 +  ​* ​数据长度:两个字节,标识后面的数据量的大小,数据长度以字节为单位。 
-表2 Modbus TCP数据读取应答报文 +  ​* ​设备标识:用以标识连接在串行线或者网络上的远程服务端的地址。 
-事务处理标识 协议标识 报文长度 设备标识 功能码 数据长度 数据 +  ​* ​功能码:一般为读取的寄存器的类型。 
-2byte 2byte 2byte 1byte 1byte 1byte n byte +  ​* ​起始地址:寄存器的起始地址。 
-事务处理标识符:两个字节,与请求标识一致。 +  ​* ​寄存器数量:要读取寄存器的数量。 
-协议标识符:两个字节,与请求标识一致。 + 
-数据长度:两个字节,指示后面的数据量的大小,数据长度以字节为单位。 +  * 数据读取应答报文格式如表2所示。 
-设备标识:用以标识连接在串行线或者网络上的远程服务端的地址。 +  ​* ​表2 Modbus TCP数据读取应答报文 
-功能码:一般为读取的寄存器的地址,与请求标识一致。 + 
-数据长度:传输的数据长度。 +|事务处理标识 |协议标识 |报文长度 |设备标识 |功能码 |数据长度 |数据| 
-数据:寄存器的数据。 +|2byte |2byte |2byte |1byte |1byte |1byte |n byte| 
-四、 实验程序 + 
-本实验主要基于TCP通讯和ADC电源监控两部分实现,本文对这两个方面不做过多描述。 +  * 事务处理标识符:两个字节,与请求标识一致。 
-1. 主函数 +  ​* ​协议标识符:两个字节,与请求标识一致。 
- +  ​* ​数据长度:两个字节,指示后面的数据量的大小,数据长度以字节为单位。 
 +  ​* ​设备标识:用以标识连接在串行线或者网络上的远程服务端的地址。 
 +  ​* ​功能码:一般为读取的寄存器的地址,与请求标识一致。 
 +  ​* ​数据长度:传输的数据长度。 
 +  ​* ​数据:寄存器的数据。 
 +==== 四、 实验程序 ​==== 
 + 
 +  * 本实验主要基于TCP通讯和ADC电源监控两部分实现,本文对这两个方面不做过多描述。 
 +1.主函数 
 +<code c> 
 +int main(void) 
 +
 +  /* USER CODE BEGIN 1 */ 
 + int cnt; 
 + short data; 
 +  /* USER CODE END 1 */ 
 +  /*MCU Configuration------------------------------------*/​  
 + ​ HAL_Init();​ 
 +  /* USER CODE BEGIN Init */ 
 + 
 +  /* USER CODE END Init */ 
 +  /* Configure the system clock */ 
 + ​ SystemClock_Config();​ 
 +  /* USER CODE BEGIN SysInit */ 
 + i2c.initialize();​ 
 + axp152.initialize();​ 
 + axp152.set_dcdc1(3500);//​[ARM & FPGA BK1/2/6 &​OTHER] 
 + axp152.set_dcdc2(1200);//​[FPGA INT & PLL D] 
 + axp152.set_aldo1(2500);//​[FPGA PLL A] 
 + axp152.set_dcdc4(3300);//​[POWER_OUTPUT] 
 + axp152.set_dcdc3(3300);//​[FPGA BK4][Adjustable] 
 + axp152.set_aldo2(3300);//​[FPGA BK3][Adjustable] 
 + axp152.set_dldo1(3300);//​[FPGA BK7][Adjustable] 
 + axp152.set_dldo2(3300);//​[FPGA BK5][Adjustable] 
 +  /* USER CODE END SysInit */ 
 + 
 +  /* Initialize all configured peripherals */ 
 +  MX_GPIO_Init();​ 
 +MX_ADC1_Init();​ 
 +  MX_ADC3_Init();​ 
 +  MX_ETH_Init();​ 
 + 
 +  /* USER CODE BEGIN 2 */ 
 +//​LWIP初始化 
 +NETMPU_Config();​ 
 +lwip.initialize();​ 
 +eth_tcps.initialize();​ 
 + /* USER CODE END 2 */ 
 + 
 + /* Infinite loop */ 
 +  /* USER CODE BEGIN WHILE */ 
 +  while (1) 
 +  { 
 +    /* USER CODE END WHILE */ 
 + 
 +    /* USER CODE BEGIN 3 */ 
 + if((cnt ++ / 800000) % 2){ 
 + LED_RED_ON;​ 
 + }else{ 
 + LED_RED_OFF;​ 
 +
 + lwip.periodic_handle();​ 
 +   //​根据定时器计数标志,每隔一秒,读取一次ADC的值 
 + if(adc_read_flag ==1) 
 +
 + adc_read_flag = 0; 
 + my_adc.read(0);​ 
 +                my_adc.read_mux();​ 
 +
 +  
 + //​将ADC采集的计算值,放大1000倍便于观察数据的正确性。计算公式请参考adc部分例程。 
 + data = my_adc.value[0]*6000;​ 
 + hold_reg[0] = data >> 8; 
 + hold_reg[1] = data & 0xff; 
 + 
 + data = my_adc.value[1] * 2000; 
 + hold_reg[2] = data >> 8; 
 + hold_reg[3] = data & 0xff; 
 +  
 + data = my_adc.value[2]*2000;​ 
 + hold_reg[4] = data >> 8; 
 + hold_reg[5] = data & 0xff; 
 + 
 + data = my_adc.value[3]*2000;​ 
 + hold_reg[6] = data >> 8; 
 + hold_reg[7] = data & 0xff; 
 + 
 + data = my_adc.value[4]*2000;​ 
 + hold_reg[8] = data >> 8; 
 + hold_reg[9] = data & 0xff; 
 +  
 + data = my_adc.value[5]*500;​·· 
 + hold_reg[10] = data >> 8; 
 + hold_reg[11] = data & 0xff; 
 +  
 + data = my_adc.value[6]*1000;​ 
 + hold_reg[12] = data >> 8; 
 + hold_reg[13] = data & 0xff; 
 +  
 + data = my_adc.value[7]*2000;​ 
 + hold_reg[14] = data >> 8; 
 + hold_reg[15] = data & 0xff; 
 +  
 + data = my_adc.value[8]*2000;​ 
 + hold_reg[16] = data >> 8; 
 + hold_reg[17] = data & 0xff; 
 +  
 + if(eth_tcps.receive_ok_flag == 1){ 
 + eth_tcps.receive_ok_flag = 0; 
 + modbus_tcp.process(eth_tcps.receive_buffer);​ 
 +
 +  } 
 +  /* USER CODE END 3 */ 
 +
 + 
 +</​code>​
    
 +2.TCP数据发送函数
 +  * 基于TCP中的服务器代码数据发送函数进行函数封装,设计一个发送指定数量数据的函数。
 +<code c>
 +int send(struct tcp_pcb *tpcb,​unsigned char *data,int len)
 +{
 + int ret_err;
 + struct tcp_server_struct *es; 
 + memcpy(eth_tcps.send_buffer,​data,​len);​
 + es = tpcb->​callback_arg;​
 + if(es != NULL){ ​ //​连接处于空闲可以发送数据
 + es->p = pbuf_alloc(PBUF_TRANSPORT,​len,​PBUF_POOL);//​申请内存 ​
 + pbuf_take(es->​p,​(char*)eth_tcps.send_buffer,​len);//​将eth_tcps.send_buffer[]中的数据拷贝到es->​p_tx中
 + tcp_server_senddata(tpcb,​es);​  ​       //​将eth_tcps.send_buffer[]里面复制给pbuf的数据发送出去
 + if(es->​p)pbuf_free(es->​p);​ //​释放内存
 + ret_err=ERR_OK;​
 + }else{
 + tcp_abort(tpcb);​ //​终止连接,​删除pcb控制块
 + ret_err=ERR_ABRT;​
 + }
 + return ret_err;
 +}
 +
 +</​code> ​
    
-2. TCP数据发送函数 +3.Modbus TCP协议处理 
-基于TCP中的服务器代码数据发送函数进行函数封装,设计一个发送指定数量数据的函数。 +  ​* ​Modbus TCP的协议处理由多个子函数组成,函数代码如下。 
-  +<code c> 
-  +int err; 
-3. Modbus TCP协议处理 +char discrete_input[32] = {0x55,​0x55,​0x55}; ​         
-Modbus TCP的协议处理由多个子函数组成,函数代码如下。 +char coil[32] = {0x55,​0x55,​0x55}; ​                   
-  +char input_reg[20] = {0,1,0,2,0,3,0,4,0,5,0,6,​0,​7,​0,​8,​0,​9,​0,​10};  ​ 
-  +char hold_reg[512] = {0x01,​0x02,​0x03};​
-  +
-  +
-  +
-  +
-  +
-  +
-五、 实验步骤 +
-1、 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连); +
-2、 把iCore4T通过以太网线与计算机相连,为iCore4T供电; +
-3、 设置电脑IP地址(见附录1); +
-4、 打开Keil MDK 开发环境,并打开本实验工程; +
-5、 烧写程序到iCore4T上; +
-6、 打开Modbus Poll软件建立连接(见附录2),读取hold寄存器中的数据值,观察核心板返回的数据值。 +
-六、 实验现象 +
-Modbus Poll软件可看到核心板电源数据的检测值。 +
- +
  
 +//​--------------------------- Function --------------------------//​
 +static int process(unsigned char *modbus_recvbuf)
 +{
 + unsigned char receive_buffer_temp[100];​
 + memcpy(receive_buffer_temp,​modbus_recvbuf,​12);​
 +     ​memset(modbus_recvbuf,​0,​12);​
 + mb_rsq_pdu(receive_buffer_temp,​12);​
 +
 +     ​return 0;
 +}
 +static int mb_rsq_pdu(unsigned char *receive_buffer_temp,​int counter_temp)
 + {
 +   ​if(receive_buffer_temp[0 + 6] == 0x01){
 +     ​switch(receive_buffer_temp[1 + 6]){
 +       case 1:
 +               ​function_1(receive_buffer_temp);​
 +               ​break;​
 +       case 2:
 +               ​function_2(receive_buffer_temp);​
 +               ​break;​
 +       case 3:
 +               ​function_3(receive_buffer_temp);​
 +               ​break;​
 +       case 4:
 +               ​function_4(receive_buffer_temp);​
 +               ​break;​
 +       case 5:
 +               ​function_5(receive_buffer_temp,​counter_temp);​
 +               ​break;​
 +       case 6:
 +               ​function_6(receive_buffer_temp,​counter_temp);​
 +               ​break;​
 +       ​default :
 +               ​mb_excep_rsq_pdu(receive_buffer_temp,​1);​
 +               ​break;​
 +     }
 +  }else if(receive_buffer_temp[0 + 6] == 0){
 +      broadcast(receive_buffer_temp);​
 +    }
 +  return 0;
 + }
 +static int function_1(unsigned char *receive_buffer_temp)
 +{
 +  int i;
 +  unsigned short cnt;
 +  unsigned short coil_num;
 +  unsigned short start_address;​
 +int temp = 0;
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
 +  coil_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6];
 +  if((start_address + coil_num) > 255){
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​
 +    return 1;
 +  }
 +  receive_buffer_temp[2 + 6] = ((coil_num % 8 )? (coil_num / 8 + 1) : (coil_num / 8));
 +  cnt = receive_buffer_temp[2 + 6] + 5 - 2;
 +  if(coil_num % 8){
 +    if(coil_num < 8){
 +      for(i = 0;i < coil_num;i ++)temp |= 1 << i;
 +      receive_buffer_temp[3 + 6] = ((coil[start_address / 8]) >> (start_address % 8) | (coil[start_address / 8 + 1]) << (8 - (start_address % 
 +8))) & temp;
 +    }else {
 +      for(i = 0;i < receive_buffer_temp[2 + 6] - 1;​i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
 +      receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8] << ((8 - (coil_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (coil_num % 8));
 +    }
 +  }else {
 +      for(i = 0;i < receive_buffer_temp[2 + 6];​i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
 +  }
 + receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
 + receive_buffer_temp[5] = (cnt & 0x00ff);
 + cnt = cnt + 6;
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​cnt);​
 +  return 0;
 +}
 +static int function_2(unsigned char *receive_buffer_temp)
 +{
 +  int i;
 +  unsigned short cnt;
 +  unsigned short discrete_num;​
 +  unsigned short start_address;​
 +int temp = 0;
  
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
  
- +  discrete_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6]; 
-附录1:电脑IP设置 + 
-打开控制面板->网络和 Internet->网络连接,选择对应的网卡,右键点击属性,设置IPV4的IP地址,如图所示、 +  if((start_address + discrete_num) > 255){ 
-  +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
-  +    return ​1; 
-  +  } 
-附录2:Modbus Poll软件建立连接 +  receive_buffer_temp[2 + 6] = ((discrete_num % 8 )? (discrete_num / 8 + 1) : (discrete_num / 8)); 
-打开Modbus Poll,点击Connet,设置协议类型、IP地址和端口号,点击OK开始进行连接。 +  cnt = receive_buffer_temp[2 + 6] + 5 2; 
- +  if(discrete_num % 8){ 
 +    if(discrete_num < 8){ 
 +      for(i = 0;i < discrete_num;​i ++)temp |= 1 << i; 
 +      receive_buffer_temp[3 + 6] = ((discrete_input[start_address / 8]) >> (start_address % 8) | (discrete_input[start_address / 8 + 1]) << (8 (start_address % 8))) & temp; 
 +    }else { 
 +      for(i = 0;i < receive_buffer_temp[2 + 6] - 1;​i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8)); 
 +      ​receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8] << ((8 - (discrete_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (discrete_num % 8)); 
 +    } 
 +  }else { 
 +      for(i = 0;i < receive_buffer_temp[+ 6];​i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8)); 
 +  } 
 +  
 + receive_buffer_temp[4] = (cnt & 0xff00) >> 8; 
 + receive_buffer_temp[5] = (cnt & 0x00ff); 
 + cnt = cnt + 6; 
 + 
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​cnt);​ 
 +  return 0; 
 +
 +static int function_3(unsigned char *receive_buffer_temp) 
 +{   
 +  int i; 
 +  int cnt = 0; 
 +  unsigned short int start_address;​ 
 + 
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 + 
 +  receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2; 
 +   
 +  if(receive_buffer_temp[2 + 6] > 48){  
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
 +    return 1; 
 +  } 
 + 
 +  if((start_address * 2 + receive_buffer_temp[2]) > 512){ 
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
 +    return 1; 
 +  } 
 +  cnt = receive_buffer_temp[2 + 6] + 5 - 2; 
 +  for(i = 0;i < receive_buffer_temp[2 + 6];i++){ 
 + receive_buffer_temp[i + 3 + 6] = hold_reg[start_address * 2 + i]; 
 +
 + 
 + receive_buffer_temp[4] = (cnt & 0xff00) >> 8; 
 + receive_buffer_temp[5] = (cnt & 0x00ff); 
 + cnt = cnt + 6; 
 +  
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​cnt);​ 
 +  return 0; 
 +
 +static int function_4(unsigned char *receive_buffer_temp) 
 +
 +  int i; 
 +  int cnt; 
 +  unsigned short int start_address;​ 
 + 
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 + 
 +  receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2; 
 + 
 +  if((start_address * 2 + receive_buffer_temp[2 + 6]) > 20){ 
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
 +    return 1; 
 +  } 
 + 
 +  cnt = receive_buffer_temp[2 + 6] + 5 - 2; 
 +  for(i = 0;i < receive_buffer_temp[2 + 6];​i++)receive_buffer_temp[i + 3 + 6] = input_reg[start_address * 2 + i]; 
 + 
 + receive_buffer_temp[4] = (cnt & 0xff00) >> 8; 
 + receive_buffer_temp[5] = (cnt & 0x00ff); 
 + cnt = cnt + 6; 
 + 
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​cnt);​ 
 +  return 0; 
 +
 +static int function_5(unsigned char *receive_buffer_temp,​int counter_temp) 
 +
 +  unsigned short start_address;​ 
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 + 
 +  if(start_address > 255){ 
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
 +    return 1; 
 +  } 
 + 
 +  if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){ 
 +     ​coil[(start_address / 8)] |= 1 << start_address % 8; 
 +  }else if((receive_buffer_temp[4 + 6] == 0x00) && (receive_buffer_temp[5 + 6] == 0x00)){ 
 +     ​coil[(start_address / 8)] &= ~(1 << start_address % 8); 
 +  }else { 
 +     ​mb_excep_rsq_pdu(receive_buffer_temp,​3);​ 
 +  } 
 + 
 + receive_buffer_temp[4] = (6 & 0xff00) >> 8; 
 + receive_buffer_temp[5] = (6 & 0x00ff); 
 +  
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​counter_temp);​ 
 +  return 0; 
 +
 +static int function_6(unsigned char *receive_buffer_temp,​int counter_temp) 
 +
 +  unsigned short start_address;​ 
 + 
 +  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 + 
 +  if(start_address > 255){ 
 +    mb_excep_rsq_pdu(receive_buffer_temp,​2);​ 
 +    return 1; 
 +  } 
 + 
 +  hold_reg[start_address * 2] = receive_buffer_temp[4 + 6]; 
 +  hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6]; 
 + 
 +receive_buffer_temp[4] = (6 & 0xff00) >> 8; 
 +receive_buffer_temp[5] = (6 & 0x00ff); 
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​counter_temp);​ 
 +  return 0; 
 +
 +static int mb_excep_rsq_pdu(unsigned char *receive_buffer_temp,​int error_code) 
 + { 
 +   ​receive_buffer_temp[1 + 6] |= 0x80;  
 +   ​switch(error_code) { 
 +     case 1: 
 +             ​receive_buffer_temp[2 + 6] = 1; 
 +             ​break;​ 
 +     case 2: 
 +             ​receive_buffer_temp[2 + 6] = 2; 
 +             ​break;​ 
 +     case 3: 
 +             ​receive_buffer_temp[2 + 6] = 3; 
 +             ​break;​ 
 +     case 4: 
 +             ​receive_buffer_temp[2 + 6] = 4; 
 +             ​break;​ 
 +     ​default : 
 +             ​break;​ 
 +   } 
 + receive_buffer_temp[4] = (3 & 0xff00) >> 8; 
 + receive_buffer_temp[5] = (3 & 0x00ff); 
 +  
 + eth_tcps.send(eth_tcps.tcppcbnew,​receive_buffer_temp,​9);​ 
 + return 0; 
 + } 
 +static int broadcast(unsigned char *receive_buffer_temp) 
 + { 
 +   int start_address;​ 
 +   ​switch(receive_buffer_temp[1 + 6]){ 
 +     case 5:  
 +             ​start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 +             ​if(start_address > 255){ 
 +                return 1; 
 +             } 
 +             ​if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){ 
 +                coil[(start_address / 8)] |= 1 << start_address % 8; 
 +             }else if((receive_buffer_temp[4 + 6] == 0x00) &&  
 +(receive_buffer_temp[5 + 6] == 0x00)){ 
 +                coil[(start_address / 8)] &= ~(1 << start_address % 8); 
 +             } 
 +             ​break;​ 
 +    case 6:  
 +            start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6]; 
 +            if(start_address > 255){ 
 +               ​return 1; 
 +            } 
 +            hold_reg[start_address * 2] = receive_buffer_temp[4 + 6]; 
 +            hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6];  
 +            break; 
 +    }  
 +   ​return 0; 
 + } 
 + 
 +</​code> ​
    
  
 +==== 五、 实验步骤 ====
 +
 +  - 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
 +  - 把iCore4T通过以太网线与计算机相连,为iCore4T供电;
 +  - 设置电脑IP地址(见附录1);
 +  - 打开Keil MDK 开发环境,并打开本实验工程;
 +  - 烧写程序到iCore4T上;
 +  - 打开Modbus Poll软件建立连接(见附录2),读取hold寄存器中的数据值,观察核心板返回的数据值。
 +==== 六、 实验现象 ====
 +
 +  * Modbus Poll软件可看到核心板电源数据的检测值。
 +{{ :​icore4t:​icore4t_arm_hal_45_1.png?​direct |}}
 +==== 附录1:电脑IP设置 ====
 +
 +  * 打开控制面板->​网络和 Internet->​网络连接,选择对应的网卡,右键点击属性,设置IPV4的IP地址,如图所示:
 +{{ :​icore4t:​icore4t_arm_hal_45_2.png?​direct |}}
 +{{ :​icore4t:​icore4t_arm_hal_45_3.png?​direct |}}
 +==== 附录2:Modbus Poll软件建立连接 ====
 +
 +  * 打开Modbus Poll,点击Connet,设置协议类型、IP地址和端口号,点击OK开始进行连接。
 +{{ :​icore4t:​icore4t_arm_hal_45_4.png?​direct |}}
 +{{ :​icore4t:​icore4t_arm_hal_45_5.png?​direct |}}
icore4t_45.1601120764.txt.gz · 最后更改: 2020/09/26 19:46 由 zgf