0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SEI异步通讯—多摩川协议支持

先楫半导体HPMicro 2024-06-14 08:17 次阅读

贾工 先楫资深 FAE

12年产品研发经验,具有变频器、伺服等工业产品开发经验,也负责过激光投影显示系统开发、AI应用开发、PYQT、Linux驱动开发等工作。

1、SEI简介

SEI(Serial Encoder Interface)串行编码器接口,是先楫半导体创新性设计的一个针对串行绝对值编码器通信的外设。SEI支持同步通信模式与异步通信模式,既能做主机——从编码器获取数据,又能做从机——将位置信息以主机需要的串行协议发出。在电机类应用中极大的降低了编码器相关开发任务的难度,同时以硬件编解码的方式降低了CPU负载率,让CPU有更多算力处理其他任务。

先楫半导体SDK 1.5.0提供了诸多SEI应用的实例,包括BISS-C、Endat、Hiperface、Nikon、SSI、Tamagawa等串行协议的主站、从站配置源码,开发者在sample实例的基础上,简单的进行修改即可应用到项目中。

本文以Tamagawa协议为例,对SEI在异步通信中用法进行讲解,同时对slave例程进行修改,增加对Tamagawa协议中EEPROM指令的支持,使读者对SEI的用法有进一步的认识与了解。

本文中,命令指协议中主站向从站发送的命令,从站需要根据命令内容进行回复或执行某些操作;指令指SEI引擎执行的动作。

1.1SEI关键概念

1.1.1数据寄存器

数据寄存器是SEI收发数据的数据存放单元。在通信的接收过程中,接收到的数据会被存放于数据寄存器中;在通信的发送过程中,需要向外发送的数据同样存放在数据寄存器中。


SEI共有9组数据寄存器,每个寄存器宽度为32bit。当以字节(8bit)为单位进行收发时,可以只使用数据寄存器的bit0~bit7,也可以使用bit0~bit32(或bit0~bit23),此时SEI引擎会自动将数据每8bit为一个单位,增加起始位、奇偶校验位、结束位等进行收发。例如有一个24bit的编码器单圈位置数据,接收时虽然每8bit接收1包,但连续收到的3包数据会放到同一个数据寄存器内;发送时,用户在数据寄存器的bit0~bit23填入数据,SEI引擎会自动拆包,将bit0~bit7、bit8~bit15、bit16~bit23分别增加起始位、奇偶校验位、结束位对外发出。


数据寄存器0用于忽略接收到的数据——某些开发者不关心的数据可以使用数据数据寄存器0进行接收;其概念与linux系统下黑洞文件类似。


数据寄存器2~数据寄存器9为通用数据寄存器。可以工作在3种模式下:

1)数据模式:仅用于存储数据;

2)检查模式:可设定期待值,例如用户期待接收到0x17,当接收到的写入该数据寄存器的值不为0x17时,可产生传输错误提示;

3)CRC模式:用于收发数据过程中实时计算CRC值,可通过设置CRC多项式与CRC初始值来设计CRC算法,当接收数据的CRC计算结果与实时计算结果不符时,可产生错误传输提示。

1.1.2命令寄存器

用于接收串行编码器协议中的命令数据。例如Tamagawa协议中CF(Control Field)字段为命令,其含义如下图:

828eea60-29e3-11ef-a655-92fbcf53809c.png82b59b10-29e3-11ef-a655-92fbcf53809c.png82da1602-29e3-11ef-a655-92fbcf53809c.png

可以看到,CF字段内的cc0~cc3决定了通信的内容,根据该字段的不同,主机可以从编码器中读取单圈位置数据、多圈位置数据、报警信息、操作EEPROM等。

1.1.3命令匹配表

命令寄存器接收到命令后,SEI引擎接收JUMP跳转指令,会根据命令内容在命令匹配表内进行检索。找到符合命令的表项后,则跳转至该命令匹配表指向的指令开始执行。SEI共支持8张命令匹配表,SEI引擎会以顺序方式对每张命令匹配表的命令进行对比,如果命令匹配表0~命令匹配表6都匹配失败,则无条件执行命令匹配表7的预设指令(回复/不回复)。

1.1.4指令

SEI引擎共支持8种指令,分为停止、等待、接收、发送、跳转5大类指令,根据是否有超时保护拓展为8种指令。例如接收指令可分为时限内接收与无限时接收,时限内接收在规定的时间内未收到数据会进行报错处理,无限时接收则会永远等待下去。其它时限内发送与无限时发送等概念,请读者自行理解。SEI共支持预设64条指令。

1.1.5状态机

SEI状态机包括4个状态,状态的切换只能以0-->1-->2-->3-->0的顺序进行,每种状态的切换条件可由开发者自行定义,例如设置执行完第10条指令后状态机从状态0切换到状态1。状态切换可向外发送事件信号,开发者可将该信号拉到其它外设进行触发,实现硬件同步;或简单的产生一次中断或DMA事件,使用中断或DMA进行一定的数据处理工作。

理解SEI工作的关键就在于以上5个概念的掌握。其它更多的技术细节需要读者自行查阅UM手册进行理解。下面就以这5个概念对SEI工作的流程进行直观的举例描述:

1)从机开始以指令0“接收”状态等待主机发送CF字段,若接收到数据,将接收到的指令保存到指令寄存器;

2)例如收到了DATA ID3指令,接收到指令后检查指令匹配表;

3)顺序检查8张指令匹配表进行指令匹配,例如匹配到了指令表1,该指令表内描述“收到DATA ID3后执行预设的64条指令中的指令10”;

4)SEI引擎执行指令10,指令10内容为“时限内发送,CF,CF存放于指令寄存器”;

5)SEI引擎执行指令11,指令11内容为“时限内发送,SF,SF存放于数据寄存器2”;

6)SEI引擎执行指令12,指令12内容为“时限内发送,ABS0~ABS2,ABS存放于数据寄存器3”;

7)SEI引擎执行指令13,指令13内容为“时限内发送,ENID,ENID存放于数据寄存器4”;

8)SEI引擎执行指令14,指令14内容为“时限内发送,ABM,ABM存放于数据寄存器5”;

9)SEI引擎执行指令15,指令15内容为“时限内发送,ALC,ALC存放于数据寄存器6”;

10)SEI引擎执行指令16,指令16内容为“时限内发送,CRC,CRC存放于数据寄存器9”;

11)SEI引擎执行指令17,指令17内容为“结束,跳转回指令0”;

12)SEI引擎执行指令0,指令0内容为“接收,等待主机发送CF字段,若接收到数据,将接收到的指令保存到指令寄存器”。

可以看到,通过以上工作流程的描述,SEI就依靠硬件自动完成了数据的发送,响应了主机读数据的需求。CPU只要在合适的时间点将数据更新到数据寄存器即可。

2 多摩川协议简介

多摩川编码器在工业控制领域广泛应用,本节简单介绍Tamagawa编码器协议。

注意,协议整体架构是固定的,但具体到每款编码器,根据编码器精度不同、多圈数据位数不同,协议的数据内容需要进行微调。

多摩川编码器支持向主站提供单圈位置信息、多圈位置信息、报警信息、复位操作、EEPROM读写操作等,不同操作指令的下发位于CF字段内。下面分别介绍协议内不同指令的具体格式。

具体的,多摩川协议以2.5M固定波特率进行数通信,数据格式8、N、1。

2.1数据读取指令格式

82f7c49a-29e3-11ef-a655-92fbcf53809c.png

数据读取过程:

1)主机下发CF,CF内的cc0~cc3为ID0~ID3时,代表读取编码器信息;

2)从机回复CF,响应主机;

3)从机回复SF,发送编码器状态信息(具体有什么状态Flag请读者自行学习多摩川编码器Datasheet);

4)从机回复DF0~DF7,即数据字段。根据不同的指令ID,数据字段长度不同,数据字段内可包含ABS(单圈信息),ENID(固定0x17),ABM(多圈信息),ALMC(报警信息),不同ID回复内容见下表。

82da1602-29e3-11ef-a655-92fbcf53809c.png

5)从机回复CRC,供主机进行数据完整性校验。

时序要求如下,在收到CF后的0.5us时刻锁存当前位置信息:

833705f6-29e3-11ef-a655-92fbcf53809c.png

2.2EEPROM读指令格式

83454cf6-29e3-11ef-a655-92fbcf53809c.png

多摩川编码器为客户提供了762字节的EEPROM空间,分为6页,每页包含127个(0~126)字节。对地址127进行写操作可改变操作页数。

1)主机发送CF,CF内cc0~cc3字段解析为ID D;

2)主机发送ADF,代表要读取当前页的第ADF个(0~126)字节的数据;

3)主机发送CRC,供从机进行数据完整性校验;

4)从机回复CF、ADF;

5)从机回复EDF,即主机需要的数据;

6)从机回复CRC,供主机进行数据完整性校验。

2.3EEPROM写指令格式

835eab06-29e3-11ef-a655-92fbcf53809c.png

1)主机发送CF,CF内cc0~cc3字段解析为ID 6;

2)主机发送ADF,代表要写入当前页的第ADF个(0~126)字节;

3)主机发送EDF,代表要写入的数据;

4)主机发送CRC,供从机进行数据完整性校验;

5)从机回复CF、ADF、EDF、CRC,与主机下发内容相同,代表写入成功。

读写时序要求如下:

8362a6de-29e3-11ef-a655-92fbcf53809c.png

3多摩川从站例程介绍

打开

sdk_env_v1.5.0\hpm_sdk\samples\drivers\sei\slave\tamagawa\src文件,获取Tamagawa从站源码。

/* [1] tranceiver config */

tranceiver_config.mode=sei_asynchronous_mode;

tranceiver_config.tri_sample= false;

tranceiver_config.src_clk_freq=clock_get_frequency(BOARD_MOTOR_CLK_NAME);

tranceiver_config.asynchronous_config.wait_len =0;

tranceiver_config.asynchronous_config.data_len =8;

tranceiver_config.asynchronous_config.parity_enable=false;

tranceiver_config.asynchronous_config.data_idle_high_z =false;

tranceiver_config.asynchronous_config.data_idle_state= sei_idle_high_state;

tranceiver_config.asynchronous_config.baudrate= 2500000;

sei_tranceiver_config_init(BOARD_SEI,BOARD_SEI_CTRL,&tranceiver_config);

设置SEI工作在异步模式,波特率为2.5M,数据格式为8、N、1。以及数据线的默认状态等,这一部分请读者自行对照UM手册SEI寄存器进行解析。

/* [2] data register config */

/* cmd register : recv CF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_CMD,BOARD_SEI_CTRL,&data_format_config);

/* data register 4: send SF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_4, &data_format_config);

/* data register 5: send ABS0 ABS1 ABS2 */

data_format_config.mode=sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order=sei_word_nonreverse;

data_format_config.word_len= 24;

data_format_config.last_bit= 23;

data_format_config.first_bit= 0;

data_format_config.max_bit= 23;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_5, &data_format_config);

/* data register 6: send ENID */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order=sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_6, &data_format_config);

/* data register 7: send ABM0 ABM1 ABM2 */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order=sei_word_nonreverse;

data_format_config.word_len= 24;

data_format_config.last_bit= 23;

data_format_config.first_bit= 0;

data_format_config.max_bit= 23;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_7, &data_format_config);

/* data register 8: send ALMC */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order=sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_8, &data_format_config);

/* data register 9: send crc */

data_format_config.mode= sei_crc_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order=sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.crc_invert= false;

data_format_config.crc_shift_mode= false;

data_format_config.crc_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

data_format_config.crc_init_value= 0;

data_format_config.crc_poly= 1;

sei_cmd_data_format_config_init

(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_9, &data_format_config);

设置数据寄存器,其中:

1)指令寄存器用于收发CF;

2)DATA4(数据寄存器4)用于发送SF;

3)DATA5(数据寄存器5)用于发送ABS;

4)DATA6(数据寄存器6)用于发送ENID;

5)DATA7(数据寄存器7)用于发送ABM;

6)DATA8(数据寄存器8)用于发送ALM;

7)DATA9(数据寄存器9)用于发送CRC;

/* [3] instructions */

instr_idx= 0;

/* instr0 : Recv CF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_1, 8);

/* instr1 : halt 1 bit for update */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1);

/* instr2 : halt some bits for waiting */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6);

/* instr3 : jump to cmd table instr_idx[0] */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX0);

/* Data ID0 : 0x02 */

/*instr4 : sendCF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);

/* instr5 : send SF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);

/*instr6 :send ST(POS) */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);

