当前位置:首页 > 聚焦财报 > 正文内容

开发者分享 | 面向工业应用的 HPM5E00 实践:ADC、SDM 与 EtherCAT

聚亿千财2026-02-04聚焦财报4091

概要

1、EUI的简单使用

2、16位ADC采样实验

3、SDM对Σ-Δ调制器输出数据采样

4、外置SRAM模拟为U盘

5、EtherCat io示例实践

一、EUI的简单使用

收到HPM5E00开发板后,由于SDK V1.9版本尚未支持该型号,开发板只能暂时存放在包装盒中,等待新版本发布。经过一段时间的等待,终于在7月1日收到了SDK V1.10版本发布的通知。我立即下载了最新版本,打开start_gui工具后,欣喜地发现界面中已经明确显示支持HPM5E00evk开发板。这意味着现在可以正式开始基于这款开发板的探索和开发工作了。

既然开发板上最显眼的就是LED数码管,那就从它开始探索吧。

首先,我查阅了开发板的原理图,确认数码管驱动方式。接着在SDK的例程中寻找相关的驱动代码,发现官方文档中已经有了关于EUI的说明,而且已经提供了EUI的示例,这正是控制数码管显示的基础。

5714b1e2-00df-11f1-96ea-92fbcf53809c.png

我修改了示例代码,试着让数码管显示自增数字,即每500ms数字加一。

数码管虽小,却是一个很好的切入点。通过它,可以逐步熟悉这款芯片的EUI库函数,为更复杂的开发打下基础。

1.1 EUI功能描述

用户手册中有关于EUI的描述

可以理解EUI是用于嵌入式系统中的矩阵键盘或LED显示控制,至于如何使用,使用好官方提供的库函数即可。

1.2 软件部分

使用start_gui工具从例程中生成工程

574dc55e-00df-11f1-96ea-92fbcf53809c.png

生成后,可以用SEGGER Embedded Studio 8.24打开工程,进行修改

在main函数中,注释掉原有的函数,调用一个自己的函数

//led_disp_config();

segment_disp();

segment_disp内容如下:

voidsegment_disp(void)

{

eui_scan_disp_data_tdisp_data;

disp_data.data_8x8[0]=s_disp_code_8_seg[(count/10000)%10];

disp_data.data_8x8[1]=s_disp_code_8_seg[(count/1000)%10];

disp_data.data_8x8[2]=s_disp_code_8_seg[(count/100)%10];

disp_data.data_8x8[3]=s_disp_code_8_seg[(count/10)%10];

disp_data.data_8x8[4]=s_disp_code_8_seg[count%10];

eui_set_scan_disp_data(BOARD_EUI,0,&disp_data);

count++;

}

就是每次调用函数,count加一,并在5个数码管上显示各位数字

在while(1)中增加

segment_disp();

board_delay_ms(500);

每500ms,增加一次count

eui引脚初始化

init_eui_pins(BOARD_EUI);

其中#define BOARD_EUI HPM_EUI1

voidinit_eui_pins(EUI_Type*ptr)

{

if(ptr==HPM_EUI1){

HPM_IOC->PAD[IOC_PAD_PB26].FUNC_CTL=IOC_PB26_FUNC_CTL_EUI1_CK;

HPM_IOC->PAD[IOC_PAD_PB27].FUNC_CTL=IOC_PB27_FUNC_CTL_EUI1_SH;

HPM_IOC->PAD[IOC_PAD_PB28].FUNC_CTL=IOC_PB28_FUNC_CTL_EUI1_DI;

HPM_IOC->PAD[IOC_PAD_PB29].FUNC_CTL=IOC_PB29_FUNC_CTL_EUI1_DO;

}else{

;

}

}

eui初始化函数

staticvoidinit_eui_config(void)

