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

news2024/9/22 17:38:51

目录

一、工作原理

二、接口图

三、真值表

四、编写思路

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.coloradmin.cn/o/2046930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8.16 mysql读写分离架构+MyCAT实现读写分离

1、读写分离的目的 数据库负载均衡&#xff1a; 当数据库请求增多时&#xff0c;单例数据库不能够满足业务 需求。需要进行数据库实例的扩容。多台数据库同时相 应请求。也就是说需要对数据库的请求&#xff0c;进行负载均衡 但是由于数据库服务特殊原因&#xff0c;数据库扩容…

《SPSS零基础入门教程》学习笔记——05.模型入门

文章目录 5.1 回归模型5.2 分类模型5.3 降维和刻度模型5.4 生存分析和时间序列模型 5.1 回归模型 线性回归&#xff08;分析 -> 回归 -> 线性&#xff09;曲线估计&#xff08;分析 -> 回归 -> 曲线估计&#xff09; 二元Logistic回归&#xff08;分析 -> 回归…

Centos7主机带宽限速

需求&#xff1a;最近有两个主机经常把带宽打满。咨询了阿里云无法对内网网卡做限制。这边想使用linux默认的TC工具。 限速之前测试带宽。这时带宽有 168.4MB/s。 ]# scp filebeat-8.8.2-x86_64.rpm 172.116.47.54:/root/100% 26MB 168.4MB/s 00:00 1. 限制出站&#xff0…

数据结构入门——08排序

1.排序 1.1什么是排序 排序是一种操作&#xff0c;通过比较记录中的关键字&#xff0c;将一组数据按照特定顺序&#xff08;递增或递减&#xff09;排列起来。排序在计算机科学中非常重要&#xff0c;因为它不仅有助于数据的快速检索&#xff0c;还能提高其他算法的性能。 1…

PostgreSQL-03-入门篇-过滤数据

文章目录 1. WHEREWHERE 子句概述WHERE 子句示例1) 使用 WHERE 子句和等于运算符 () 示例2) 使用 WHERE 子句和 AND 运算符示例3) 使用 WHERE 子句和 OR 运算符示例4) 使用 WHERE 子句和 IN 运算符示例5) 使用 WHERE 子句和 LIKE 运算符示例6) 将 WHERE 子句与 BETWEEN 运算符一…

自动化运维---ansible

ansible是一种由Python开发的自动化运维工具&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能。 特点: 部署简单 默认使用ssh进行管理&#xff0c;基于py…

【LLM大模型论文日更】| 大型语言模型用于模拟搜索用户行为

论文&#xff1a;https://arxiv.org/pdf/2403.09142代码&#xff1a;未开源机构&#xff1a;中国人民大学高瓴人工智能研究院领域&#xff1a;信息检索发表&#xff1a;SIGIR2024 短文 Abstract 由于成本效益和可再现性方面的优势&#xff0c;用户模拟已成为信息检索系统面向用…

Python酷库之旅-第三方库Pandas(084)

目录 一、用法精讲 351、pandas.Series.str.isdigit方法 351-1、语法 351-2、参数 351-3、功能 351-4、返回值 351-5、说明 351-6、用法 351-6-1、数据准备 351-6-2、代码示例 351-6-3、结果输出 352、pandas.Series.str.isspace方法 352-1、语法 352-2、参数 3…

【 亿邦动力网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

钢铁百科:美标A633GrC材质分析、A633GrC正火状态、A633GrC材料性能

A633GrC钢板是一种美国ASTM标准的高强度低合金结构钢板&#xff0c;字母"A"代表钢&#xff08;Steel&#xff09;&#xff0c;数字"633"表示该材料的牌号&#xff0c;而"GrC"表示该材料为高强度低合金钢&#xff08;High Strength Low Alloy&…

wtv-next 宝塔更新教程

数据库升级办法 输入用户名密码&#xff0c;点执行 程序升级办法 文件后缀看清楚&#xff0c;是amd64、arm64。etc 目录下是配置文件&#xff0c;按照格式往下加就行。 回到刚才那个页面 先点停止&#xff0c;再点启动

