当前位置: 首页 > news >正文

Linux驱动入门实验班——步进电机模块驱动(附百问网视频链接)

目录

一、工作原理

二、接口图

三、真值表

四、编写思路

1.构造file_operations结构体

2.编写入口函数

3.编写出口函数

4.编写write函数

五、bug记录

六、源码

课程链接


一、工作原理

步进电机由定子和转子两部分组成。定子上有多组线圈,通常称为相,每组相通常由两个电流互相反向的线圈组成。转子上有多个磁极,通常称为步进角。

当电流通过其中一组线圈时,该线圈就会产生一个磁场。由于线圈中电流方向的变化,磁场也会随之改变方向。转子的磁极会受到相邻线圈磁场的作用而进行转动。当电流改变到下一组线圈时,转子又会根据新的磁场方向进行转动。通过不断改变电流的方向和大小,可以控制步进电机的转动角度。

二、接口图

三、真值表

下图为驱动芯片MX1508输入输出真值表:

可以看出OUTB1、OUTA1不能同时输出1(只能同时为高阻态),因步进电 机的公共端是接到5V的,可以用高阻态代替1,OUTB2、OUTA2也是如此。 根据电机激励序列推出驱动芯片的输出序列;根据MX1508输入输出真值表, 可以从输出信号序列推出输入序列;由电机驱动芯片的输入推导出 100ASK_IMX6ULL的GPIO的信号序列:

四、编写思路

1.构造file_operations结构体

static struct file_operations gpio_key_drv = {.owner	 = THIS_MODULE,.write   = motor_write,
};

2.编写入口函数

先每个申请引脚,然后每个引脚配置为输出模式,初始电平为低电平。

注册file_operations结构体

  • register_chrdev()
  • class_create()
  • device_create()

3.编写出口函数

卸载驱动程序,释放gpio

  • device_destroy()
  • class_destroy()
  • unregister_chrdev()
  • gpio_free()

4.编写write函数

应用层会传入步进数和延时时间,根据步进数的正负判断电机转动的方向。

static int g_motor_pin_ctrl[8]= {0x2,0x3,0x1,0x9,0x8,0xc,0x4,0x6}; 

根据步进数按正或反顺序从该数组中取出值,对引脚进行设置。

完成转动后,将引脚输出电平都设置为低电平。

五、bug记录

请求到gpio后,忘记给gpio设置输出。 

六、源码

驱动

#include "asm-generic/gpio.h"
#include "asm/gpio.h"
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>struct gpio_desc{int gpio;int irq;char *name;int key;struct timer_list motor_timer;
};static struct gpio_desc gpios[4] = {{115, 0, "motor_gpio0", },{116, 0, "motor_gpio1", },{117, 0, "motor_gpio2", },{118, 0, "motor_gpio3", },
};static int major;
static struct class *motor_class;
static int g_motor_pin_ctrl[8]= {0x2,0x3,0x1,0x9,0x8,0xc,0x4,0x6};static ssize_t motor_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{int kernel_buf[2];int ret;int step;int index = 0;int i;if (size != 8){return -EINVAL;}ret = copy_from_user(kernel_buf, buf, size);if (kernel_buf[0] > 0){for (step = 0; step < kernel_buf[0]; step++){for (i = 0; i < 4; i++){gpio_set_value(gpios[i].gpio, g_motor_pin_ctrl[index] & (1 << i) ? 1 : 0);}index--;mdelay(kernel_buf[1]);if (index < 0){index = 7;}}}else{kernel_buf[0] = 0 - kernel_buf[0];for (step = 0; step < kernel_buf[0]; step++){for (i = 0; i < 4; i++){gpio_set_value(gpios[i].gpio, g_motor_pin_ctrl[index] & (1 << i) ? 1 : 0);}index++;mdelay(kernel_buf[1]);if(index > 7){index = 0;}}}for (i = 0; i < 4; i++){gpio_set_value(gpios[i].gpio, 0);}return 8;
}static struct file_operations motor_drv = {.owner = THIS_MODULE,.write = motor_drv_write,
};static int __init motor_drv_init(void)
{int i ;int count = sizeof(gpios) / sizeof(gpios[0]);for (i = 0; i < count; i++){gpio_request(gpios[i].gpio, gpios[i].name);gpio_direction_output(gpios[i].gpio, 0);}major = register_chrdev(0, "motor_drv", &motor_drv);motor_class = class_create(THIS_MODULE, "motor_class");if (IS_ERR(motor_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "motor_drv");return PTR_ERR(motor_class);}device_create(motor_class, NULL, MKDEV(major, 0), NULL, "motor_drv");return 0;
}static void __exit motor_drv_exit(void)
{int i ;int count = sizeof(gpios) / sizeof(gpios[0]);device_destroy(motor_class, MKDEV(major, 0));class_destroy(motor_class);unregister_chrdev(major, "motor_drv");for (i = 0; i < count; i++){gpio_free(gpios[i].gpio);}
}module_init(motor_drv_init);
module_exit(motor_drv_exit);MODULE_LICENSE("GPL");

应用


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <stdlib.h>static int fd;/** ./button_test /dev/motor -100  1**/
int main(int argc, char **argv)
{int buf[2];int ret;/* 1. 判断参数 */if (argc != 4) {printf("Usage: %s <dev> <step_number> <mdelay_number>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}buf[0] = strtol(argv[2], NULL, 0);buf[1] = strtol(argv[3], NULL, 0);ret = write(fd, buf, 8);close(fd);return 0;
}

课程链接

46_步进马达控制原理与接线 (100ask.net)icon-default.png?t=N7T8https://video.100ask.net/p/t_pc/course_pc_detail/video/v_636f7261e4b0276efeaffac6?product_id=p_634cbce4e4b00a4f37500252&content_app_id=&type=6


http://www.mrgr.cn/news/2281.html

相关文章:

  • QT-计算器
  • 数据结构(6_2_3)——十字链表法和多重领接表
  • 32位入门级MCU(ARM Cortex-M3内核)STM32F103系列
  • 计算机基础知识复习8.14
  • 4款AI 生成 PPT的工具,帮你赶上演示文稿的新趋势!
  • HTML静态网页成品作业(HTML+CSS)——花主题介绍网页设计制作(1个页面)
  • Tomcat 部署与优化
  • 探索生成式AI在文档处理中的应用:llm Whisperer
  • 数字媒体产业发展现状剖析,洞悉数字产业园的创新之举
  • HCIP | 三层架构
  • 如何在HTML中创建链接?什么是CSS定位?什么是CSS优化?
  • JavaScript语法基础之流程结构(顺序、选择、循环结构)
  • XXX【5】观察者模式
  • 你是如何克服编程学习中的挫折感的?(-@-^-0-)
  • 数学建模预测类—【多元线性回归】
  • C# 不一样的洗牌算法---Simd指令
  • 只用一个 HTML 元素可以写出多少形状?——伪元素篇(上)
  • 微服务架构
  • 网易云音乐崩了!冲上热搜第一
  • Swin-Transformer论文阅读