从0开始学linux韦东山教程Linux驱动入门实验班(6)
本人从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