在电机控制中,实时获取电机转子位置是非常重要的。通过监测电机轴或机械设备运动的位置可以计算电机转速。当电机转动时,编码盘传感器(Encoder)会发出类似于正交PWM波的高低电平信号,对此信号进行解码,可以得到电机转动角度及方向。
DSC系列MCU的Quad Timer(TMR)外设可以对正交编码信号解码,有些客户使用LPC55XX系列也需要解码,本文用PLU模块对Encoder的信号解码,用计数器计数解码信号,进而得到转子位置及速度。
1. 标准推拉输出
DSP系列MCU的Quad Timer(TMR)外设可以对正交编码信号进行解码,如下:
在进行解码时,其实是两个信号发生电平翻转时进行计数,那么可以理解为对这两个信号做异或运算,对结果信号上升沿和下降沿进行计数,就可实现解码功能。利用可编程逻辑单元PLU对正交编码信号做异或运算,利用CTIMER计数器对输出信号进行计数,同样可以达到Quad Timer(TMR)解码效果。
2. 配置PLU与CTIMER
PLU(Programmable Logic Unit),即可编程逻辑单元,可创建小型组合与时序逻辑电路。LPC804与LPC55XX的PLU在使用上是完全相同的,包含了6个输入、8个输出、26个5输入查找表(LUT)、4个触发器(state Flip-Flops),详细介绍如下: https://www.nxpic.org.cn/module/forum/thread-622667-1-1.html 用PIO_19与PIO_20产生类似于正交编码信号,将两路信号输入PLU模块的IN3与IN4,进行异或运算,再输出到OUT5,将OUT5信号输入到CTIMER计数器进行计数,如下:
以LPC55S69-EVK开发板为例,具体的引脚使用如下:
配置PLU与CTIMER引脚,如下:
打开PLU与CTIMER时钟,如下:
添加PLU外设,如下:
配置CTIMER外设,在main.c文件中添加CTIMER初始化,上升沿与下降沿都可触发计数器。假如电机转一圈触发4096次计数器,电机在旋转60°时要控制电机变相,当计数器值为4096/6 = 682时,触发一次ctimer中断,在中断处理函数中控制电机,如下:
uint32_t motor_flag = 0; const ctimer_config_t CTIMER0_config = { .mode = kCTIMER_IncreaseOnBothEdge, .input = kCTIMER_Capture_0, .prescale = 0 }; const ctimer_match_config_t CTIMER0_Match_0_config = { .matchValue = 681, .enableCounterReset = true, .enableCounterStop = false, .outControl = kCTIMER_Output_NoAction, .outPinInitState = false, .enableInterrupt = true }; /*Single callback functions definition */ ctimer_callback_t CTIMER0_callback[] ={ctimer0_match0_callback}; static void CTIMER0_init(void) { /* CTIMER0 peripheral initialization */ CTIMER_Init(CTIMER0, &CTIMER0_config); /* Interrupt vector CTIMER0_IRQn priority settings in theNVIC. */ NVIC_SetPriority(CTIMER0_IRQn, 0); /* Match channel 0 of CTIMER0 peripheral initialization*/ CTIMER_SetupMatch(CTIMER0, kCTIMER_Match_0, &CTIMER0_Match_0_config); CTIMER_RegisterCallBack(CTIMER0,CTIMER0_callback, kCTIMER_SingleCallback); CTIMER_StartTimer(CTIMER0); } void ctimer0_match0_callback(uint32_t flags) { motor_flag++; }
下载PLU configure tool,下载链接如下:
https://www.nxp.com/mcu-plu-config-tool 打开PLU配置工具,选择原理图设计,做一个异或运算,如下:
点击菜单栏File->Export->PLU source file将其导出为C文件,将C文件的内容复制到main函数中,如下:
PLU->LUT[4].INP_MUX[0] = 0x00000003; /* IN3 (IN3) */ PLU->LUT[4].INP_MUX[1] = 0x00000004; /* IN4 (IN4) */ PLU->LUT[4].INP_MUX[2] = 0x0000003F; /* default */ PLU->LUT[4].INP_MUX[3] = 0x0000003F; /* default */ PLU->LUT[4].INP_MUX[4] = 0x0000003F; /* default */ PLU->LUT_TRUTH[4] = 0x66666666; /* XOR01 (XOR01) STD 2INPUT XOR */ PLU->OUTPUT_MUX[5] = 0x00000004; /* LUT4 (XOR01) ->OUT5 */
利用GPIO产生正交编码信号,CTimer进行计数,当计数到682时会触发中断进入回调函数,计数器值(TC)会自动清零,重新计数,如下:
while(1) { GPIO_PortToggle(GPIO,0, 1u <TC; }
3. 测试结果 逻辑分析仪测试结果如下:
调试时,计数器的值如下所示:
相关文章