这是本文档旧的修订版!
编码器DTS探究
背景:ST的PLC参考设计板对应的设备树源码位于:https://github.com/peyoot/ccmp25_dt/blob/scarthgap/ccmp25-plc.dts ,编码器设备树的部分只是按早期官方文档的一个示例修改,需要进一步修改并验证其可用性。 官方文档可能有更新,LPTIM见:https://wiki.st.com/stm32mpu/wiki/LPTIM_device_tree_configuration#On_STM32MP2_series ,而 TIM DEVICE见https://wiki.st.com/stm32mpu/wiki/TIM_device_tree_configuration#On_STM32MP2_series
当前的设计,以counter_DI_1_2为例
&timers1 { status = "okay"; /* USER CODE BEGIN timers1 */ /delete-property/dmas; /delete-property/dma-names; /* USER CODE END timers1 */ counter_DI_1_2 { /* remove pwm10,pwm11 and add this */ pinctrl-names = "default", "sleep"; pinctrl-0 = <&ccmp25_timers1_ch3_4_pins>; pinctrl-1 = <&ccmp25_timers1_ch3_4_sleep_pins>; status = "okay"; };
和 <code> ccmp25_timers1_ch3_4_pins: ccmp25-timers1-ch3_4 { pins { pinmux = <STM32_PINMUX('D', 9, AF8)>, /* TIM1_CH3_PWM */ <STM32_PINMUX('D', 8, AF8)>; /* TIM1_CH4_PWM */ bias-disable; }; };
ccmp25_timers1_ch3_4_sleep_pins: ccmp25-timers1-ch3_4_sleep { pins { pinmux = <STM32_PINMUX('D', 9, ANALOG)>, /* TIM1_CH3_PWM */ <STM32_PINMUX('D', 8, ANALOG)>; /* TIM1_CH4_PWM */ }; }; </code>
注意,上面这个配置并未验证,在AI的协助下,需要的知识点包括:
timers1: timer@address { compatible = "st,stm32mp25-timers"; /* ...其他公共资源... */ pwm { compatible = "st,stm32mp25-pwm"; }; // PWM功能 timer@0 { compatible = "st,stm32mp25-timer-trigger"; }; // 触发功能 counter { compatible = "st,stm32mp25-timer-counter"; }; // 编码器/计数器功能 }; // counter子节点专门用于编码器/计数器功能,stm32mp25-timer-counter是STM32MP25系列的新绑定方式,而非以前的stm32-timer-encoder
下面,以这个编码器节点为例,可能需要的改变包括: 1、增加在counter内的compatible说明; 2、counter内增加一些描述
// 编码器模式参数 st,counter-mode = "encoder"; // 设置为编码器模式 st,encoder-mode = <3>; // 模式3:双通道边沿计数(四倍频), st,prescaler = <0>; // 无预分频 st,filter = <0>; // 输入滤波器关闭,这句可先不用,信号抖动可增加滤波器,最大滤波(需根据信号频率调整),如st,filter = <15> // 通道映射(CH3和CH4) st,channel-config { //当方向相反时,调整st,encoder-mode或交换CH3/CH4的引脚 ch3-mode = "input"; // CH3作为编码器输入A ch4-mode = "input"; // CH4作为编码器输入B
而pinctrl处也要相应修改一些内容,注意AF8改为AF2,待查文档确认,并在节点名别名处添加encoder以增加识别度,偏置也改为上拉等。
ccmp25_timers1_ch3_4_pins: ccmp25-timers1-ch3_4-encoder { pins { // PD9: TIM1_CH3, PD8: TIM1_CH4 pinmux = <STM32_PINMUX('D', 9, AF2)>, // CH3复用AF2 <STM32_PINMUX('D', 8, AF2)>; // CH4复用AF2 bias-pull-up; // 根据编码器类型选择上拉 drive-push-pull; // 推挽输出驱动 slew-rate = <1>; // 高速模式(>50MHz信号) }; }; ccmp25_timers1_ch3_4_sleep_pins: ccmp25-timers1-ch3_4_sleep-encoder { pins { pinmux = <STM32_PINMUX('D', 9, ANALOG)>, // 睡眠时设为模拟 <STM32_PINMUX('D', 8, ANALOG)>; }; };
下面讲解如何确认I/O pin alternate-function multiplexer and mapping,在处理器的文档RM0457 Rev 5中,page1368开始为GPIO相关文档,page1370处说到: Each I/O pin has a multiplexer with up to 16 alternate function inputs (AF0 to AF15), that can be configured through GPIOx_AFRL (for pin 0 to 7) and GPIOx_AFRH (for pin 8 to 15):
对应到这里引脚为8,9,则是看GPIOx_AFRH,在page1385处为GPIOx_AFRL,在page1386处为GPIOx_AFRH。
*疑点**
在文档的timers中,即64,65章节,pins and internal signals表格里描述到:
即
Each channel can be used for capture, compare or PWM. TIM_CH1 and TIM_CH2 can also be used as external clock (below 1/4 of the tim_ker_ck clock), external trigger and quadrature encoder inputs. TIM_CH1, TIM_CH2 and TIM_CH3 can be used to interface with digital hall effect sensors
也就是,定时器如果是作为capture,compare或PWM,随便用一个通道即可,但如果要用作quadrature encoder inputs,则需要用CH1和CH2, 而PLC开发板的设计文件中,大部是用CH3和CH4,需原厂确认是否有问题
假定CH3,CH4也可用作编码器接口,我目录改了一下:
/* encoder interface for DI1 and DI2 */ counter_DI_1_2 { compatible = "st,stm32mp25-timer-counter"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&ccmp25_timers1_ch3_4_pins>; pinctrl-1 = <&ccmp25_timers1_ch3_4_sleep_pins>; status = "okay"; st,counter-mode = "encoder"; st,encoder-mode = <3>; st,prescaler = <0>; st,channel-config { ch3-mode = "input"; ch4-mode = "input"; }; }; ccmp25_timers1_ch3_4_pins: ccmp25-timers1-ch3_4-encoder { pins { pinmux = <STM32_PINMUX('D', 9, AF2)>, /* TIM1_CH3_PWM */ <STM32_PINMUX('D', 8, AF2)>; /* TIM1_CH4_PWM */ bias-pull-up; drive-push-pull; slew-rate = <1>; }; }; ccmp25_timers1_ch3_4_sleep_pins: ccmp25-timers1-ch3_4_sleep-encoder { pins { pinmux = <STM32_PINMUX('D', 9, ANALOG)>, /* TIM1_CH3_PWM */ <STM32_PINMUX('D', 8, ANALOG)>; /* TIM1_CH4_PWM */ }; };
用户空间的验证如下:
# 启用计数器 echo 1 > /sys/bus/counter/devices/counter0/enable # 读取当前计数值 cat /sys/bus/counter/devices/counter0/count # 旋转编码器后,观察数值变化