{

eui_ctrl_config_tctrl_config;

eui_get_default_ctrl_config(BOARD_EUI,&ctrl_config);

ctrl_config.work_mode=eui_work_mode_8x8;

ctrl_config.clko_freq_khz=100;

ctrl_config.key_filter_ms=50;

ctrl_config.disp_data_invert=0xFF;

ctrl_config.scan_invert=0x00;

ctrl_config.dedicate_out_cfg=BOARD_EUI_DEDICATE_OUT_LINES;

ctrl_config.dedicate_in_cfg=0x0000;

eui_config_ctrl(BOARD_EUI,s_eui_clock_freq,&ctrl_config);

printf("clko_tm_us:%d, slot_tm_us:%d, hold_tm_us:%d, disp_tm_us:%d, filter_tm_us:%d\n\n",

eui_get_time_us(BOARD_EUI,s_eui_clock_freq,eui_clko_time),eui_get_time_us(BOARD_EUI,s_eui_clock_freq,eui_slot_time),

eui_get_time_us(BOARD_EUI,s_eui_clock_freq,eui_hold_time),eui_get_time_us(BOARD_EUI,s_eui_clock_freq,eui_disp_time),

eui_get_time_us(BOARD_EUI,s_eui_clock_freq,eui_filter_time));

eui_set_irq_enable(BOARD_EUI,eui_irq_area_mask);

intc_m_enable_irq_with_priority(BOARD_EUI_IRQ,1);

eui_set_enable(BOARD_EUI,true);

}

1.3 运行效果

578527d8-00df-11f1-96ea-92fbcf53809c.jpg57a8305c-00df-11f1-96ea-92fbcf53809c.jpg

二、16位ADC采样实验

HPM5E00支持高达16位的ADC采样。

SDK中提供了ADC采样示例位于:sdk_env_v1.10.0\hpm_sdk\samples\drivers\adc\adc16

本文对示例做适当修改,将采集数据转换为电压并通过LED数码管显示。

2.1 生成工程

57c5e91c-00df-11f1-96ea-92fbcf53809c.png

2.2 软件部分

1、初始化oneshot模式

voidinit_oneshot_config(void)

{

adc16_channel_config_tch_cfg;

/* get a default channel config */

adc16_get_channel_default_config(&ch_cfg);

/* initialize an ADC channel */

ch_cfg.ch =BOARD_APP_ADC16_CH_1;

ch_cfg.sample_cycle=APP_ADC16_CH_SAMPLE_CYCLE;

adc16_init_channel(BOARD_APP_ADC16_BASE,&ch_cfg);

adc16_set_nonblocking_read(BOARD_APP_ADC16_BASE);

#ifdefined(ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT)&&ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT

/* enable oneshot mode */

adc16_enable_oneshot_mode(BOARD_APP_ADC16_BASE);

#endif

}

2、EUI设备初始化及数码管显示电压数值函数

#include"board.h"

#include"hpm_eui_drv.h"

#include"hpm_interrupt.h"

#include"hpm_clock_drv.h"

#include"common.h"

staticconstuint8_ts_disp_code_8_seg[]=BOARD_EUI_SEG_ENCODE_DATA;

staticuint32_ts_eui_clock_freq;

voidinit_eui_config(void)

{

eui_ctrl_config_tctrl_config;

clock_add_to_group(BOARD_EUI_CLOCK_NAME,0);

s_eui_clock_freq=clock_get_frequency(BOARD_EUI_CLOCK_NAME);

eui_get_default_ctrl_config(BOARD_EUI,&ctrl_config);

ctrl_config.work_mode=eui_work_mode_8x8;

ctrl_config.clko_freq_khz=100;

ctrl_config.key_filter_ms=50;

ctrl_config.disp_data_invert=0xFF;

ctrl_config.scan_invert=0x00;

ctrl_config.dedicate_out_cfg=BOARD_EUI_DEDICATE_OUT_LINES;

ctrl_config.dedicate_in_cfg=0x0000;

eui_config_ctrl(BOARD_EUI,s_eui_clock_freq,&ctrl_config);

/*

printf("clko_tm_us:%d, slot_tm_us:%d, hold_tm_us:%d, disp_tm_us:%d, filter_tm_us:%d\n\n",

eui_get_time_us(BOARD_EUI, s_eui_clock_freq, eui_clko_time), eui_get_time_us(BOARD_EUI, s_eui_clock_freq, eui_slot_time),

eui_get_time_us(BOARD_EUI, s_eui_clock_freq, eui_hold_time), eui_get_time_us(BOARD_EUI, s_eui_clock_freq, eui_disp_time),

eui_get_time_us(BOARD_EUI, s_eui_clock_freq, eui_filter_time));

eui_set_irq_enable(BOARD_EUI, eui_irq_area_mask);

intc_m_enable_irq_with_priority(BOARD_EUI_IRQ, 1);

*/

eui_set_enable(BOARD_EUI,true);

}

