扩展板振动马达驱动移植

1.实验原理

打开扩展板原理图对照扩展板可以看到扩展板有 1 个振动马达 M1 ,如下图:

 由上图可见可通过 TIM16_CH1 电平改变控制电路的通断从而驱动线性马达。

查看原理图可知 TIM16_CH1 对应 PF6 ,查看芯片手册可知 PF6 可以作为 PWM TIMER16 的通道 1 使用,本文实现如何通过 PWM 驱动振动马达:

2.实验步骤

1) 导入交叉编译工具链

linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environm ent-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

2) 内核配置

内核中为振动马达提供了标准的驱动,只要在内核中配置对应选项即可,驱动路径为:
drivers/input/misc/pwm- vibra.c
执行 make menuconfig 配置内核对应选项
linux@ubuntu:$ make menuconfig
Device Drivers --->
        Input device support --->
                [*] Miscellaneous devices --->
                        <*> PWM vibrator support

3) 修改设备树

参考 linux 内核文档:
Documentation/devicetree/bindings/pwm/pwm-stm32.txt
Documentation/devicetree/bindings/input/pwm-vibrator.txt
修改设备树文件:
arch/arm/boot/dts/stm32mp157a-fsmp1a-extended.dts
由于 timers16 stm32mp151.dtsi 中已完成定义,这里需要在原有基础添加与硬件对应的 相关信息,在文件 stm32mp157a-fsmp1a-extended.dts 末尾继承并添加 timers16 相关内容:
&timers16 {
    /* spare dmas for other usage */
    /delete-property/dmas;
    /delete-property/dma-names;
    status = "okay";
    pwm16: pwm {
        pinctrl-0 = <&pwm16_pins_a>;
        pinctrl-1 = <&pwm16_sleep_pins_a>;
        pinctrl-names = "default", "sleep";
        #pwm-cells = <2>;
        status = "okay";
    };
    timer@16 {
        status = "disabled";
    };
};
仿照设备树对于 pwm 管脚的配置添加 timers16 pwm 输出管脚配置,在 stm32mp157a-fsmp1a-extended.dts 文件 pinctrl 节点中添加 pwm16 管脚信息,红色字体内容为添加内容:
&pinctrl {
        ……
        pwm16_pins_a: pwm16-0 {
                pins {
                        pinmux = <STM32_PINMUX('F', 6, AF1)>; /* TIM16_CH1 */
                        bias-pull-down;
                        drive-push-pull;
                        slew-rate = <0>;
                };
        };
        pwm16_sleep_pins_a: pwm16-sleep-0 {
                pins {
                        pinmux = <STM32_PINMUX('F', 6, ANALOG)>; /* TIM16_CH1 */
                };
       };
};
最后在根节点下添加振动马达驱动对应节点:
vibrator {
        compatible = "pwm-vibrator";
        pwms = <&pwm16 0 4000000>;
        pwm-names = "enable";
        direction-duty-cycle-ns = <10000000>;
};

4) 重新编译内核和设备树文件

linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040

5) 更新系统内核和设备树

6) 测试

系统启动后可以查看目录 /dev/input
root@fsmp1a:~# ls /dev/input/
by-path event0 event1 event2
如果系统中有多个 input 设备,这里可能会有很对 eventx ,确定哪个 event 文件是我们的 设备文件,可以通过查看/dev/input/by-path 或查看 dmesg 系统启动信息确认:
查看 by-path 目录下文件
root@fsmp1a:~# ls /dev/input/by-path/ -l
total 0
lrwxrwxrwx 1 root root 9 May 30 08:43 platform-40013000.i2c-event -> ../event2
lrwxrwxrwx 1 root root 9 Jun 30 07:40 platform-beeper-event -> ../event0
lrwxrwxrwx 1 root root 9 Jun 30 07:40 platform-vibrator-event -> ../event1
由显示信息可以确认 event1 是振动马达的设备文件
编写测试程序测试:
pwm-vibrator.c
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/ioctl.h>

int main(const int argc, const char **argv)
{
    int fd;

    if (argc != 2) {
        printf("usage: %s <device-file>\n", argv[0]);
        return 1;
    }

    fd = open(argv[1], O_RDWR);
    
    if (fd < 0) {
        printf("Error opening file '%s': %s\n", argv[1], strerror(errno));
        return 1;
    }

    int num_effects;
    
    if (ioctl(fd, EVIOCGEFFECTS, &num_effects) < 0) {
        printf("Error getting number of effects playable at the same time: %s\n",
        strerror(errno));
        return 1;
    }

    printf("%d effects playable at the same time\n", num_effects);

    struct ff_effect effect;
    effect.type = FF_RUMBLE,
    effect.id = -1,
    effect.u.rumble.strong_magnitude = 0xFFFF; //调节振动强度
    effect.u.rumble.weak_magnitude = 0;
    effect.replay.length = 3000; //调节振动时长 ms
    effect.replay.delay = 0;

    if (ioctl(fd, EVIOCSFF, &effect) < 0) {
        printf("Error creating new effect: %s\n", strerror(errno));
        return 1;
    }

    printf("New effect ID: %d\n", effect.id);

    struct input_event play = {
        .type = EV_FF,
        .code = effect.id,
        .value = 1
    };

    if (write(fd, (const void*) &play, sizeof(play)) < 0) {
        printf("Error writing effect to file: %s\n", strerror(errno));
        return 1;
    }

    printf("Wrote effect\n");
    sleep(3);
    return 0;
}
交叉编译测试程序并将编译好的测试程序下载到板子上,执行程序如下:
root@fsmp1a:~# ./vibrator_test /dev/input/event1
16 effects playable at the same time
New effect ID: 0
Wrote effect
这时可以听到振动马达振动的声音。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐的记事本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值