以Tamagawa协议为例,详解SEI在异步通信中的用法

2024-07-03 先楫半导体 微信公众号
串行编码器,先楫半导体 串行编码器,先楫半导体 串行编码器,先楫半导体 串行编码器,先楫半导体

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.1 SEI关键概念

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)字段为命令,其含义如下图:


1719793980839043129.png

1719793980763019930.png

1719793981942048344.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 数据读取指令格式


数据读取过程:

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

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

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

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

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


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


2.2 EEPROM读指令格式


多摩川编码器为客户提供了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.3 EEPROM写指令格式

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

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

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

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

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


读写时序要求如下:


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 : send CF */

   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手册。


void isr_sei(void)

{

    uint32_t delta;


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:%d us\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指令支持开发过程中,绘制的流程图。

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

uint32_t eeprom_page= 0;

uint32_t eeprom[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操作;


void isr_sei(void)

{

uint32_t delta;


  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:%d us\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;

    }

  else if (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_t addr = sei_get_data_value(BOARD_SEI, SEI_DAT_2);

  uint32_t data = sei_get_data_value(BOARD_SEI, SEI_DAT_3);

  if(addr == 127) {

        eeprom_page = data;

}else{

  eeprom[eeprom_page][addr] = data;

    }

}else if(cmd == 0xEAu) {

            uint32_t addr = 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模块,加速项目开发与落地。

授权代理商:世强先进(深圳)科技股份有限公司
技术资料,数据手册,3D模型库,原理图,PCB封装文件,选型指南来源平台:世强硬创平台www.sekorm.com
现货商城,价格查询,交期查询,订货,现货采购,在线购买,样品申请渠道:世强硬创平台电子商城www.sekorm.com/supply/
概念,方案,设计,选型,BOM优化,FAE技术支持,样品,加工定制,测试,量产供应服务提供:世强硬创平台www.sekorm.com
集成电路,电子元件,电子材料,电气自动化,电机,仪器全品类供应:世强硬创平台www.sekorm.com
  • +1 赞 0
  • 收藏
  • 评论 0

本文由赵优秀转载自先楫半导体 微信公众号,原文标题为:经验分享 | SEI异步通讯—多摩川协议支持,本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关研发服务和供应服务

评论

   |   

提交评论

全部评论(0

暂无评论

相关推荐

先楫半导体HPM5300系列MCU-SEI串行编码器接口:如何设置通讯协议(上)

SEI 串行编码器接口是HPM单片机独创的通信接口外设,可以在同一个硬件接口上实现不同类型的串行通信协议的数据收发,是5300精确位置系统的一部分,可以与系统中的其它外设协同工作。本文介绍HPM5300系列SEI串行编码器接口如何设置通讯协议。

2024-02-21 -  设计经验 代理服务 技术支持 采购服务

【经验】先楫半导体MCU HPM6750使用JLINK调试下如何进行串口打印配置

在使用JLINK调试先楫半导体HPM6750EVK2开发板调试时遇到不知如何使用SEGGER Embedded Studio (以下简称SES)内置的虚拟串口打印工具,本文介绍正确配置串口打印工具的步骤。

2023-06-30 -  设计经验 代理服务 技术支持 采购服务

先楫HPM5361EVK开发板测评

上海先楫半导体举办的HPM5361EVK开发板试用活动圆满结束,广大工程师和爱好者们踊跃参与此次试用并提交报告。HPM5361EVK是基于先楫HPM5300系列高性能RISC-V内核MCU的一款开发板。本文介绍先楫HPM5361EVK开发板测评。

2024-05-15 -  设计经验 代理服务 技术支持 采购服务

Z85C30 CMOS单片机串行通信控制器产品简介

描述- Zilog Z85C30是一款CMOS SCC串行通信控制器,具备低功耗、双通道、多协议操作等特点。它支持异步和同步通信模式,包括NRZ、NRZI、FM数据编码,以及SDLC/HDLC模式。该控制器具有丰富的功能,如波特率发生器、数字锁相环、晶振振荡器等,可满足多种串行通信应用需求。此外,它还支持DMA控制器,并具备CRC生成和检查功能。

型号- Z85C3016PSC,Z85C3008VSC,Z85C3008PSC,Z85C3010PSC,Z85C30,Z85C3016VSC,Z85C3010VSC

02/01  - ZILOG  - 商品及供应商介绍 代理服务 技术支持 采购服务

实验室4a:通用异步收发器

描述- 本资料为Digilent公司提供的实验手册,主要介绍了如何使用PIC32MX370微控制器进行异步串行通信协议的应用。实验内容包括设置PC终端监控、使用PIC32MX370发送和接收ASCII编码的文本字符串,并在工作站显示器和Basys MX3 LCD上显示。资料详细说明了实验所需的硬件和软件,包括Basys MX3训练板、工作站计算机、USB线缆、Microchip MPLAB X IDE、PLIB库、XC32交叉编译器和PuTTY终端仿真程序。实验还涉及UART的基本概念、通信协议、数据流图、软件控制流程图以及测试方法。

型号- PIC32MX370

April 25, 2017  - DIGILENT  - 技术文档

使用MCP2120进行红外通信

描述- 本文介绍了MCP2120红外通信模块的应用。MCP2120能够将异步串行数据流编码成红外格式脉冲,并解码接收到的红外脉冲为UART格式串行数据。文章详细阐述了MCP2120的硬件连接、编码解码过程、数据速率选择以及与微控制器的接口方式。此外,还提供了使用MCP2120的示例代码,展示了如何通过硬件和软件方式设置数据速率,以及如何实现红外通信。

型号- MCP2120

2006/01/01  - ADVANCED DIGITAL CHIPS  - 应用笔记或设计指南

PI7C9X794高性能1.62V至3.6V四通道UART,带64字节FIFO

描述- PI7C9X794是一款高性能的1.62V至3.6V四通道UART,具有64字节FIFO,适用于高带宽通信系统。该设备具有5V容错的串行输入,单中断输出,全局中断源寄存器,5G“平坦”UART寄存器,同时初始化所有UART通道,通用命令驱动的16位定时器/计数器,睡眠模式带唤醒指示,高度集成以节省空间。每个UART独立控制,具有16C550兼容的5G寄存器集,64字节的发送和接收FIFO,可编程的TX和RX FIFO触发级别,自动RTS/CTS或DTR/DSR硬件流控制,自动Xon/Xoff软件流控制,RS485 HDX控制输出,RS485自动地址检测,红外(IrDA 1.0/1.1)数据编码器/解码器,可编程数据速率和预分频器,最高8Mbps的串行数据速率,支持晶振振荡器(高达24MHz)或外部时钟(高达80MHz)输入,内置上电复位电路。

型号- PI7C9X794,PI7C9X794FCEX

October 2017  - DIODES  - 数据手册  - Rev 2-2

32位RISC微控制器TMPM3H组(2)参考手册产品信息(PINFO-M3H(2))版本3.2

描述- 本资料为TMPM3H系列32位RISC微控制器的产品信息手册,详细介绍了该系列微控制器的特性、外设功能、寄存器配置等。内容包括外围功能信息,如触发选择器、看门狗定时器、振荡频率检测器、调试接口、闪存、DMA控制器、电机控制电路、编码器输入电路、模数转换器、数模转换器、比较器、电压检测电路、定时器事件计数器、实时时钟、异步串行通信电路、I2C接口、串行外设接口、远程控制信号预处理电路、数字噪声滤波电路、CRC计算电路、RAM奇偶校验和调整电路等。

型号- TMPM3H

2019-02-28  - TOSHIBA  - 用户指南  - Rev. 3.2

PI7C9X752高性能1.62V至3.6V双UART,带64字节FIFO

描述- PI7C9X752是一款由Diodes Incorporated公司生产的1.62V至3.6V双通道UART,具有64字节FIFO,适用于高带宽通信系统。该产品具有5V容错串行输入、可编程睡眠模式、自动唤醒功能、独立控制的UART通道、DMA和中断生成、RS485控制输出、自动地址检测、红外数据编码/解码器、可编程数据速率、高达16Mbps的串行数据速率、内置上电复位电路、无铅且符合RoHS标准。

型号- PI7C9X752FAEX,PI7C9X752

April 2019  - DIODES  - 数据手册  - Rev 3-2

ComSync/PCI-104用户手册

描述- 本手册介绍了Connect Tech的ComSync/PCI-104双通道同步/异步串行适配卡,适用于PCI-104总线系统。该卡提供高性能和可靠的通信,支持多种电气接口、协议和编码方案,适用于工业和嵌入式应用。手册详细说明了硬件安装、软件开发、硬件信息、DMA支持、中断、系统框图、全双工模式、时钟控制、线接口模式、串行设备连接、V.28连接、RS-422/V.11连接、ComSync/PCI-104同步时钟、环回连接器和连接器引脚分配等内容。

型号- PLX-9054,Z16C32,COMSYNC/PCI-104,CB001,CBG001,PCI-104

October 31, 2008  - CONNECT TECH  - 用户指南  - Revision 0.00

教程:向消费者和工业应用程序开发人员介绍XGATE模块应用说明

描述- 本资料介绍了Freescale Semiconductor的XGATE模块,旨在提高嵌入式应用的处理速度和响应能力。XGATE模块能够并行处理中断指令,减轻主CPU的负担。资料详细阐述了XGATE模块的概念、功能、编程方法以及在实际应用中的性能表现,包括多通道PWM、串行通信协议处理、CAN网关、编码器、同步/异步串行通信、队列管理、LCD显示控制和加密算法等。此外,还讨论了XGATE模块的编程技巧和性能预期,为开发者提供了实用的指导。

型号- MC9S12XDP512,S12X,MC9S12XA256,MC9S12XA512,MC9S12XDT256,MC9S12XD256,MC9S12XDT512,HCS12X

3/2006  - NXP  - 应用笔记或设计指南  - Rev. 0

先楫半导体hpm_sdk v1.6.0全新上线!新增HPM6E80产品支持

先楫半导体hpm_sdk v1.6.0上线!新增HPM6E80产品支持。HPM6E00系列MCU是一款高性能、高实时以太互联,RISC-V双核微控制器。HPM6E00系列提供多达4端口千兆以太交换模块,支持TSN,并且支持3端口EtherCAT从站控制器,以及32路高分辨率PWM输出,高精度运动控制系统,可以在工业自动化领域实现基于高实时性,低延时以太网的高性能伺服电机控制,机器人运动控制等应用。

2024-07-03 -  原厂动态 代理服务 技术支持 采购服务

HPM6800EVK 用户使用手册

描述- 本手册为上海先楫半导体HPM6800系列高性能微控制器HPM6800EVK的用户使用手册。内容包括HPM6800EVK的硬件电路介绍、软件开发套件(SDK)的使用指南、调试出错常见原因及解决方案等。手册详细介绍了HPM6800EVK的硬件设计、电路模块、软件开发环境搭建、开发工具使用、调试方法等,为用户提供了全面的使用指导。

型号- HPM6800EVK,HPM6800 系列,HPM6800

2024/03/17  - 先楫半导体  - 用户指南  - Rev1.1 代理服务 技术支持 采购服务

【IC】先楫半导体最新款高性能MCU HPM5301,搭载单核32位RISC-V处理器,主频高达360MHz

先楫半导体于2023年11月24日宣布推出高性能HPM5300系列MCU最新款——HPM5301芯片。这款MCU搭载单核32位RISC-V处理器,采用QFN48封装,是迄今为止先楫推出的最简单易用的产品。该芯片的开发板HPM5301EVKLite也同步上市。

2023-11-25 -  产品 代理服务 技术支持 采购服务
展开更多

电子商城

查看更多

品牌:先楫半导体

品类:高性能微控制器

价格:¥33.9025

现货: 250

品牌:先楫半导体

品类:高性能微控制器

价格:¥25.7561

现货: 130

品牌:先楫半导体

品类:高性能微控制器

价格:¥20.4879

现货: 119

品牌:先楫半导体

品类:高性能微控制器

价格:¥34.7561

现货: 116

品牌:先楫半导体

品类:高性能微控制器

价格:¥40.1220

现货: 83

品牌:先楫半导体

品类:开发板

价格:¥326.8293

现货: 1

品牌:先楫半导体

品类:32位高性能微控制器

价格:

现货: 0

品牌:先楫半导体

品类:32位高性能微控制器

价格:

现货: 0

品牌:先楫半导体

品类:32位高性能微控制器

价格:

现货: 0

品牌:先楫半导体

品类:32位高性能微控制器

价格:

现货: 0

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

现货市场

查看更多

暂无此商品

海量正品紧缺物料,超低价格,限量库存搜索料号

服务

查看更多

弹簧针(pogo pin)连接器定制

可定制连接器的间距范围1.25mm~4.5mm、单列/双列列数、焊尾/表面贴装/浮动式等安装方式、镀层、针数等参数,插拔寿命达100万次以上。

最小起订量: 1 提交需求>

VC均温板散热器定制

可来图定制均温板VC尺寸50*50mm~600*600 mm,厚度1mm~10mm,最薄0.3mm。当量导热系数可达10000W/M·K,散热量可达10KW, 功率密度可达50W/cm²。项目单次采购额需满足1万元以上,或年需求5万元以上。

提交需求>

查看更多

授权代理品牌:接插件及结构件

查看更多

授权代理品牌:部件、组件及配件

查看更多

授权代理品牌:电源及模块

查看更多

授权代理品牌:电子材料

查看更多

授权代理品牌:仪器仪表及测试配组件

查看更多

授权代理品牌:电工工具及材料

查看更多

授权代理品牌:机械电子元件

查看更多

授权代理品牌:加工与定制

世强和原厂的技术专家将在一个工作日内解答,帮助您快速完成研发及采购。
我要提问

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

研发客服
商务客服
服务热线

联系我们

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

投诉与建议

E-mail:claim@sekorm.com

商务合作

E-mail:contact@sekorm.com

收藏
收藏当前页面