voidadc_led_disp(uint16_tval)

{

floatf_val=val*3.3/65535;

printf("f_val:%f\r\n",f_val);

eui_scan_disp_data_tdisp_data;

disp_data.data_8x8[0]=s_disp_code_8_seg[((uint16_t)f_val)%10]|BOARD_EUI_SEG_DP_BIT_MASK;

disp_data.data_8x8[1]=s_disp_code_8_seg[((uint16_t)(f_val*10))%10];

disp_data.data_8x8[2]=s_disp_code_8_seg[((uint16_t)(f_val*100))%10];

disp_data.data_8x8[3]=s_disp_code_8_seg[((uint16_t)(f_val*10000))%10];

disp_data.data_8x8[4]=s_disp_code_8_seg[((uint16_t)(f_val*100000))%10];

eui_set_scan_disp_data(BOARD_EUI,0,&disp_data);

}

3、oneshot采集处理,增加了调用adc_led_disp函数部分

voidoneshot_handler(void)

{

uint16_tresult;

if(adc16_get_oneshot_result(BOARD_APP_ADC16_BASE,BOARD_APP_ADC16_CH_1,&result)==status_success){

if(adc16_is_nonblocking_mode(BOARD_APP_ADC16_BASE)){

adc16_get_oneshot_result(BOARD_APP_ADC16_BASE,BOARD_APP_ADC16_CH_1,&result);

}

printf("Oneshot Mode - %s [channel %02d] - Result: 0x%04x\n",BOARD_APP_ADC16_NAME,BOARD_APP_ADC16_CH_1,result);

adc_led_disp(result);

}

board_delay_ms(500);

}

4、EUI初始化

init_eui_pins(BOARD_EUI);

init_eui_config();

5、采集通道修改

从原理图上可以看出ADC对应管脚PF18(ADC_IN11)

所以需要将BOARD_APP_ADC16_CH_1修改为11U

57d082fa-00df-11f1-96ea-92fbcf53809c.png57e8ddbe-00df-11f1-96ea-92fbcf53809c.png580311ca-00df-11f1-96ea-92fbcf53809c.png

修改

#defineBOARD_APP_ADC16_CH_1 (11U)

2.3 运行效果

串口输出

582140d2-00df-11f1-96ea-92fbcf53809c.png

在跳冒断开的情况下,手触碰jp7,可以改变PF18输入电压,可以看到数码管显示电压随之改变。

5831de38-00df-11f1-96ea-92fbcf53809c.gif

三、SDM对Σ-Δ调制器输出数据采样

3.1 引言

SDM(Sigma-Delta Modulator)是Σ∆信号接收单元(Σ∆Modulator)。

Σ-Δ电流采样优点是容易实现模拟隔离采样:主回路的开关噪声对控制电路干扰大,会影响系统稳定性和控制精度,隔离Σ-Δ采样可以实现控制与主回路隔离。隔离Σ-Δ转换器是采用脉冲输出方式传输信号,通过数字隔离芯片的原理实现隔离,较模拟隔离成本低而且失真小。

HPM5E00提供SDM模块具有以下特点:

