本人从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