基于嵌入式Linux的步进电机驱动程序设计

发布者:rnm888最新更新时间:2010-08-02 来源: 微计算机信息关键字:嵌入式  Linux  步进电机  驱动 手机看文章 扫描二维码
随时随地手机看文章

  1.引言

  随着嵌入式技术的飞速发展,基于嵌入式系统的新一代工业控制器也日益增多。同以往的控制器不同,新的仪器大多以32位嵌入式处理器为核心,并且安装有嵌入式操作系统,从而大幅度提高了处理能力,方便了设计开发。在各种嵌入式操作系统中,嵌入式Linux是免费的自由软件,其构建的系统成本较低,而且Linux是单内核的操作系统,并可按要求进行任意剪裁,因此越来越多的研究人员开始在用Linux平台来开发自己的产品[1]。

  嵌入式开发过程中,经常需要为特定设备开发驱动程序。这些驱动程序的编写和编译与PC上的Linux驱动开发相比存在明显的差异,需要考虑的因素更多,实现过程更为复杂。本文以Samsung公司S3C2410X CPU为例,探讨如何为使用嵌入式Linux的工业控制器开发字符设备驱动程序来驱动步进电动机。

  2.Linux驱动程序概述

  在Linux中,几乎所有的内容都是文件,对设备驱动的访问也是以文件操作的方式实现的。Linux系统支持3种类型的硬件设备:字符设备、块设备和网络设备,这些设备的驱动程序是系统内核的重要组成部分。对用户程序而言,操作系统隐藏了设备的具体细节,把设备映射为一个设备文件,用户程序可以对设备文件进行open、close、read、write等操作。这些操作和驱动程序是通过struct file_operations这一数据结构关联起来的,编写设备驱动程序的主要工作就是编写子函数填充file_operations的各个字段[2]。

  3.嵌入式Linux步进电机驱动程序开发

  3.1  嵌入式Linux设备驱动程序的结构

  嵌入式Linux下的设备总体上可以分为两部分:

  其一,驱动与内核接口层,它实现驱动模块在Linux内核的注册加载与卸除工作。主要任务就是在模块加载时向内核注册驱动,以及实现虚拟文件系统的设备操作接口。对于采用中断的设备,此部分还包括中断处理函数的注册与注销。

  其二,硬件设备接口层,这部分主要描述驱动程序与设备的交互。它主要包括硬件探测和初始化以及设备的读写访问和设备控制操作。硬件探测主要是在驱动注册加载时监测设备是否存在,设备初始化主要是检测到设备后对它进行初始化操作。设备的读写操作主要完成从设备接受数据和将数据发送给设备的操作。硬件设备接口层还需要包括一些设备的控制操作,设定设备的工作参数。

  对于驱动程序与内核接口层,Linux提供了标准的入口点函数init_module();在通过模块化的设计方法设计驱动程序时,使用insmod加载核心模块时会调用本函数,通知内核对驱动程序进行注册。模块的卸除工作与加载工作类似,通过rmmod卸载模块时,调用cleanup_module()取消驱动程序的注册。

  3.2 步进电机驱动程序需求分析

  步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。在非超负载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响。所以在驱动程序中间只需要考虑这两个方面的影响。

  本系统的步进电机的四相由硬件地址0x28000006的bit0~bit3控制,bit0对应MOTOR_A,bit1对应MOTOR_B,bit2对应MOTOR_C,bit3对应MOTOR_D。本文所描述的驱动是针对整步模式下的步进电机,整步模式下的步距角18°。在整步模式下的脉冲分配信号如表所示。


  所以在程序中需要通过编制脉冲分配表控制步进电机,并且通过修改脉冲分配表可以实现步进电机方向的控制。

  系统的步进电机仅仅是一个输出的通道,只能顺序的进行控制的操作,因此作为一个字符设备来进行驱动。对于字符设备的操作而言驱动程序需要提供相关的几个操作分别为open,read,write,ioctl等相关的函数入口点。在驱动程序的实现过程中需要定义这些文件相关的操作,填充进入file_operations结构中。

  与普通文件相比,设备文件的操作要复杂得多,不可能简单的通过read、write等操作来实现。并且由于对于步进电机驱动程序没有相关的输入与输出,更关注的是对硬件的控制,因此在驱动程序对于write操作和read操作仅需返回0,而对于硬件的控制只需要在驱动程序中实现ioctl函数,并在其中添加相应的case即可。通过cmd区分操作,通过arg传递参数和结果[3]。

  3.3 步进电机驱动程序设计

  因为步进电机用到了I/O端口,而在ARM9中操作端口要用虚拟地址而非实际的物理地址,所以要修改内核代码。

  修改文件内核源代码中间的smdk.c,在结构体

  static struct map_desc smdk_io_desc] __initdata = {

  { vCS8900_BASE, pCS8900_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },

  { vCF_MEM_BASE, pCF_MEM_BASE, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },

  { vCF_IO_BASE, pCF_IO_BASE, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },

  LAST_DESC

  };

  中添加一行数组元素{ 0xd3000000,   0x28000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },则步进电机的物理地址0x28000006对应的虚拟地址为0xd3000006,在驱动程序中应对这个地址进行操作。

  定义全局变量num和status用来控制步进电机的速度和方向:

  static int num=1;

  static enum{off,clockwise,anticlockwise} status=off;

  定义步进电机的整步模式正转脉冲表:

  unsigned char pulse_table[] =

  {

  0x05, 0x09, 0x0a, 0x06,

  };

  定义时钟节拍函数time_tick()

  static void time_tick(unsigned long data)

  {

  static int i=0;

  switch(status)

  {

  case off: break;

  case clockwise:

  if(++i==num){

  i=0;

  if( row == 4 ) row = 0;

  (*(char *)0xd3000006)=pulse_table[row++];

  }

  ttimer.expires=jiffies+1;

  add_timer(&ttimer);

  break;

  case anticlockwise:

  if(++i==num){

  i=0;

  if( row == -1 ) row = 3;

  (*(char *)0xd3000006)=pulse_table[row--];

  }

  ttimer.expires=jiffies+1;

  add_timer(&ttimer);

  break;

  case default:  break;

  }

  }

  在time_tick()函数中判断步进电机的状态,是停止、正转还是反转。若是正转,则按正向顺序发送脉冲,并添加定时器ttimer;若是反转,则按反向顺序发送脉冲,并添加定时器ttimer;若是停止则不再发送脉冲,也不再添加定时器。

  在stepper_module_init()函数中申请I/O端口,并初始化定时器ttimer:

  if(check_region(0x28000006, 1))         //看该I/O端口是否已经被占用

  {

  printk("The stepper port is used by another module.\n");

  return -1;

  }

  request_region(0x28000006, 1, DEVICE_NAME);  //申请该I/O端口

  init_timer(&ttimer); //初始化定时器ttimer

  ttimer.function=time_tick;    //填写定时器处理函数为time_tick()

  编写ioctl函数用来接收应用程序对于步进电机的控制。

  int device_ioctl( struct inode *inode,  struct file *file, unsigned int ioctl_num,

  unsigned long ioctl_param)

  {

  struct stepper * s;

  /* 根据实际程序中的不同需求更改ioctl函数的调用*/

  switch (ioctl_num)

  {

  case IOCTL_SET_MSG:

  s = (struct stepper*) ioctl_param;

  switch (s->CmdID)

  {

  case 0:       /*开始*/

  status=clockwise;

  ttimer.expires=jiffies+1; //开启定时器

  add_timer(&ttimer);

  break;

  case 1:  status=off;    break;     /*停止*/

  case 2:       /*反转*/

  if(status==clockwise){  status=anticlockwise;  }

  if(status==anticlockwise){  status=clockwise;  }

  break;

  case 3:  if(num!=1)num--; break;      /*加速*/

  case 4:  num++;       break;      /*减速*/

  }

  }

  return 0;

  };

  通过s指针得到stepper结构中的表示命令类型的参数,根据该参数判断命令类型,0是start起动,1是stop停止,2是reverse反向,3是up电机加速,4是down电机减速,通过改变全局变量num和status来控制电机。电机的起动是通过在start分支中起动一个定时器ttimer,然后在定时器处理函数time_tick中发送步进电机脉冲,并重新添加定时器,从而实现步进电机的转动。

  4.结语

  本文归纳了嵌入式Linux驱动程序开发的特点并且结合嵌入式Linux下步进电机的驱动说明了驱动程序的编写。本文论述的驱动程序比较简单,一个功能齐全的驱动程序除了本文提到的几种功能外,还应该包括中断处理。这些工作有待日后完成。

  本文作者创新点:步进电机在嵌入式的应用中传统的方式都是在没有操作系统中完成,或者在没有支持MMU的操作系统中实现,本文在操作系统支持MMU的情况下完成了对于步进电机的控制。