/*instr7 :CRC */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);

/*instr8 :Jump back to initiate*/

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID1 : 0x8A */

/* Reference to instr0 ~ instr8 */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID2 : 0x92 */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8); /* SF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID3 : 0x1A */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8); /* SF */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_8, 8);/* ALMC */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

设置预设指令,其中:

1)指令0用于接收CF;

2)指令1用于延迟0.5us后锁存位置信息;

3)指令2用于延迟3us满足时序要求;

4)指令3用于跳转,查找指令匹配表进行匹配;

5)指令4~指令表结束,根据不同的指令向主机发送主机查询的信息。

/* [4] command table */

command_table_config.cmd_min_value= 0x02u;

command_table_config.cmd_max_value= 0x02u;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 4;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_0, &command_table_config);

command_table_config.cmd_min_value= 0x8Au;

command_table_config.cmd_max_value= 0x8Au;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 9;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_1, &command_table_config);

command_table_config.cmd_min_value= 0x92u;

command_table_config.cmd_max_value= 0x92u;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 14;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_2,&command_table_config);

command_table_config.cmd_min_value= 0x1Au;

command_table_config.cmd_max_value= 0x1Au;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 19;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_3,&command_table_config);

设置指令匹配表,

cmd_min_value、cmd_max_value、cmd_mask_value设置了指令匹配的模式,请参考UM手册查询具体的含义;instr_idx[0]设置了如果匹配成功,跳转的目标指令。

/* [5] state transition config */

/* latch0 */

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= false;

state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;

state_transition_config.instr_ptr_value= 1;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_1_2,&state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_2_3, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_3_0, &state_transition_config);

state_transition_latch_config.enable= true;

state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;

state_transition_latch_config.delay= 0;

sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0,&state_transition_latch_config);

状态机跳转的配置代码,此处只配置了状态0到状态1转换的条件为“指令1执行完成”,即接收到CF后0.5us的时间点,进行状态转换,同时向外生成事件(本例程内产生了中断,中断内对要发送的数据进行了设置)。

/* [6] sample config*/

sample_config.pos_data_idx= SEI_DAT_5;

sample_config.rev_data_idx= SEI_DAT_7;

sample_config.pos_data_use_rx= false;

sample_config.rev_data_use_rx= false;

sample_config.sample_window= 0x5;

sample_config.sample_once= true;

sample_config.latch_select= SEI_LATCH_0;

sample_config.data_register_select= BIT5_MASK| BIT7_MASK; /* SEI_DAT_5, SEI_DAT_7 */

sei_sample_config_init(BOARD_SEI, BOARD_SEI_CTRL,&sample_config);

sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);

sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL,mock_rev);

/* [7] interrupt config */

intc_m_enable_irq_with_priority(BOARD_SEI_IRQn, 1);

sei_set_irq_enable(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event | sei_irq_wdog_event | sei_irq_trx_err_event,true);

采样设置(读取电机系统内的位置信息)与中断开启,状态0到状态1实现状态转换时,出发了sei_irq_latch0_event中断。

/* [8] enbale sync timer timestamp */

synt_enable_timestamp(HPM_SYNT, true);

/* [9] engine config */

printf("Started sei engine!\n");

engine_config.arming_mode= sei_arming_direct_exec;

engine_config.data_cdm_idx= 0;

engine_config.data_base_idx= 0;

engine_config.init_instr_idx= 0;

engine_config.wdg_enable= true;

engine_config.wdg_action= sei_wdg_exec_exception_instr;

engine_config.wdg_instr_idx= 0;

engine_config.wdg_time= 1000; /* 1000 bits time */

sei_engine_config_init(BOARD_SEI, BOARD_SEI_CTRL,&engine_config);

sei_set_engine_enable(BOARD_SEI, BOARD_SEI_CTRL, true);

看门狗的设置及使能SEI引擎,看门狗的配置含义请参考UM手册。

voidisr_sei(void)

{

uint32_tdelta;

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event);

sample_latch_tm1= sei_get_latch_time(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0);

mock_pos++;

if(mock_pos> 0x00FFFFFF) {

mock_pos= 0;

mock_rev++;

if(mock_rev> 0x00FFFFFF) {

mock_rev= 0;

}

}

sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);

sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_rev);

sei_set_data_value(BOARD_SEI, SEI_DAT_4, 0x00);

sei_set_data_value(BOARD_SEI, SEI_DAT_6, 0x17);

sei_set_data_value(BOARD_SEI, SEI_DAT_8, 0x00);

delta= (sample_latch_tm1> sample_latch_tm2) ? (sample_latch_tm1- sample_latch_tm2) : (sample_latch_tm1- sample_latch_tm2+ 0xFFFFFFFFu);

printf("CMD:%#x, SF:%#x, ST:%#x, ENID:%#x, MT:%#x, ALMC:%#x, CRC:%#x, sample_tm1:%u, sample_tm2:%u, sample_interval:%dus\n",

sei_get_command_value(BOARD_SEI, BOARD_SEI_CTRL),

sei_get_data_value(BOARD_SEI, SEI_DAT_4),

sei_get_data_value(BOARD_SEI, SEI_DAT_5),

sei_get_data_value(BOARD_SEI, SEI_DAT_6),

sei_get_data_value(BOARD_SEI, SEI_DAT_7),

sei_get_data_value(BOARD_SEI, SEI_DAT_8),

sei_get_data_value(BOARD_SEI, SEI_DAT_9),

sample_latch_tm1, sample_latch_tm2, delta/ (clock_get_frequency(BOARD_MOTOR_CLK_NAME) / 1000000));

sample_latch_tm2= sample_latch_tm1;

}

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event);

sei_set_command_rewind(BOARD_SEI, BOARD_SEI_CTRL);

}

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event);

printf("TRX Error!\n");

}

}

SEI中断设置,当sei_irq_latch0_event中断发生时,设置了向主机回复的数据,满足多摩川时序要求,即接收到CF后0.5us时间点进行数据设置。

4 EEPROM指令支持

由于读写EEPROM的指令格式与读取位置数据指令格式有区别,即接收CF后不进行锁存,需要继续接收ADF、EDF等数据,因此整个SEI指令处理流程上,指令的跳转逻辑变得更复杂。下图是在做EEPROM指令支持开发过程中,绘制的流程图。

8376968a-29e3-11ef-a655-92fbcf53809c.png

支持EEPROM指令的关键源码如下:

uint32_teeprom_page= 0;

uint32_teeprom[6][127] = {0};

声明eeprom地址页信息变量与6页共762字节的eeprom数据数组。

/* [2] data register config */

/* cmd register : recv CF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_CMD, BOARD_SEI_CTRL, &data_format_config);

/* cmd register : recv ADF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_2,&data_format_config);

/* cmd register : recv EDF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_3,&data_format_config);

/* data register 4: send SF */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_4, &data_format_config);

/* data register 5: send ABS0 ABS1 ABS2 */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag=false;

data_format_config.bit_order=sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 24;

data_format_config.last_bit= 23;

data_format_config.first_bit= 0;

data_format_config.max_bit= 23;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_5, &data_format_config);

/* data register 6: send ENID */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_6, &data_format_config);

/* data register 7: send ABM0 ABM1 ABM2 */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 24;

data_format_config.last_bit= 23;

data_format_config.first_bit= 0;

data_format_config.max_bit= 23;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_7,&data_format_config);

/* data register 8: send ALMC */

data_format_config.mode= sei_data_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_8,&data_format_config);

/* data register 9: send crc */

data_format_config.mode= sei_crc_mode;

data_format_config.signed_flag= false;

data_format_config.bit_order= sei_bit_lsb_first;

data_format_config.word_order= sei_word_nonreverse;

data_format_config.word_len= 8;

data_format_config.crc_invert= false;

data_format_config.crc_shift_mode= false;

data_format_config.crc_len= 8;

data_format_config.last_bit= 7;

data_format_config.first_bit= 0;

data_format_config.max_bit= 7;

data_format_config.min_bit= 0;

data_format_config.crc_init_value= 0;

data_format_config.crc_poly= 1;

sei_cmd_data_format_config_init

(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_9, &data_format_config);

设置数据寄存器,其中:

1)指令寄存器用于收发CF

2)DATA2(数据寄存器2)用于收发ADF

3)DATA3(数据寄存器3)用于发送EDF

4)DATA4(数据寄存器4)用于发送SF

