嵌入式系统是以应用为中心,以计算机技术为基础,并且软硬件可裁减,适用于应用系统对功能、可靠性、成本、体积、功耗等有严格要求的专用计算机系统[1].自20世纪70年代世界上个为嵌入式应用而设计的微处理器诞生以来,已在几十年的发展历程,如今嵌入式系统(embedded system)已经成为电子信息产业中增长力的一个分支。随着微电子技术的发展,嵌入式控制系统在工业生产智能化、自动化中的应用越来越普及。尤其手机、PAD、GSP、机顶盒等新兴产品的大量应用,嵌入式系统的市场正在以每年30%的速度递增,嵌入式系统的设计也成为软硬件工程师越来越关心的问题。
步进电机是工业控制中的一种常用执行部件,具有控制灵活、价格低等优点,因而在许多设备和装置中常被采用。嵌入式步进电机控制器就是将微处理器置于电机控制器中,使步进电机控制器能按设定的相数、拍数以及单个触发脉冲所走的步数,提供相应的控制逻辑。本文以Samsung公司的友善之譬S3C2440开发板为例,探讨如何使用嵌入式Linux开发字符设备驱动程序来驱动步进电动机。
1 硬件系统设计方案
控制系统由处理器、步进电机驱动器、步进电机3部分组成。
中央处理器(英文Central Processing Unit,CPU)是一台计算机的运算和控制。CPU、内部存储器和输入/输出设备是电子计算机三大部件。电脑中所有操作都由CPU负责读取指令,对指令译码并执行指令的部件。其功能主要是解释计算机指令以及处理计算机软件中的数据。所谓的计算机的可编程性主要是指对CPU的编程。 CPU由运算器、控制器和寄存器及实现它们之间联系的数据、控制及状态的总线构成。
处理器用友善之譬QQ2440V3开发板,内核为ARM920T.步进电机驱动器采用北京和利时电机技术有限公司(原四通电机)的SH-20403.驱动器共有四路输入信号:公共、脉冲信号输入、方向信号输入和脱机信号输入。驱动器的输入信号既可以采用共阳极也可以采用共阴极接线方式,使用共阳极模式时,应将输入信号的电源正极连接到公共端,将输入信号连接到对应的信号端子,信号低电平有效,此时对应的内部光耦导通,控制信号输入驱动器中;对应共阴极模式时,将输入信号的电源负极连接到公共端,信号高电平有效,我们采用的是共阳极接法。
2 步进电机驱动系统设计
Linux内核结构体系可分为:应用程序、库函数、操作系统(内核)、驱动程序。在Linux操作系统中,驱动程序是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,驱动程序是内核的一部分,它具有以下功能:
对设备初始化和释放:比如向内核注册这个程序,这样应用程序传入文件名时,内核才能找到相应的驱动程序。
对设备进行管理,包括实时参数设置以及提供对设备的操作接口。
读取应用程序传送给设备文件的数据并回送给应用程序请求的数据。
检测是处理设备出现的错误。
应用程序通过Linux系统的调用实现与内核通信。由于Linux中将设备当做文件处理,所以对设备进行操作的调用和对文件操作的操作类似,主要包括open()、read()、write()、ioctl()、close()等接口函数。应用程序发出系统调用命令后,会从用户态转到内核态,通过内核将openO等的系统调用转换成对物理设备的操作。在Linux中通过分层实现对物理设备的调用,这样使得内核的结构清晰,提高了模块化的独立性。
2.1 嵌入式Linux设备驱动程序的框架
Linux系统设备分成三种基本类型:字符设备、块设备、网络设备。每个模块通常实现其中某一种:字符模块、块模块或网络模块。
嵌入式设备驱动整体可分以下两部分:
(1)硬件设备接口层。这部分主要描述驱动程序与设备的交互。
(2)驱动与内核接口层,它实现驱动模块在Linux内核的注册加载与卸除工作。
对于驱动程序与内核接口层,Linux提供了标准的入口点函数init_functionO;在通过模块化的设计方法设计驱动程序时,使用insmod加载模块时会调用本函数,通知内核对驱动程序进行注册。模块的卸除工作与加载工作类似,通过rmmod卸载模块时,调用cleanup_funct-ion0取消驱动程序的注册。
2.2 GPIO的步进电机驱动开发
GeneralPurposeInputOutput(通用输入/输出)简称为GPIO,或总线扩展器,利用工业标准I2C、SMBus?或SPI?接口简化了I/O口的扩展。当微控制器或芯片组没有足够的I/O端口,或当系统需要采用远端串行通信或控制时,GPIO产品能够提供额外的控制和监视功能。每个GPIO端口可通过软件分别配置成输入或输出。Maxim的GPIO产品线包括8端口至28端口的GPIO,提供推挽式输出或漏极开路输出。提供微型3mmx3mmQFN封装。
2.2.1 开发步骤
(1)模块化驱动程序
写字符设备的驱动程序时,也要遵守模块化编程的一般规范。设备模块在用户空间的初始化和终止:
Init_mnodule()向内核注册模块提供数据结构、局部和全局变量。
Cleanup_module()取消所有init_module在内核中的注册。
(2)设备模块在内核空间的内存申请和释放
kmalloc()函数分配一段内存,这样就实现了Chrdevs向量表中指向设备驱动程序名称的指针。使用kfree释放内存。
(3)字符设备主设备号和次设备号的分配
主设备号标志设备对应的驱动程序,内核利用主设备号将设备与相应的驱动程序对应起来。主设备号的取值范围是O~255,如果不善加规划,则容易造成主设备号的冲突。
次设备号由驱动程序使用,内核的其他部分并不使用它,仅将它传递给驱动程序。
(4)设备模块在内核空间的注册与注销
字符设备的注册有两种方法,一种是常用注册方法,通过系统函数registel_chrdev()将设备加入到系统设备列表中;另一种是devfs技术,通过系统函数devfs-regisrer()实现设备的注册。注销与注册相反,分别调用unregister_chrdev()函数和devfs_unregister()函数。
(5)设备模块在内核空间提供系统调用的函数设备驱动程序在注册成功以后,用户可以通过访问设备特殊文件(一般情况在/dev目录下)实现系统调用。
GPIO驱动程序只需要一个file operations数据结构体就可以了。
2.2.2 驱动开发
要写实际的驱动,就必需了解相关的硬件资源。比如:用到的寄存器、物理地址、中断等。在这里,它用到如下硬件资源。
要用操作所用到的IO口,就要设置他们所用到的寄存器,我们需要调用一些现成的函数或者宏,比如:
/*每个port有16个引脚,而每个引脚由两位来配置,所以你看到32×N。 32表示一个port的配置寄存器,而N代表是第几个端口。而这里的offset表示的是第几个引脚。
S3C2440开发板中GPIO的许多引脚是和地址线、数据线、串口线等引脚复用的。所以我们必须对GPIO进行重新定义和配置。一般来说,写驱动可以在内核中找相近的驱动程序,以它为模板进行开发,有时也要从零开始,这次作者在内核Linux-2.6.13-qq2440\kernel2.6.13\drivers\char中的qq2440 led.c进行修改。
定义了file_operations和各种API函数,配置了init和exit函数以及module_exit和module_init.
驱动开发完后,要进行测试。把编写好的驱动程序在PC机上进行交叉编译。然后用命令#insmod stepper.ko加载模块到内核中,通过命令#rmmod stepper.ko可以卸载模块。用mknod/dev/stepper 1000 0建立与驱动程序相应的设备节点。编写相应的应用程序。在应用程序中打开步进电机的设备文件,通过调用ioctl(fd,1&dir,O),运行应用程序,查看步进电机的转向。
3 结论
本文在S3C2440开发板下实现了步进电机的控制。给出了简单的驱动程序,实验结果表明驱动运行正常、稳定。但对于实现传能激光雕刻的图形及灰度雕刻,还有待于进一步的完善。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。