关键字:嵌入式  Linux  步进电机  驱动 引用地址:基于嵌入式Linux的步进电机驱动程序设计

上一篇:复杂路线下机器人的三点三轮寻迹系统
下一篇:旋风预热器教研平台的设计与实现

推荐阅读最新更新时间:2024-03-30 21:31

大容量NAND Flash TC58DVG02A1FT00在嵌入式系统中的应用
摘要:随着嵌入式系统产品的发展,对存储设备的要求也日益增强。文章以东芝的NAND E2PROM器件TC58DVG02A1F00为例,阐述了NAND Flash的基本结构和使用方法,对比了NAND和NOR Flash的异同,介绍了容量NAND Flash在嵌入式系统中的应用方法,以及如何在Linux操作系统中加入对NAND Flash的支持。 关键词:嵌入式 NAND Flash Linux 内核 TC58DVG02A1F00 1 NAND和NOR flash 目前市场上的flash从结构上大体可以分为AND、NAND、NOR和DiNOR等几种。其中NOR和DiNOR的特点为相对电压低、随机读取快、功耗低、稳定性高,而NAND
[缓冲存储]
新型IGBT/MOSFET驱动模块SKHI22A/B
摘要:SKHI22A/B是德国西门康(SEMIKRON)公司推出的一种新型的IGBT/MOSFET的驱动模块。文章介绍了SKHI22A/B的主要结构特点和功能,给出了它的具体应用电路。 关键词:IGBT;驱动模块 ;SKHI22A/B 1 概述 SKHI系列驱动模块是德国西门康(SEMIKRON)公司推出的一种新型IGBT/MOSFET驱动模块。SKHI系列驱动模块主要有以下特点: ●仅需一个不需隔离的+15V电源供电 ●抗dV/dt能力可以达到75kV/μs ●控制电路和IGBT主电路之间的隔离电压可以达到4kV ●输出峰值电流可以达到30A ●同一桥臂上下开关管驱动信号具有互锁功能,可以防止两
[电源管理]
基于VxWorks的嵌入式系统复合通信模式
摘要:在嵌入式系统与VxWorks实时操作系统应用愈加广泛的背景下,结合嵌入式系统对于各类实时通信方式的不同需要,提出基于控制应用的复合通信模式;以Radstone公司的PPCx系列单板机为例,给出实现方法,并对数据通信的产时性与安全性作了研究。片对于各类嵌入式操作系统的数据测验具有很大的参考价值。 关键词:VxWorks 嵌入式系统 实时性 数据通信 引言 随着信息技术的不断发展和更新,嵌入式操作系统以其速率高、稳定、可配置内核的优势正得到越来越广泛的应用,包括医学、图像处理、军事、工业控制、电信等许多领域。嵌入式系统必须采用特殊有效的实时操作系统,VxWorks正是一个具有高性能的实时操作系统,成为嵌入式系统操作内核的
[嵌入式]
浅析“隔离驱动电源”在LED电源领域发展中的趋势
LED照明 电源的设计有非隔离设计和隔离型设计之分。带隔离变压器或者电气隔离的 LED驱动电源 意味着 LED 可以直接用手接触而不会触电。而无隔离变压器的 LED驱动 电源虽仍可以借助防护外壳实现部分机械绝缘,但此时的LED在工作时并不能直接接触。   物理设计决定着驱动器是隔离式还是非隔离式。安全规则通常要求使用两个独立的隔离层。设计师可以选择两种物理隔离层,即塑料散光罩和玻璃护罩,并使用非隔离式电源。如果物理隔离成本太高、存在机械困难或者吸收太多光,就必须在电源中解决电气隔离问题。隔离式电源通常要比同等功率水平的非隔离式电源大一些。 照明 灯设计师必须在他们所设计的每款产品中进行大量的成本及设计优化工作。   由于适用于不
[电源管理]
10路AD驱动程序
//Author: 泪与汗的缠绵 //Data:2011-11月 //功能:10路AD驱动程序,TFT函数的配置 #include stm32f10x_lib.h #include stdio.h #include main.h u8 Rx_Buffer ; vu32 FLASH_ID = 0; #define M25P64_FLASH_ID 0x202017 //u16 colors ={ // 0xf800,0x07e0,0x001f,0xffe0,0x0000,0x07ff,0xf81f,0xffff ,0x7bef //}; RCC_Init(); ADC_configuration(
[单片机]
驱动IC自主化难在哪里呢?
以海思为代表的国内众厂,正在向驱动IC巨大市场奋起狂奔。 集微网向业内人士求证得知,海思OLED驱动IC(Display Driver IC,DDI)将于2022年上半年量产,产能约20-30万颗/月。除了海思之外,国内包括集创北方、奕斯伟、云英谷、中颖电子在内的多家厂商近年来也实现各自领域的突破。 业内普遍认为,DDI一般采用65nm、40nm成熟工艺制程,最高也只会到28nm制程,从国内目前达到的代工水平来说,并非难以解决。那么,是什么让国产半导体一度将这一潜力巨大的市场旁落他人?代工之外,DDI自主化是否还存在隐藏难点? 集微网从多位产业链人士处了解到,技术上看,代工恐怕确非DDI自主化的最大阻碍,后道的DDI封测以及关键
[手机便携]
IR推出汽车应用单通道高压端驱动IC
国际整流器公司(International Rectifier,简称IR)日前推出适合汽车应用的高、中、低压坚固600V单通道高压端驱动IC AUIRS212xS系列,其应用包括通用汽车驱动器、高压执行器和低油耗直喷系统。 AUIRS2123S和AUIRS2124S高速功率MOSFET和IGBT驱动器符合AEC-Q100标准,可以提供10V至20V的栅极驱动电源电压。输出驱动器具有适用于最小驱动器跨导的高脉冲电流缓冲过程,而浮动通道可用来驱动在600V电压下工作的高压端配置的N沟道功率MOSFET或IGBT。这两种器件均具有负电压尖峰(Vs)免疫性,可防止系统在大电流切换和短路情况下发生損坏事件。 IR亚
[电源管理]
IU632兼容DRV632/SGM8903/AD22650,支持3Vrms音频线性驱动
IU632C是一款3VRMS无杂音立体声线性驱动器,此驱动器设计用于去除输出隔直流电容器,以减少组件数目及成本。对于那些将尺寸和成本作为关键设计参数的单电源电子产品,该器件是理想的选择。 IU632C能够在3.3V/5.0V电源电压供电时驱动2VRMS/3VRMS进入一个10kΩ 负载。此器件具有差分输入,并采用外部增益设置电阻以支持±1V至±10V的增益范围,而且可为每个通道单独配置增益。线路输出只需要使用一个简单的电阻器-电容器ESD保护电路即可。IU632C 具有针对无杂音音频打开/关闭控制的内置有源静音控制功能。 IU632C具有一个外部欠压检测器, 该欠压检测器在电源被移除时将输出静音,从而确保了无杂音的关断操作。与
[嵌入式]
IU632兼容DRV632/SGM8903/AD22650,支持3Vrms音频线性<font color='red'>驱动</font>器
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
最新工业控制文章
换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved