西玛电机
本文档的指导下是编写一个Linux步进电机驱动程序的前提下:
1、理解Linux内核模块编程。
2、了解步进电机的原理和驱动电路。
3、可以在51单片机(或其他??CPU)驱动步进电机。
答:运行环境
硬件平台:tq2440发展局(CPU、s3c2440)
软件平台:linux2.6.30.4内核
编译工具:横臂-Linux-GCC编译器
2:基本内核函数与驾驶有关
1、动态分配设备号
Intalloc_chrdev_region(unsignedIntbaseminordev_t*dev,unsignedInt数,constchar*名称)
戴夫:分配的设备数量
baseminor:注册数倍的起始值
数:设备号登记的数量
名称:设备的名称
返回值:0表示成功,消极的错误代码
2、设备号的取消
空白unregister_chrdev_region(dev_t,unsignedint数)
应该取消:设备号起始值吗
应取消数:数量的设备号码吗
3、创建一个字符设备和初始化
在开车,字符设备实际上是一个结构,如下
Structcdev{
//指出,Conststructfile_operations*行动;操作的设备的结构
}
Structfile_operations{
结构模块*所有者;//this_module一般
Ssize_t(*读)(struct文件*,char__user*,size_t,loff_t*);
写ssize_t(*)(struct文件*,char__user*,size_t,loff_t*);
int(*)开放(structinode*,struct文件*);
int(*)(structinode*,struct文件*);
Int(*ioctl)(structinode*,*结构文件,unsignedInt,长);
一些成员列表*/
S3c2410_gpio_pullup(en,0);
S3c2410_gpio_pullup(ck,0);
S3c2410_gpio_pullup(cw,0);
S3c2410_gpio_setpin(en,1);
S3c2410_gpio_setpin(ck,1);
S3c2410_gpio_setpin(cw,1);
}
//以下函数相应的驱动程序
静态intopen_motor(structinode*inode,struct文件*文件)
静态intrelease_motor(structinode*inode,structfile*文件)
静态ssize_tread_motor(结构文件,文件*char__user*buf,size_t计数,loff_t*pos)
{
Returncount;
}
静态ssize_twrite_motor(结构文件,文件*char__user*buf,size_t计数,loff_t*pos)
{
Returncount;
}
静态ssize_tioctl_motor(structinode*inode,structfile*文件,unsignedintCMD,长数据)
{
开关(CMD)
{
Casecw:
{
S3c2410_gpio_setpin(cw,0);//
打破;
}
Caseccw:
{
S3c2410_gpio_setpin(cw1);//逆转
打破;
}
Casepowerup:
{
S3c2410_gpio_setpin(en,1);//可以驱动电路
打破;
}
Casepowerdown:
{
S3c2410_gpio_setpin(en,0);//驱动电路是被禁止的
打破;
}
Caseck0:
{
S3c2410_gpio_setpin(ck,0);//设置时钟线是低水平
打破;
}
Caseck1:
{
S3c2410_gpio_setpin(ck1);//设置时钟线是高水平
打破;
}
默认值:
返回-einval;
}
返回0;
}
静态结构file_operations据=
{
老板=this_module,
开放=open_motor,
=release_motor发布,
阅读=read_motor,
的。写=write_motor,
ioctl=ioctl_motor,
};
静态dev_tdevn;///创建一个设备号
静态结构cdev电动机;///创建一个字符设备
静态int_main(空白)
{
init();
如果(alloc_chrdev_region(及amp;devn,0、1、“motor&”),lt;0)///申请号
Printk(,,,lt;0,gt;allocdevn失败\n&”);
其他的
{
Printk(,,,lt;0,gt;主要=%d\n&”,主要(devn));
Printk(,,,lt;0,gt;小=%d\n&”,小(devn));
}
Cdev_init(及amp;公司,amp;据);///初始化字符设备
如果(cdev_add(及amp;公司devn1)及lt;0)////注册字符???
Printk(,,,lt;0,gt;addmotor失败\n&”);
其他的
Printk(,,,lt;0,gt;addmotor成功\n&”);
返回0;
}
静态__exit空白_leave(空白)
{
Cdev_del(及amp;公司);////取消字符设备
Unregister_chrdev_region(devn,1);////取消号码
}
module_init(_main);
Module_exit(_leave);
2、编译驱动程序makefile
Ifneq($(kernelrelease))
Obj-m:=。o
其他的
Kdir:=/home/工具/Linux-2.6.30.4/#开发板中使用的内核文件
#kdir:=/lib/模块/2.6.27.5-117。fc10。I686/构建
全部:
让-(kdir)加元=$(PWD)模块
清洁:
Rm-f*。Ko**。Mod。O*。国防部,C*。Symvers
#的其他
#obj-m:=。o
Endif
3、测试程序
#include#include#include#include#include#include//#include#definecw0
1#define公约
#定义powerup2
#定义powerdown3
#定义ck04
#定义ck15
Int主要(Intgeshu,char**zifu)
{
Intfb=58;
无符号字符b=5;
如果((fb=开放(和“/dev/motor&”,o_rdwr))==1)
{
Perror(和“open&”);
返回-1;
}
Printf(和“fd=%d\n&”,神奇动物)。
如果(ioctl(fbpowerup)及lt;0)////电
Printf(和“ioctlpowerup失败\n&”);
如果(ioctl(fb,连续波),lt;0)////
Printf(和“ioctlcw失败\n&”);
而(1)
{////驱动时钟
如果(ioctl(fbck0)及lt;0)
Printf(和“ioctlstep失败\n&”);
Usleep(2000);
如果(ioctl(fb,对照),lt;0)
Printf(和“ioctlstep失败\n&”);
Usleep(2000);
}
ioctl(fbpowerdown);////权力
关闭(神奇动物)。
返回0;
}
五、编制安装过程
1、交叉编译过程
2、安装和测试过程中
在NFS程序调试。
六、问题和解决方案
在写作的过程中遇到司机主要是三个问题:
1、在测试程序中,如果((fb=开放(及“/dev/motor&”,o_rdwr))==1)到如果(fb=开放(及“/dev/motor&”,o_rdwr)==1),导致总是得不到想要的结果,最后绝望的(我两天),无意中发现了错误。
2、开发板高度的3.3v,输出和步进电机驱动电路需要高水平为5.0v,刚刚开始使用74hc32芯片将3.3v至5.0v???但是失败了,因为74年hc32与TTL兼容水平。后来lm339比较器,3.3v至5.0v,转换成功。
s3c2410_gpio_cfgpin(s3c2410_gpb0s3c2410_gpb0_outp);在这个函数首先,找不到代表的输出函数宏(马赫/硬件。Jh,没有说,也可以在互联网上找不到)。然后试着s3c2410_gpb0_outputs3c2410_gpb0_output,失败了。以后想去用整数代替宏,写在以下表格s3c2410_gpio_cfgpin(s3c2410_gpb0,1),发现这只适用于gpg0嘴,可能不同销s3c2410_gpxn_outp对应于一个不同的数字。最后,无意中看见了outpBBS。
7、理解
不包括准备时间的知识,从开始到完成驱动程序编写驱动程序,总共四天。回想起来,过程中遇到的问题,突然觉得原来这个过程可能更顺利,因为一些小问题(如上图)。但仔细想想,我受益匪浅,这些小问题了。例如,上面提到的第一个问题,在开始的时候,以为是司机的问题,然后反复使用核函数,查看、修改或改变另一种方式写。正因为如此,我使用的内核函数,结构,从一开始的不熟悉到熟练。对于第三个问题,为了找到答案,我主要看所有的马赫所有头文件目录,并学到了很多的知识。塞翁,???马后面厄运会好运。问题虽小,但是寻找答案的过程中你可以学到很多知识。
西玛电机 西玛电机 西玛电机
Arduino学习笔记】【uln2003apg步进电机控制代码