信号输入接口

- 4组独立的CLK和DAT信号输入

- 每组CLK/DAT可独立配置采样模式

- 支持多种采样模式:

- Mode 0: MCLK上升沿采样

- Mode 1: MCLK上升沿和下降沿采样

- Mode 2: Manchester编码模式

- Mode 3: MCLK下降沿采样

- Mode 4: 每2个MCLK上升沿采样

- Mode 5: 每2个MCLK下降沿采样

- 数据滤波器(PCM_CIC):

- 支持4种滤波器类型:

- Sinc1 (1阶)

- Sinc2 (2阶)

- Sinc3 (3阶)

- SincFast (2阶快速)

- 可配置过采样率(1-256)

- 内置16深度32bit宽度FIFO

- 支持同步采样

- 支持掩码控制(指定版本)

- 可选时间戳输出功能(指定版本)

- 幅值检测器(AMP_CIC):

- 同样支持4种滤波器类型

- 独立的幅值监测通道

- 支持高/低门限检测

- 支持过零检测

- 可配置过采样率(1-32)

- 实时幅值输出

- 中断支持:

- FIFO阈值中断

- 数据溢出中断

- 数据饱和中断

- 幅值超限中断

- 同步功能:

- 支持TRGMUX触发输入

- 支持TRGMUX触发输出

3.2 数据寄存器

开发板上已经集成了NSI1306。NSI1306是一款高性能Σ-Δ调制器,基于NOVOSENSE电容隔离技术,其输出与输入分离。该器件的线性差分输入信号范围为±50mV(满量程±64mV)或±250mV范围(满量程±320mV)。差分输入非常适合需要隔离的高压应用中基于分流电阻电流检测。模拟输入经过放大,并由二阶Σ-Δ调制器连续采样,然后转换为高速,单比特数据流。输出数据与外部时钟同步,时钟上升沿有效,频率范围为5MHz至21MHz。通过使用适当的数字滤波器(例如sinc3滤波器)来抽取比特流,该器件可以在78.125KPS的条件下以20MHz的主时钟实现16位分辨率和86dB/82.5dB信噪比(SNR)。故障安全功能包括输入共模过压检测和VDD1缺失检测,简化了系统设计和诊断。

NSI1306管脚图

5865d5ee-00df-11f1-96ea-92fbcf53809c.png

在CLKIN上升沿时通过DOUT采集数据

587cb304-00df-11f1-96ea-92fbcf53809c.png

开发板原理图SDM连接图

588f9118-00df-11f1-96ea-92fbcf53809c.png

SDM使用了PF16、PF17管脚

57e8ddbe-00df-11f1-96ea-92fbcf53809c.png

为了进行实验,外部接入如下分压电路,用于测量电池分压后的结果

58b6d02a-00df-11f1-96ea-92fbcf53809c.png

3.3 软件部分

SDK示例中提供了四种工作模式演示:1. 轮询模式采样;2. 幅值检测模式;3. 中断模式采样;4. 同步信号采样模式

下面主要解读轮询模式采样模式。

(1) SDM 模块初始化

sdm_get_default_module_control(TEST_SDM,&control);

sdm_init_module(TEST_SDM,&control);

初始化 SDM 模块,配置时钟同步、数据同步。

(2) 通道配置

ch_config.sampling_mode=sdm_sampling_rising_clk_edge;

ch_config.enable_err_interrupt=false;

ch_config.enable_data_ready_interrupt=false;

sdm_config_channel_common_setting(TEST_SDM,TEST_SDM_CHANNEL,&ch_config);

采样模式:在时钟上升沿采样(与 NSI1306 的 Σ-Δ 输出同步)。

中断配置:禁用错误中断和数据就绪中断(使用轮询模式)。

(3) 数字滤波器配置

filter_config.filter_type=sdm_filter_sinc3;

filter_config.oversampling_rate=256;

filter_config.ignore_invalid_samples=2;

