1、概述
碰到光电编码器、磁编码器等,有时候传出来的位置信息为ABZ的方式,在S32K3里面通过TRGMUX、LCU、Emios结合的方式可以实现ABZ解码。
官方推荐方式为
也有另外一种图示
ABZ的是什么在前面的正交编码文章里面已经有了叙述,S32K芯片本身存在一定的缺陷,例如Z信号的接入,Z信号是每转动一个机械周期会发出一个脉冲,此时清除AB信号的脉冲计数值,防止累计误差,但是S32K3里面此功能并没有实现,需要通过外接emios触发边沿检测中断,在中断里面清除AB的计数器。
ABZ并显示如下
Trgmux的作用是功能路由
LCU进行真正的信号解析
Emios仅仅用来边沿计数或周期测量。
通常测量一段时间内的脉冲个数,叫做测频法,也就是M法
测量若干个脉冲的周期时间叫测周法,也就是T法
为了提高转速精度的测量,高速时候采用测频法,低速采用测周法。
对LCU来说,正交信号的上升沿与下降沿到达emios的时候均会计数,也就是通过示波器测出来的A或者B上升沿的4倍才是脉冲数,正转A计数,反转B计数。以此A-B既可以测量位置,又可以测量旋转方向。
LCU实现原理
从上图可以看出I0、I1作为ENC_PHA\B输入,经过LCU的LC模块做延时再输出其中下图的4倍,边沿也就是出来了,其实到emios的已经经过LCU处理后的了,只不过开发者无法监测而已。
2、SDK配置
2.1、IO配置
按照顺序,先把IO口与Trgnux连接起来
2.2、TRGMUX配置
使能TRGMUX
TRGMUX实例,针对S32K312这个只有一个。
将IO口路由到LCU,将IO输出到LCU
2.3、LCU配置
使能LCU模块,并开启LCU的同步与异步功能。
将解码功能放置在LCU1上
LCU的输入,从之前原理解析图里面可以看出,输入为I0\1、O0\1,所以下面的配置就逻辑清晰了
其中的Hardware input 与Mux Select分别表示如下图
LCU的输出
LUT的值,其实现在也不是特别明白,这个值的来源
2.4、Trgmux配置
将LCU的输出路由到Emios通道实现边沿计数
2.5、Emios配置
2.6、代码实现
初始化
/*Init Io*/
Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
/*Init Trgmux*/
Trgmux_Ip_Init(&Trgmux_Ip_xTrgmuxInitPB);
/* Initialize Lcu */
Lcu_Ip_Init(&Lcu_Ip_xLcuInitPB);
/* Initialize Emios0 */
Emios_Mcl_Ip_Init(0U, &Emios_Mcl_Ip_0_Config_BOARD_INITPERIPHERALS);
mios_Icu_Ip_Init(0U, &eMios_Icu_Ip_0_Config_PB);
Emios_Icu_Ip_EnableEdgeCount(0u, 5U); /*A Phase*/
Emios_Icu_Ip_EnableEdgeCount(0u, 6U); /*B Phase*/
/* Direct access register setting is needed due to missing feature in Configuration Tools. */
/* It is a known issue and will be fix in the later RTD releases */
IP_EMIOS_0->CH.UC[5].A = (uint32_t)0x1000U; /*0x1000 = 4096 this is main max count is 4096*/
IP_EMIOS_0->CH.UC[6].A = (uint32_t)0x1000U;
/* Assign eMIOS0_CH5 input to TRGMUX_OUT_36 */
IP_SIUL2->IMCR[53] = SIUL2_IMCR_SSS(3U); /*IMCR53 53 = 565%512 = 53 Reference S32K312_IOMUC.xlsx(S32K312_Input Muxing) */
/* Assign eMIOS0_CH6 input to TRGMUX_OUT_37 */
IP_SIUL2->IMCR[54] = SIUL2_IMCR_SSS(3U); /*IMCR53 54 = 566%512 = 54 SIUL = System Integration Unit Lite2 (SIUL2)*/
Lcu_Ip_SyncOutputValueType EncLcuEnable[6U];
EncLcuEnable[0].LogicOutputId = LCU_LOGIC_OUTPUT_6; /* Logic Instance 6 SDK configer ID this is logic ID*/
EncLcuEnable[0].Value = 1U;
EncLcuEnable[1].LogicOutputId = LCU_LOGIC_OUTPUT_7;
EncLcuEnable[1].Value = 1U;
EncLcuEnable[2].LogicOutputId = LCU_LOGIC_OUTPUT_8;
EncLcuEnable[2].Value = 1U;
EncLcuEnable[3].LogicOutputId = LCU_LOGIC_OUTPUT_9;
EncLcuEnable[3].Value = 1U;
Lcu_Ip_SetSyncOutputEnable(EncLcuEnable, 4U);
执行代码
counterCW = (uint16_t)(Emios_Icu_Ip_GetEdgeNumbers(0U, 5U)); /* CW counter */
counterCCW = (uint16_t)(Emios_Icu_Ip_GetEdgeNumbers(0U, 6U)); /* CCW counter */
清除计数值,在ICU里面已经有介绍,使用函数为
Emios_Icu_Ip_ResetEdgeCount(0,5); /*Clear A Edge Count*/
Emios_Icu_Ip_ResetEdgeCount(0,6); /*Clear B Edge Count*/
测试结果如下,边沿计数准确无误。