您的位置:首页 > 运维架构

【技术支持】ARM9无线遥控视频实时监控小车(一)--------小车的电机控制模块

2012-03-30 21:50 621 查看
     项目决定初期的想法主要出自于网上安卓手机的遥控下车

     这个项目也是自己第一次做,肯定会话很多的冤枉钱

     项目的总体花费为1000元左右

     下图是这几天完成的一些内容,主要是小车运行和云台运动的实现
     之后完成的模块将慢慢实现与展示



首先是怎么用ARM9的开发板实现轮子的伺服,小车的购买主要是来自淘宝,小车的是伺服主要是通过双H桥直流电机驱动板,它的使用方式就不拿出来说了,都是参考别人的 http://blog.sina.com.cn/s/blog_5e4725590100d2oq.html这是我使用的直流驱动板买家写的博客,里面说的非常之详细。其他的电机驱动板都是一个原理。

我使用的开发板的只有GPJ引脚是可以现成使用的,其他的都已经被封装使用了,电机驱动板只要通过GPJ的四个引脚分别置高低电平分别接I1\T2\I3\I4(这四个端口启动驱动板的时候就是高电平,所以是低电平有效),由于开发板的定时器有限,我之后还要用timer产生PWM波控制舵机,而且又不想扩展另外一块单片机来控制,就索性不控制电机的速度了。将小车的所有硬件都搭建完毕之后是测试电机的使用。第一步当然是编写GPJ的驱动,代码如下所示(驱动的编写就不在给予介绍)其实网上可以收到很多