sdm_config_channel_filter(TEST_SDM,TEST_SDM_CHANNEL,&filter_config);

滤波器类型:Sinc³ 滤波器(适合 Σ-Δ 调制器,抑制高频噪声)。

过采样率 (OSR):256(提高分辨率,但降低带宽)。

无效样本忽略:跳过前 2 个样本(避免初始不稳定数据)。

(4) 数据采集与转换

do{

stat=sdm_receive_filter_data(TEST_SDM,TEST_SDM_CHANNEL,true,(int8_t*)filter_result,TEST_DATA_COUNT,4U);

}while(stat!=status_success);

doublevoltage=sdm_data_value_to_voltage(&filter_config,filter_result[i]);

轮询数据:从 FIFO 读取 32 位滤波后的数据(filter_result 为缓冲区)。

电压转换:将原始数据转换为实际电压值。

3.4运行效果

串口输出采集结果:

58d9da66-00df-11f1-96ea-92fbcf53809c.png

采集结果约为14.74mV

根据分压可以算出电池电压:1010*14.74/10=1488.74mV≈1.49V

四、外置SRAM模拟为U盘

SDK中有PPI接口驱动外置SRAM和TinyUSB模拟2个MSC大容量设备的例子。将2者结合可以将外置SRAM(256KB容量)虚拟为U盘。

原示例位于:

sdk_env_v1.10.0\hpm_sdk\samples\tinyusb\device\msc_dual_lun

4.1 软件部分

1、main函数增加

clock_add_to_group(clock_ppi0,0);

init_ppi_pins();

init_sram_config();

init_pmp_for_ppi();

init_disk(0xF8000000);

init_ppi_pins为板级函数,初始化PPI引脚以驱动外置SRAM

init_sram_config、init_pmp_for_ppi函数均可在

sdk_env_v1.10.0\hpm_sdk\samples\drivers\ppi\async_sram示例中找到

init_disk为将msc_disk1指向外置SRAM区域,用来虚拟U盘空间,这个函数需要在外置SRAM就位后调用。

msc_disk1为指向数组的指针。

uint8_t (*msc_disk1)[DISK_BLOCK_SIZE];

init_disk函数,diskinfo中有3个BLOCK(512字节*3)为FAT文件结构,需要拷贝到msc_disk1中,msc_disk1的其他部分需清零

voidinit_disk(uint32_tstart){

// Cast the start address to our disk pointer type

msc_disk1=(uint8_t(*)[DISK_BLOCK_SIZE])start;

// Copy the disk info to the disk memory

memcpy(msc_disk1,diskinfo,3*DISK_BLOCK_SIZE);

memset(msc_disk1+3,0,(512-3)*DISK_BLOCK_SIZE);

}

2、TinyUSB模拟MSC设备部分(msc_disk_dual.c)

diskinfo为FAT文件系统定义,对原示例进行了修改。

diskinfo位于flash区域,非内存,需要在外置SRAM就位后,copy到msc_disk1中

block2、block3相同为FAT12表

staticconstuint8_tdiskinfo[4][DISK_BLOCK_SIZE]=

{

{

0xEB,0x3C,0x90,0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,0x00,0x02,0x01,0x01,0x00,

0x02,0x10,0x00,0x00,0x02,0xF8,0x02,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x80,0x00,0x29,0x78,0x56,0x00,0x00,'T','i','n','y','U',

'S','B',' ','1',' ',' ',0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x00,

/* Zero up to 2 last bytes of FAT magic code */

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAA

},

/*------------- Block1: FAT12 Table -------------*/

{

0xF8,0xFF,0xFF,0xFF,0x0F,0x00,0x00// // first 2 entries must be F8FF, third entry is cluster end of readme file

},

/*------------- Block2: FAT12 Table -------------*/

{

0xF8,0xFF,0xFF,0xFF,0x0F,0x00,0x00// // first 2 entries must be F8FF, third entry is cluster end of readme file

},

}

tud_msc_capacity_cb函数