5)DATA5(数据寄存器5)用于发送ABS

6)DATA6(数据寄存器6)用于发送ENID

7)DATA7(数据寄存器7)用于发送ABM

8)DATA8(数据寄存器8)用于发送ALM

9)DATA9(数据寄存器9)用于发送CRC

/* [3] instructions */

instr_idx= 0;

/*00*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_1, 8);/* Recv CF */

/* jump to cmd */

/*01*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX0);/* jump to cmd table instr_idx[0] */

/*02*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1); /* halt 1 bit for update */

/*03*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6); /* halt some bits for waiting */

/*04*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);

/* Data ID0 : 0x02 */

/*05*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */

/*06*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */

/*07*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */

/*08*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

/*09*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID1 : 0x8A */

/*10*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */

/*11*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */

/*12*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */

/*13*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

/*14*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID2 : 0x92 */

/*15*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */

/*16*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */

/*17*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */

/*18*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

/*19*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID3 : 0x1A */

/*20*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */

/*21*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */

/*22*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */

/*23*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */

/*24*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */

/*25*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_8, 8); /* ALMC */

/*26*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

/*27*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

/* Data ID6 : 0x32 */ /*write to eeprom */

/*28*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_2, 8); /* ADF */

/*29*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_3, 8); /* EDF */

/*30*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */

/*31*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);

/* Data IDD : 0xEA */ /*read from eeprom */

/*32*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_2, 8);/* ADF */

/*33*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */

/*34*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);

/*response to write/read eeprom */

/*35*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1); /* halt 1 bit for update */

/*36*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6); /* halt some bits for waiting */

/*37*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */

/*38*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_2, 8); /* ADF */

/*39*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_3, 8);/* EDF */

/*40*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */

/*41*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);

以上代码为根据流程图编写的新指令预设内容。

/* [4] command table */

command_table_config.cmd_min_value= 0x02u;

command_table_config.cmd_max_value= 0x02u;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 2;

command_table_config.instr_idx[6] = 05;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_0,&command_table_config);

command_table_config.cmd_min_value= 0x8Au;

command_table_config.cmd_max_value= 0x8Au;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 2;

command_table_config.instr_idx[6] = 10;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_1,&command_table_config);

command_table_config.cmd_min_value= 0x92u;

command_table_config.cmd_max_value= 0x92u;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 2;

command_table_config.instr_idx[6] = 15;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_2,&command_table_config);

command_table_config.cmd_min_value= 0x1Au;

command_table_config.cmd_max_value= 0x1Au;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 2;

command_table_config.instr_idx[6] = 20;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_3,&command_table_config);

command_table_config.cmd_min_value= 0x32u;

command_table_config.cmd_max_value= 0x32u;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 28;

command_table_config.instr_idx[6] = 35;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL,SEI_CMD_TABLE_4,&command_table_config);

command_table_config.cmd_min_value= 0xEAu;

command_table_config.cmd_max_value= 0xEAu;

command_table_config.cmd_mask_value= 0xFFu;

command_table_config.instr_idx[0] = 32;

command_table_config.instr_idx[6] = 35;

sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_5,&command_table_config);

以上代码为根据流程图编写的新指令匹配表。

/* [5] state transition config */

/* latch0 */

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= false;

state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;

state_transition_config.instr_ptr_value= 2;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_1_2, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_2_3, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_3_0,&state_transition_config);

state_transition_latch_config.enable= true;

state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;

state_transition_latch_config.delay= 0;

sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0,&state_transition_latch_config);

/* [6] state transition config */

/* latch1 */

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= false;

state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;

state_transition_config.instr_ptr_value= 35;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL,SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_1_2, &state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_2_3,&state_transition_config);

state_transition_config.disable_clk_check= true;

state_transition_config.disable_txd_check= true;

state_transition_config.disable_rxd_check= true;

state_transition_config.disable_timeout_check= true;

state_transition_config.disable_instr_ptr_check= true;

sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_3_0, &state_transition_config);

state_transition_latch_config.enable= true;

state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;

state_transition_latch_config.delay= 0;

sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1,&state_transition_latch_config);

锁存器0配置为执行完指令2(读取位置信息CF的0.5us锁存点)后进行位置锁存;