#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<asm/uaccess.h>
#include<linux/device.h>
#include<asm/io.h>
7
MODULE_AUTHOR("FOX,GMAIL:huli_131@hotmail.com);
MODULE_DESCRIPTION("Driver test gpj");
MODULE_LICENSE("GPL");
#define DEVICE_NAME "gpj"
12
#define GPJCON (unsigned long)(0x560000D0)
#define GPJDAT (unsigned long)(0x560000D4)
#define GPJUP (unsigned long)(0x560000D8)
16
static int major=0;
static int minor=0;
static int counter=0;
static int gpjdp=0;
21
static unsigned long _io_gpjcon;
static unsigned long _io_gpjdat;
static unsigned long _io_gpjup;
unsigned long temp;
26
27
static struct class *dev_class;//方便驱动创建节点

static int gpj_open(struct inode *,struct file *);
static ssize_t gpj_read(struct file *,char *,size_t,loff_t *);
static ssize_t gpj_write(struct file *, const char *,size_t,loff_t *);
33
static int gpj_ioctl(struct inode *,struct file *,unsigned int,unsigned long);
35
struct file_operations gpj_ops={
.open = gpj_open,
.read = gpj_read,
.write = gpj_write,
.ioctl = gpj_ioctl,
};
42
static int gpj_open(struct inode * pinode,struct file * filep)
{
if(counter)
return -EBUSY;
47
counter++;
49
_io_gpjcon = (unsigned long)ioremap(GPJCON,4);
_io_gpjdat = (unsigned long)ioremap(GPJDAT,4);
_io_gpjup = (unsigned long)ioremap(GPJUP,4);
53
/*----------------------------0~3 控制电机设置为输入输出模式-------------------------------*/
55
temp= *(volatile unsigned long*)_io_gpjcon;
temp &= ~(0xFF);
temp |=0X55;
*(volatile unsigned long*)_io_gpjcon = temp ;
60
temp= *(volatile unsigned long*)_io_gpjdat;                        //将4个引脚的输出初始化为低电平
temp &= ~(0xF);
*(volatile unsigned long*)_io_gpjdat = temp ;
64
temp= *(volatile unsigned long*)_io_gpjup;                        //开启下拉电阻的模式
temp |= 0xf;
*(volatile unsigned long*)_io_gpjup = temp ;
68
/*------------------------------------------结束-------------------------------------------*/
70
return 0;
}
static ssize_t gpj_read(struct file * pinode,char * buf,size_t len,loff_t * off)
{
return sizeof(int);
}
static ssize_t gpj_write(struct file * pinode, const char * buf,size_t len,loff_t * off)
{
if(copy_from_user(&gpjdp,buf,sizeof(int)))
return -EFAULT;
81
return sizeof(int);
}
84
static int gpj_ioctl(struct inode * nodep,struct file * filep,unsigned int cmd,unsigned long arg)
{
87
/////////////////////////////////////////0~5引脚高低电平的控制/////////////////////////////
//cmd : true false
//arg : 0~3
if(arg<0 | arg>4)
{
printk("arg error");
return -1;
}
temp = *(volatile unsigned long*)_io_gpjdat;
if(cmd)
{
temp |= (0x01<<arg);                //置高电平
}
else
{
temp &= ~(0x01<<arg);                //置低电平
}
*(volatile unsigned long*)_io_gpjdat = temp;
return 0;
}
108
109
static int gpj_init(void)
{
printk("init gpj driver:\n");
major=register_chrdev(0,DEVICE_NAME,&gpj_ops);
114
if(major<0)
{
printk("Register failure\n");
}
else
{
//printk("Register Success %d - %d\n",major,minor);
dev_class=class_create(THIS_MODULE,DEVICE_NAME);
123
if(dev_class==NULL)
{
printk("device create fail:mknod /dev/%s %d %d",DEVICE_NAME,major,minor);
}
else
{
//
device_create(dev_class,NULL,MKDEV(major,minor),"%s",DEVICE_NAME);
printk("/dev/%s register success\n",DEVICE_NAME);
133
}
135
}
137
return 0;
139
}
static void gpj_exit(void)
{
printk("exit gpj driver:\n");
144
if(dev_class)
{
device_destroy(dev_class,MKDEV(major,minor));
class_destroy(dev_class);
149
}
151
unregister_chrdev(major,DEVICE_NAME);
}
154
module_init(gpj_init);
module_exit(gpj_exit);


下面是编写驱动c文件的makefile文件

#version 2.0
DEBUG ?=n
KSOURCE ?=/home/fox/utu-Linux2.6.24_for_utu2440_2009-07-18/
KBUILD_VERBOSE:=1
5
%.x :%.c
arm-linux-gcc -o $@ $<
8
obj-m:=gpj.o
10
default:
make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules
.PHONY:
cscope:
cscope -b -k -R
.PHONY:
clean:
make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules
rm -f *.x *~
rm -rf *.o *.ko


记得将KSOURCE ?=/home/fox/utu-Linux2.6.24_for_utu2440_2009-07-18/ 命令改为自己的内核编译目录

接下来就是测试代码(其实就是控制代码了)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
5
void car_advance();
void car_sternway();
void car_turn_left();
void car_turn_right();
void car_brake();
11
int main(int argc, char **argv)
{
int control_num;
if(argc!=2){printf("cmd error\n");return 1;}
fd=open(argv[1],O_RDWR);
//fd = open("/dev/goj", O_RDWR);

if(fd < 0)
{
printf("Open PWM Device Faild!\n");
exit(1);
}
printf("please enter a control number:\n");
while(1)
26
{
//输入参数
scanf("%d", &control_num);
printf("control_num = %d\n", control_num);
//IO控制
switch(control_num)
{
case 0:
car_advance();
break;
case 1:
car_sternway();
break;
case 2:
car_turn_left();
break;
case 3:
car_turn_right();
break;
case 4:
car_brake();
break;
default:
break;
}
}
//关闭设备
close(fd);
return 0;
}
57
/*---------------------------------说 明----------------------------------------*/
//                  * @ 接口对应
//                  * @ Gpj0:I1
//                  * @ Gpj1:I2
//                  * @ Gpj2:I3
//                * @ Gpj3:I4
/*---------------------------------前 进----------------------------------------*/
void car_advance()
{
ioctl(fd,true, 0);
ioctl(fd,false, 1);
ioctl(fd,true, 2);
ioctl(fd,false, 3);
}
72
/*---------------------------------后 退----------------------------------------*/
void car_sternway()
{
ioctl(fd,true, 1);
ioctl(fd,false, 0);
ioctl(fd,true, 3);
ioctl(fd,false, 2);
}
81
/*---------------------------------左 转----------------------------------------*/
void car_turn_left()
{
ioctl(fd,true, 0);
ioctl(fd,false, 1);
ioctl(fd,true, 3);
ioctl(fd,false, 2);
}
90
/*---------------------------------右 转-----------------------------------------*/
void car_turn_right()
{
ioctl(fd,true, 1);
ioctl(fd,false, 0);
ioctl(fd,true, 2);
ioctl(fd,false, 3);
}
99
/*---------------------------------刹 车-----------------------------------------*/
void car_brake()
{
ioctl(fd,false, 0);
ioctl(fd,false, 1);
ioctl(fd,false, 2);
ioctl(fd,false, 3);
}


先声明上面的测试程序我是在项目整合中拷贝过来的,虚拟机已经关闭就没有经过编译,希望有错的下面留言,本人必将改之,不过一般来说不会出太大的或太多的错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