主要对lun进行判断,当0时第一U盘,返回DISK_BLOCK_NUM*DISK_BLOCK_SIZE(32*512=16kb),当1时第二U盘,返回512*512=256kb

voidtud_msc_capacity_cb(uint8_tlun,uint32_t*block_count,uint16_t*block_size)

{

(void)lun;

if(lun==0)

{

*block_count=DISK_BLOCK_NUM;

*block_size =DISK_BLOCK_SIZE;

}elseif(lun==1)

{

*block_count=512;

*block_size =DISK_BLOCK_SIZE;

}

printf("tud_msc_capacity_cb:%d\r\n",lun);

}

其他主要TingUSB接口函数未做修改

tud_msc_read10_cb

tud_msc_write10_cb

tud_msc_scsi_cb

4.2 运行效果

1、插上外置板卡

SRAM位于外置板卡上

58e8b0f4-00df-11f1-96ea-92fbcf53809c.jpg

2、断开JP6

根据SDK说明,为了使PPI工作,断开JP6

58ffe1de-00df-11f1-96ea-92fbcf53809c.jpg

3、Type-C连接开发板J1(USB)和PC机

可以看到新识别了2个U盘,其中E盘为原示例中第一个U盘位做修改,第二U盘为外置SRAM模拟的U盘,容量大概256KB

59234f2a-00df-11f1-96ea-92fbcf53809c.png

E:的内容,F:是空的

59355648-00df-11f1-96ea-92fbcf53809c.png

设备管理中也可以看到这2个U盘

59463a30-00df-11f1-96ea-92fbcf53809c.png

五、EtherCat io示例实践

对于一个陌生的技术,按照示例按部就班地实现无疑是一个很多好的学习方法。

在完成本次实验前,笔者没有接触过EtherCat,所有行文中有错误和不当之处在所难免。

本文记录EtherCat io示例运行环境搭建及演示。

例程位于

sdk_env_v1.10.0\hpm_sdk\samples\ethercat\ecat_io

5.1 环境准备

1、SSC ToolV5.13

因为SDK中的配置采用的是V51.3,所以一定不要用其他版本。

因为Beckhoff官网只给企业用户提供下载用户,因此花了一些时间找到一个下载地址:

https://gitcode.com/open-source-toolkit/a3990/?utm_source=tools_gitcode&index=top&type=href&

SSC Tool主要的作用是生成EtherCAT从站协议栈代码。

2、TwinCAT 3

可以从倍福(中国)官方下载,需要注册

地址:

https://www.beckhoff.com.cn/zh-cn/support/download-finder/search-result/?c-1=26782567

下载中心中查找:TwinCAT 3 download | eXtended Automation Engineering (XAE) 1.4G

下载后文件为TC31-FULL-Setup.3.1.4024.67.exe,注意安装时要以管理员身份运行。

5957dbd2-00df-11f1-96ea-92fbcf53809c.png

TwinCAT在本例中主要起到EEPROM更新,控制EtherCAT从站的作用。

3、patch

示例中SSC协议栈代码修改用到了patch工具,所以需要安装patch,然后将patch路径加到系统路径中

patch下载地址:

https://gnuwin32.sourceforge.net/packages/patch.htm

5.2 示例构建

1、用start_gui工具生成工程

596a6a72-00df-11f1-96ea-92fbcf53809c.png

2、SSC tool生成EtherCAT从站协议栈代码

new->import->HPM_ECAT_IO_Config.xml

import后,SSC tool可以支持HPM代码的生成

59830fa0-00df-11f1-96ea-92fbcf53809c.png

tool->import->Application->digital_io.xlsx

599b27f2-00df-11f1-96ea-92fbcf53809c.png

Project->Create new Slave ***生成从站协议栈代码

59b1fff4-00df-11f1-96ea-92fbcf53809c.png

3、SSC协议栈代码修改

sdk_env_v1.10.0\hpm_sdk\samples\ethercat\ecat_io下