锁存器1配置为执行完指令35(操作EEPROM指令CRC后0.5us锁存点)后进行EEPROM操作;

voidisr_sei(void)

{

uint32_tdelta;

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event);

sei_set_data_rewind(BOARD_SEI,SEI_DAT_9);

sample_latch_tm1= sei_get_latch_time(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0);

mock_pos++;

if(mock_pos> 0x00FFFFFF) {

mock_pos= 0;

mock_rev++;

if(mock_rev> 0x00FFFFFF) {

mock_rev= 0;

}

}

sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);

sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_rev);

sei_set_data_value(BOARD_SEI, SEI_DAT_4, 0x00);

sei_set_data_value(BOARD_SEI, SEI_DAT_6, 0x17);

sei_set_data_value(BOARD_SEI, SEI_DAT_8, 0x00);

delta= (sample_latch_tm1> sample_latch_tm2) ? (sample_latch_tm1- sample_latch_tm2) : (sample_latch_tm1- sample_latch_tm2+ 0xFFFFFFFFu);

printf("CMD:%#x, SF:%#x, ST:%#x, ENID:%#x,MT:%#x, ALMC:%#x, CRC:%#x,sample_tm1:%u,sample_tm2:%u, sample_interval:%dus\n",

sei_get_command_value(BOARD_SEI, BOARD_SEI_CTRL),

sei_get_data_value(BOARD_SEI, SEI_DAT_4),

sei_get_data_value(BOARD_SEI, SEI_DAT_5),

sei_get_data_value(BOARD_SEI, SEI_DAT_6),

sei_get_data_value(BOARD_SEI, SEI_DAT_7),

sei_get_data_value(BOARD_SEI, SEI_DAT_8),

sei_get_data_value(BOARD_SEI, SEI_DAT_9),

sample_latch_tm1, sample_latch_tm2, delta/ (clock_get_frequency(BOARD_MOTOR_CLK_NAME) / 1000000));

sample_latch_tm2= sample_latch_tm1;

}

elseif(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch1_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch1_event);

uint32_tcmd= sei_get_command_value(BOARD_SEI, SEI_CTRL_1);

if(cmd== 0x32u) {

uint32_taddr= sei_get_data_value(BOARD_SEI, SEI_DAT_2);

uint32_tdata= sei_get_data_value(BOARD_SEI, SEI_DAT_3);

if(addr== 127) {

eeprom_page= data;

}else{

eeprom[eeprom_page][addr] = data;

}

}elseif(cmd== 0xEAu) {

uint32_taddr= sei_get_data_value(BOARD_SEI, SEI_DAT_2);

sei_set_data_value(BOARD_SEI, SEI_DAT_3, eeprom[eeprom_page][addr]);

}

}

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event);

sei_set_command_rewind(BOARD_SEI, BOARD_SEI_CTRL);

printf("WDG!\n");

}

if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event)) {

sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event);

printf("TRX Error!\n");

}

}

在中断内,sei_irq_latch0_event分支处理位置锁存信息;sei_irq_latch1_event根据收到的指令信息对eeprom数组和地址页进行操作,更新数据/设置回复数据。

5 小结

相信通过以上针对SEI的讲解,及对多摩川协议、例程代码的分析与修改,读者对SEI有了更深的认识,希望开发者可以用好SEI模块,加速项目开发与落地。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编码器
    +关注

    关注

    45

    文章

    3641

    浏览量

    134473
  • 异步通信
    +关注

    关注

    1

    文章

    57

    浏览量

    10131
  • 异步通讯
    +关注

    关注

    0

    文章

    12

    浏览量

    7473
  • 先楫半导体
    +关注

    关注

    10

    文章

    214

    浏览量

    2117
收藏 人收藏

    评论

    相关推荐

    HPM5300系列SEI串行编码器接口:如何设置通讯协议(上)

    01.串行编码器接口SEI的应用场景SEI串行编码器接口是HPM单片机独创的通信接口外设,可以在同一个硬件接口上实现不同类型的串行通信协议的数据收发。是5300精确位置系统的一部分,可以与系统中的其它外设协同工作。主要应用场景:
    的头像 发表于 12-20 08:17 2336次阅读
    HPM5300系列<b class='flag-5'>SEI</b>串行编码器接口:如何设置<b class='flag-5'>通讯</b><b class='flag-5'>协议</b>(上)

    MODBUS通讯协议---通讯

    、 //************************************************************************************************************* //主题: Modbus协议--
    发表于 11-11 17:25

    labview支持通讯协议有哪些?

    请问现在想用labview和三菱的Q03UDE CPU基于以太网的通讯,三菱手册里面说该CUP支持 MC协议 和套间字通讯方式,请问LABVIEW有自带的这两种
    发表于 08-07 14:36

    求助,所搭的IP软核的通讯协议与总线支持通讯协议(ICB)不同怎么转换?

    所搭的IP软核的通讯协议与总线支持通讯协议(ICB)不同怎么转换?
    发表于 08-17 07:05

    绝对式编码器特点和应用

    本文简要介绍日本多绝对式 编码器 应用特点和接口方法,其中重点介绍产品通信协议和硬件接口威廉希尔官方网站 以及专用的接收芯片AU5561 应用方法。
    发表于 06-16 15:45 73次下载
    <b class='flag-5'>多</b><b class='flag-5'>摩</b><b class='flag-5'>川</b>绝对式编码器特点和应用

    机器人通讯网络的路由协议的研究

    本文是关于机器人通讯网络的路由协议的研究
    发表于 11-03 18:44 33次下载

    存储硬盘协议支持

    协议支持可谓是统一存储率先受到人们关注的要素,一直以来专家都认为对协议支持能够给用户带来非
    发表于 08-02 14:23 894次阅读
    存储硬盘<b class='flag-5'>多</b><b class='flag-5'>协议</b><b class='flag-5'>支持</b>

    一主从Modbus通讯协议的无线通讯

    该方案可适用于3台以上西门子PLC,S7-200或S7-200Smart之间实现一主从Modbus通讯协议的无线通讯
    发表于 06-04 09:50 1.1w次阅读
    一主<b class='flag-5'>多</b>从Modbus<b class='flag-5'>通讯</b><b class='flag-5'>协议</b>的无线<b class='flag-5'>通讯</b>

    米家智能模网关今日开售,支持三种无线通讯协议

    12月11日消息,日前,小米宣布推出米家智能模网关,支持Zigbee、Wi-Fi、蓝牙&蓝牙Mesh等三种无线通讯协议,售价129元,将于12月12日0点开售。
    的头像 发表于 12-12 15:23 4894次阅读

    PLC无线传输模块支持哪些协议

    PLC无线通讯终端支持西门子PPI协议、三菱专用协议、汇N:N协议、欧姆龙HOST Link
    的头像 发表于 02-18 09:13 3212次阅读
    PLC无线传输模块<b class='flag-5'>支持</b>哪些<b class='flag-5'>协议</b>

    编码器资料

    常用规格编码器资料
    发表于 07-01 15:31 12次下载

    世强先进与电阻制造商SEI签署合作协议

    近日,世强先进与SEI(世达柏科技)签署合作协议SEI授权世强先进代理旗下电阻、电感、多层陶瓷电容等全线产品。
    的头像 发表于 08-02 14:07 1523次阅读

    工程监测通道振弦模拟信号采集仪VTN的AABB 通讯协议

    方法更容易,便于进行快速测试。 AABB 通讯协议支持单寄存器读写两种指令。 (1) 读取单个寄存器 工程监测通道振弦模拟信号采集仪VTN的AABB
    的头像 发表于 02-20 10:32 565次阅读
    工程监测<b class='flag-5'>多</b>通道振弦模拟信号采集仪VTN的AABB <b class='flag-5'>通讯</b><b class='flag-5'>协议</b>

    HPM6200系列微控制器PLA实战—

    电子发烧友网站提供《HPM6200系列微控制器PLA实战—.pdf》资料免费下载
    发表于 09-19 15:48 1次下载
    HPM6200系列微控制器PLA实战—<b class='flag-5'>多</b><b class='flag-5'>摩</b><b class='flag-5'>川</b>

    三菱PLC支持哪些通讯协议

    。在三菱PLC的应用过程中,通讯协议起着至关重要的作用,它决定了PLC与其他设备之间的数据交换方式。本文将详细介绍三菱PLC支持通讯协议.
    的头像 发表于 07-01 10:20 5221次阅读