从0开始学linux韦东山教程Linux驱动入门实验班(6)

发布于:2025-07-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

  本人从0开始学习linux,使用的是韦东山的教程,在跟着课程学习的情况下的所遇到的问题的总结,理论虽枯燥但是是基础。本人将前几章的内容大致学完之后,考虑到后续驱动方面得更多的开始实操,后续的内容将以韦东山教程Linux驱动入门实验班的内容为主,学习其中的代码并手敲。做到锻炼动手能力的同时钻研其中的理论知识点。
摘要:这篇文档主要介绍的是步进电机的控制,其实步进电机就是引脚的高低电平控制,所以没有特别深入的内容,此章节较短。
摘要关键词:步进电机驱动

本文详细介绍以下问题,如果你遇到了以下问题,看看我的方案能否解决。

步进电机

1.引脚配置

1.原理图参考引脚设置

1.引脚对应原理图
由于本人没有买他的拓展板,只好看原理图来找引脚的分布,然后发现原理图对不上只能看封装图。
在这里插入图片描述
想着确定图片中红色框的引脚位置,找半天没找着j5,说实在的原理图画的有点不好。
在这里插入图片描述
这部分也是自己采购的模块,使用的引脚和它一样的,使用的是GPIO4_19、20、21、22。
其实这个章节没有什么很难的地方,就是输入高低电平控制引脚。

在这里插入图片描述
本人使用的步进电机驱动模块如图所示。IN1,IN2,IN3,IN4也就是连接对应的GPIO引脚。步进电机有防呆接口直接连接就行。注意跳帽不用拔。
输入以下命令行即可。

make clean
bear make
ctrl+h
arm-buildroot-linux-gnueabihf-gcc  编译设置
make
adb push gpio_drv.ko button_test root

越到后面代码没有啥好讲解的了,更多的是引脚功能配置和逻辑了

驱动代码

#include <linux/module.h>
#include <linux/poll.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>
#include <linux/delay.h>
struct gpio_desc{
	int gpio;
    char *name;

} ;

static struct gpio_desc gpios[] = {
    {115, "motor_gpio0", },
    {116, "motor_gpio1", },
	{117, "motor_gpio2", },
	{118, "motor_gpio3", },
};

/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_class;

/* int buf[2];
*  buf[0] = 步进的次数,》0:逆时针;《 0:顺时针
*  buf[1] = mdelay的时间
*/
// 马达引脚设置数组
static int g_motor_pin_ctrl[8] = {0x2,0x3,0x1,0x9,0x8,0xc,0x4,0x6};
static int g_motor_index = 0;

void set_pin_for_motor(int index)
{
	int i ;
	for(i = 0;i < 4;i++)
	{
		gpio_set_value(gpios[i].gpio,g_motor_pin_ctrl[index] & (1<<i) ? 1:0);
	}
}
static ssize_t motor_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
    int ker_buf[2];
    int err;
	int step;
    if (size != 8)
        return -EINVAL;

    err = copy_from_user(ker_buf, buf, size);
    if (ker_buf[0] > 0)
	{
		/*逆时针旋转*/
		for(step = 0;step<ker_buf[0];step++)
		{
			set_pin_for_motor(g_motor_index);
			mdelay(ker_buf[1]);
			g_motor_index--;
			if(g_motor_index == -1)
			g_motor_index = 7 ;
		}
	}
	else
	{
		ker_buf[0] = 0 - ker_buf[0];
		/*顺时针旋转*/
		for(step = 0;step<ker_buf[0];step++)
		{
			set_pin_for_motor(g_motor_index);
			mdelay(ker_buf[1]);
			g_motor_index ++;
			if(g_motor_index == 8)
			g_motor_index = 0 ;
		}
	}
    return 2;    
}




/* 定义自己的file_operations结构体                                              */
static struct file_operations gpio_key_drv = {
	.owner	 = THIS_MODULE,
	.write   = motor_drv_write,

};


/* 在入口函数 */
static int __init motor_drv_init(void)
{
    int err;
    int i;
    int count = sizeof(gpios)/sizeof(gpios[0]);
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	for (i = 0; i < count; i++)
	{		
		err = gpio_request(gpios[i].gpio,gpios[i].name);
		gpio_direction_output(gpios[i].gpio,0);
	}

	/* 注册file_operations 	*/
	major = register_chrdev(0, "100ask_gpio_key", &gpio_key_drv);  /* /dev/gpio_desc */

	gpio_class = class_create(THIS_MODULE, "100ask_gpio_key_class");
	if (IS_ERR(gpio_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "100ask_gpio_key");
		return PTR_ERR(gpio_class);
	}

	device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "motor"); /* /dev/motor */
	
	return err;
}

/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数
 */
static void __exit motor_drv_exit(void)
{
    int i;
    int count = sizeof(gpios)/sizeof(gpios[0]);
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	device_destroy(gpio_class, MKDEV(major, 0));
	class_destroy(gpio_class);
	unregister_chrdev(major, "100ask_gpio_key");

	for (i = 0; i < count; i++)
	{
		gpio_free(gpios[i].gpio);
	}
}


/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */

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 | O_NONBLOCK);
	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;
}
rmmod gpio_drv.ko
[root@100ask:~]# insmod gpio_drv.ko
[root@100ask:~]# ./button_test /dev/motor 100 1 
[root@100ask:~]# ./button_test /dev/motor 100 1 
[root@100ask:~]# ./button_test /dev/motor 100 1

网站公告

今日签到

点亮在社区的每一天
去签到