运行patch -d Src < ssc_pdi_mask.patch

4、用SEGGER Embedded Studio 8.24打开工程,编译下载到开发板

5、TwinCAT工程设置

下面只列出一些主要工作,详见gitee的官方SDK说明:https://gitee.com/hpmicro/hpm_sdk/tree/main/samples/ethercat/ecat_io

1)将ESI文件

(sdk_env_v1.10.0\hpm_sdk\samples\ethercat\ecat_io\SSC\ESIECAT-IO.xml )复制到TwinCAT的安装目录下(如: C:/TwinCAT/3.1/Config/Io/EtherCAT )。

2)运行TwinCAT XAE Shell,打开TwinCAT软件,选择 File->New->project,新建工程

3)首次使用更新网卡驱动

4)时钟设置

管理员身份运行

C:\TwinCAT\3.1\System\win8settick.bat

5)扫描设备

扫描设备前,开发板应和PC机通过双绞线连接

6)更新EEPROM

7) IO操作

5.3 软件方面

59c7ea26-00df-11f1-96ea-92fbcf53809c.png59e4134a-00df-11f1-96ea-92fbcf53809c.png

APPL_Application函数被EtherCat中断调用,执行gpio输入判断和LED点亮操作

voidAPPL_Application(void)

{

InputCounter0x6000=APPL_GetDipSw();

APPL_SetLed((UINT32)OutputCounter0x7010);

}

LED点亮函数

voidAPPL_SetLed(UINT32 value)

{

UINT8 led0=((value&1)? BOARD_ECAT_OUT_ON_LEVEL:!BOARD_ECAT_OUT_ON_LEVEL);

UINT8 led1=((value&2)? BOARD_ECAT_OUT_ON_LEVEL:!BOARD_ECAT_OUT_ON_LEVEL);

gpio_write_pin(BOARD_ECAT_OUT1_GPIO,BOARD_ECAT_OUT1_GPIO_PORT_INDEX,BOARD_ECAT_OUT1_GPIO_PIN_INDEX,led0);

gpio_write_pin(BOARD_ECAT_OUT2_GPIO,BOARD_ECAT_OUT2_GPIO_PORT_INDEX,BOARD_ECAT_OUT2_GPIO_PIN_INDEX,led1);

}

gpio输入判断函数

UINT32APPL_GetDipSw(void)

{

UINT8 pin0_level=gpio_read_pin(BOARD_ECAT_IN1_GPIO,BOARD_ECAT_IN1_GPIO_PORT_INDEX,BOARD_ECAT_IN1_GPIO_PIN_INDEX);

UINT8 pin1_level=gpio_read_pin(BOARD_ECAT_IN2_GPIO,BOARD_ECAT_IN2_GPIO_PORT_INDEX,BOARD_ECAT_IN2_GPIO_PIN_INDEX);

UINT32 val=pin0_level<<0|pin1_level<<1;

returnval;

}

5.4 运行

1、双绞线连接PC机

59f998fa-00df-11f1-96ea-92fbcf53809c.jpg

2、ECAT交互区

5a0e7fea-00df-11f1-96ea-92fbcf53809c.jpg

示例运行演示视频:

https://www.bilibili.com/video/BV1YJGgzYEA6/?share_source=copy_web&vd_source=7258d8aa5251054c1d4c51d8c4cc2a02

文章来源:EEFocus

开发者ID:eefocus_3941691

原文链接:

https://www.eefocus.com/forum/home.php?mod=space&uid=378371&do=thread&view=me&from=space

/

/

以上内容来自先楫开发者的原创分享。

我们始终相信开发者共创的力量。先楫社区坚持开源共享、互惠互利,贴近每一个开发者,一步一个脚印,一点一滴积累,为成为更好的我们而不断努力。

心之所向,锐意进取,星辰大海,恣意成长。

返回列表

上一篇:UV胶在工业领域的运用案例

没有最新的文章了...