差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
digi:arm-embedded:ccmp2:encoder_dts [2025/03/31 15:54] robindigi:arm-embedded:ccmp2:encoder_dts [2025/03/31 23:44] (当前版本) robin
行 70: 行 70:
 </code> </code>
 而pinctrl处也要相应修改一些内容,注意AF8改为AF2,待查文档确认,并在节点名别名处添加encoder以增加识别度,偏置也改为上拉等。 而pinctrl处也要相应修改一些内容,注意AF8改为AF2,待查文档确认,并在节点名别名处添加encoder以增加识别度,偏置也改为上拉等。
 +
 +AF可以通过下面查:Alternate function mapping
 +
 +https://wiki.st.com/stm32mpu/wiki/GPIO_internal_peripheral
 +
 <code> <code>
 ccmp25_timers1_ch3_4_pins: ccmp25-timers1-ch3_4-encoder { ccmp25_timers1_ch3_4_pins: ccmp25-timers1-ch3_4-encoder {
行 87: 行 92:
                      <STM32_PINMUX('D', 8, ANALOG)>;                      <STM32_PINMUX('D', 8, ANALOG)>;
         };         };
 +};
 +</code>
 +
 +下面讲解如何确认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表格里描述到:
 +{{:digi:arm-embedded:ccmp2:pasted:20250331-164714.png}}
 +
 +<code>
 +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
 +</code>
 +也就是,定时器如果是作为capture,compare或PWM,随便用一个通道即可,但如果要用作quadrature encoder inputs,则需要用CH1和CH2, 而PLC开发板的设计文件中,大部是用CH3和CH4,需原厂确认是否有问题
 +
 +假定CH3,CH4也可用作编码器接口,我目录改了一下:
 +
 +<code>
 +/*  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 */
 + };
 + };
 +</code>
 +
 +用户空间的验证如下:
 +<code>
 +# 启用计数器
 +echo 1 > /sys/bus/counter/devices/counter0/enable
 +
 +# 读取当前计数值
 +cat /sys/bus/counter/devices/counter0/count
 +
 +# 旋转编码器后,观察数值变化
 +</code>
 +
 +-----
 +进阶:
 +使用cubeMX验证,发现:TIM1里可以选择conbined channels的方式是encoder mode,并且它用了:PD11,PE12,即TIM1_CH1,TIM1_CH2 , 
 +{{:digi:arm-embedded:ccmp2:pasted:20250331-201456.png}}
 +
 +如果不用encoder mode,则每个通道可选为input capture direct mode, 也许这才是原先想要的方式:
 +{{:digi:arm-embedded:ccmp2:pasted:20250331-201625.png}}
 +
 +补充:用cubeMX生成的设备树发现,和smartIOMUX一样,是用AF8,因此,如果用ch3,ch4只能用input capture direct mode来操作, 
 +
 +根据AI给的说法:虽然也可以把将CH3和CH4配置为输入捕获模式,在中断或轮询中读取捕获值,计算脉冲数和方向,或是通过软件逻辑模拟正交编码器的计数和方向判断,但这样实时性较差,占用CPU资源,适合低速场景。
 +因此能用上专用的encoder的模式肯定效率高一些
 +
 +一个完整的电机控制的设备树的例子参考如下,可根据板子情况参考:
 +<code>
 +/ {
 +    // 配置时钟(确保定时器时钟源正确)
 +    clocks {
 +        // 假设TIM1使用APB2时钟(需根据实际时钟树配置)
 +        tim1_clk: tim1-clk {
 +            #clock-cells = <0>;
 +            compatible = "fixed-clock";
 +            clock-frequency = <16000000>; // 16 MHz(示例)
 +        };
 +    };
 +
 +    // PWM控制器配置(TIM1通道1用于PWM输出)
 +    pwm_motor: pwm-motor {
 +        compatible = "st,stm32-pwm";
 +        #pwm-cells = <3>;
 +        reg = <0x40010000 0x400>; // TIM1寄存器基地址
 +        clocks = <&tim1_clk>;
 +        status = "okay";
 +
 +        pwm@0 {
 +            // 通道1(TIM1_CH1)作为PWM输出
 +            reg = <0>;
 +            st,pwm-channels = <1>; // 使用通道1
 +            st,pwm-period-ns = <50000>; // PWM周期50us(20kHz)
 +        };
 +    };
 +
 +    // 编码器接口(TIM3通道1和2用于正交编码器)
 +    encoder_motor: encoder-motor {
 +        compatible = "st,stm32-timer-encoder";
 +        reg = <0x40000400 0x400>; // TIM3寄存器基地址
 +        st,encoder-mode = <1>; // 编码器模式:TI1和TI2均捕获边沿
 +        st,capture-channels = <1 2>; // 使用通道1和2(TIM3_CH1和TIM3_CH2)
 +        clocks = <&rcc TIM3_K>;
 +        status = "okay";
 +    };
 +
 +    // 霍尔传感器GPIO中断(可选,用于无刷电机换相)
 +    hall_sensor {
 +        compatible = "gpio-keys";
 +        hall-u {
 +            label = "HALL_U";
 +            gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>; // PA0为霍尔U相信号
 +            linux,code = <0x100>; // 自定义输入事件
 +        };
 +        hall-v { /* 类似配置 */ };
 +        hall-w { /* 类似配置 */ };
 +    };
 +
 +    // ADC配置(用于电流采样,可选)
 +    adc_motor: adc-motor {
 +        compatible = "st,stm32-adc";
 +        reg = <0x48003000 0x400>; // ADC1基地址
 +        vref-supply = <&vrefbuf>;
 +        st,adc-channels = <5 6>; // 使用ADC1_IN5和IN6(电流检测)
 +        status = "okay";
 +    };
 }; };
 </code> </code>