【大模型部署及其应用 】RAG检索技术和生成模型的应用程序架构:RAG 使用 Meta AI 的 Llama 3

目录 RAG检索技术和生成模型的应用程序架构1. **基本概念**2. **工作原理**3. **RAG的优势**4. **常见应用场景**5. **RAG的挑战**6. **技术实现**参考RAG 使用 Meta AI 的 Llama 3亲自尝试运行主笔记本与文档应用聊天关键架构组件1. 自定义知识库2. 分块3. 嵌入模型4. 矢量数据…

GAMES104:08游戏引擎的动画技术基础-学习笔记

文章目录 一&#xff0c;动画技术简介动画技术的挑战 二&#xff0c;2D游戏动画技术2.1 精灵动画&#xff08;sprite animation&#xff09;2.2 Live2D 三&#xff0c;3D游戏动画技术3.1 基于层次的刚体动画3.2 顶点动画3.3 Morph Target Animation3.4 蒙皮动画3.4.1 2D蒙皮动画…

房产系统源码开发

一、开发需求&#xff1a; 信息录入与管理&#xff1a;系统需要支持各种数据的录入&#xff0c;这包括但不限于客户信息、房源信息、员工信息、合同信息和财务信息等。这些数据是房产系统的基础&#xff0c;对于后续的信息查询、分析和共享至关重要。信息查询与检索&#xff1…

Ports Number of field profile samples 参数设置

Ports Number of field profile samples 参数设置 正文正文 在进行 Port 仿真时,通常我们会对 port 端口中的光束模式进行设定,很多时候我们会遇到一个名为 Number of field profile samples 的参数,如下图所示: 如果去官方论坛查看解释,往往会被搞得云里雾里。这个参数…

什么是AR、VR、MR、XR?

时代背景 近年来随着计算机图形学、显示技术等的发展&#xff0c;视觉虚拟化技术得到了广泛的发展&#xff0c;并且越来越普及化&#xff0c;慢慢的也走入人们的视野。目前市场上视觉虚拟化技术的主流分为这几种 VR、AR、MR、XR。这几项技术并不是最近才出现的&#xff0c;VR的…

RabbitMQ 的工作原理

下面是rabbitmq 的工作原理图解 1、客户端连接到消息队列服务器&#xff0c;打开一个channel。 2、客户端声明一个exchange&#xff0c;并设置相关属性。 3、客户端声明一个queue&#xff0c;并设置相关属性。 4、客户端使用routing key&#xff0c; 在exchange和queue 之间…

FreeBSD 针对OpenSSH 高危漏洞发布紧急补丁

近日&#xff0c;FreeBSD 项目的维护者针对OpenSSH 高危漏洞发布了紧急补丁。该漏洞被追踪为 CVE-2024-7589&#xff0c;CVSS 得分为 7.4&#xff08;最高分为 10.0&#xff09;。通过利用该漏洞&#xff0c;黑客能够在权限提升的情况下远程执行任意代码。 根据上周发布的一份…

Hive3:常用的虚拟列(Virtual Columns)

一、作用 虚拟列是Hive内置的可以在查询语句中使用的特殊标记&#xff0c;可以查询数据本身的详细参数。 Hive目前可用3个虚拟列&#xff1a; INPUT__FILE__NAME&#xff1a;显示数据行所在的具体文件BLOCK__OFFSET__INSIDE__FILE&#xff1a;显示数据行所在文件的偏移量ROW…

HarmonyOS开发:跨应用数据共享详解

目录 前言跨应用数据共享的重要性HarmonyOS的数据共享能力相关的基本概念跨应用数据共享的数据管理具体实现跨应用数据共享延伸&#xff1a;数据共享的安全和隐私结语 前言 现在的移动操作系统中&#xff0c;应用之间的数据共享已成为提升用户体验和实现功能互补的重要手段&a…