【技术支持】ARM9无线遥控视频实时监控小车(一)--------小车的电机控制模块
项目决定初期的想法主要出自于网上安卓手机的遥控下车
这个项目也是自己第一次做,肯定会话很多的冤枉钱
项目的总体花费为1000元左右
下图是这几天完成的一些内容,主要是小车运行和云台运动的实现
之后完成的模块将慢慢实现与展示

首先是怎么用ARM9的开发板实现轮子的伺服,小车的购买主要是来自淘宝,小车的是伺服主要是通过双H桥直流电机驱动板,它的使用方式就不拿出来说了,都是参考别人的 http://blog.sina.com.cn/s/blog_5e4725590100d2oq.html这是我使用的直流驱动板买家写的博客,里面说的非常之详细。其他的电机驱动板都是一个原理。
我使用的开发板的只有GPJ引脚是可以现成使用的,其他的都已经被封装使用了,电机驱动板只要通过GPJ的四个引脚分别置高低电平分别接I1\T2\I3\I4(这四个端口启动驱动板的时候就是高电平,所以是低电平有效),由于开发板的定时器有限,我之后还要用timer产生PWM波控制舵机,而且又不想扩展另外一块单片机来控制,就索性不控制电机的速度了。将小车的所有硬件都搭建完毕之后是测试电机的使用。第一步当然是编写GPJ的驱动,代码如下所示(驱动的编写就不在给予介绍)其实网上可以收到很多
1 #include<linux/module.h>
2 #include<linux/init.h>
3 #include<linux/fs.h>
4 #include<asm/uaccess.h>
5 #include<linux/device.h>
6 #include<asm/io.h>
7
8 MODULE_AUTHOR("FOX,GMAIL:huli_131@hotmail.com);
9 MODULE_DESCRIPTION("Driver test gpj");
10 MODULE_LICENSE("GPL");
11 #define DEVICE_NAME "gpj"
12
13 #define GPJCON (unsigned long)(0x560000D0)
14 #define GPJDAT (unsigned long)(0x560000D4)
15 #define GPJUP (unsigned long)(0x560000D8)
16
17 static int major=0;
18 static int minor=0;
19 static int counter=0;
20 static int gpjdp=0;
21
22 static unsigned long _io_gpjcon;
23 static unsigned long _io_gpjdat;
24 static unsigned long _io_gpjup;
25 unsigned long temp;
26
27
28 static struct class *dev_class;//方便驱动创建节点
29
30 static int gpj_open(struct inode *,struct file *);
31 static ssize_t gpj_read(struct file *,char *,size_t,loff_t *);
32 static ssize_t gpj_write(struct file *, const char *,size_t,loff_t *);
33
34 static int gpj_ioctl(struct inode *,struct file *,unsigned int,unsigned long);
35
36 struct file_operations gpj_ops={
37 .open = gpj_open,
38 .read = gpj_read,
39 .write = gpj_write,
40 .ioctl = gpj_ioctl,
41 };
42
43 static int gpj_open(struct inode * pinode,struct file * filep)
44 {
45 if(counter)
46 return -EBUSY;
47
48 counter++;
49
50 _io_gpjcon = (unsigned long)ioremap(GPJCON,4);
51 _io_gpjdat = (unsigned long)ioremap(GPJDAT,4);
52 _io_gpjup = (unsigned long)ioremap(GPJUP,4);
53
54 /*----------------------------0~3 控制电机设置为输入输出模式-------------------------------*/
55
56 temp= *(volatile unsigned long*)_io_gpjcon;
57 temp &= ~(0xFF);
58 temp |=0X55;
59 *(volatile unsigned long*)_io_gpjcon = temp ;
60
61 temp= *(volatile unsigned long*)_io_gpjdat; //将4个引脚的输出初始化为低电平
62 temp &= ~(0xF);
63 *(volatile unsigned long*)_io_gpjdat = temp ;
64
65 temp= *(volatile unsigned long*)_io_gpjup; //开启下拉电阻的模式
66 temp |= 0xf;
67 *(volatile unsigned long*)_io_gpjup = temp ;
68
69 /*------------------------------------------结束-------------------------------------------*/
70
71 return 0;
72 }
73 static ssize_t gpj_read(struct file * pinode,char * buf,size_t len,loff_t * off)
74 {
75 return sizeof(int);
76 }
77 static ssize_t gpj_write(struct file * pinode, const char * buf,size_t len,loff_t * off)
78 {
79 if(copy_from_user(&gpjdp,buf,sizeof(int)))
80 return -EFAULT;
81
82 return sizeof(int);
83 }
84
85 static int gpj_ioctl(struct inode * nodep,struct file * filep,unsigned int cmd,unsigned long arg)
86 {
87
88 /////////////////////////////////////////0~5引脚高低电平的控制/////////////////////////////
89 //cmd : true false
90 //arg : 0~3
91 if(arg<0 | arg>4)
92 {
93 printk("arg error");
94 return -1;
95 }
96 temp = *(volatile unsigned long*)_io_gpjdat;
97 if(cmd)
98 {
99 temp |= (0x01<<arg); //置高电平
100 }
101 else
102 {
103 temp &= ~(0x01<<arg); //置低电平
104 }
105 *(volatile unsigned long*)_io_gpjdat = temp;
106 return 0;
107 }
108
109
110 static int gpj_init(void)
111 {
112 printk("init gpj driver:\n");
113 major=register_chrdev(0,DEVICE_NAME,&gpj_ops);
114
115 if(major<0)
116 {
117 printk("Register failure\n");
118 }
119 else
120 {
121 //printk("Register Success %d - %d\n",major,minor);
122 dev_class=class_create(THIS_MODULE,DEVICE_NAME);
123
124 if(dev_class==NULL)
125 {
126 printk("device create fail:mknod /dev/%s %d %d",DEVICE_NAME,major,minor);
127 }
128 else
129 {
130 //
131 device_create(dev_class,NULL,MKDEV(major,minor),"%s",DEVICE_NAME);
132 printk("/dev/%s register success\n",DEVICE_NAME);
133
134 }
135
136 }
137
138 return 0;
139
140 }
141 static void gpj_exit(void)
142 {
143 printk("exit gpj driver:\n");
144
145 if(dev_class)
146 {
147 device_destroy(dev_class,MKDEV(major,minor));
148 class_destroy(dev_class);
149
150 }
151
152 unregister_chrdev(major,DEVICE_NAME);
153 }
154
155 module_init(gpj_init);
156 module_exit(gpj_exit);
下面是编写驱动c文件的makefile文件
1 #version 2.0
2 DEBUG ?=n
3 KSOURCE ?=/home/fox/utu-Linux2.6.24_for_utu2440_2009-07-18/
4 KBUILD_VERBOSE:=1
5
6 %.x :%.c
7 arm-linux-gcc -o $@ $<
8
9 obj-m:=gpj.o
10
11 default:
12 make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules
13 .PHONY:
14 cscope:
15 cscope -b -k -R
16 .PHONY:
17 clean:
18 make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules
19 rm -f *.x *~
20 rm -rf *.o *.ko
记得将KSOURCE ?=/home/fox/utu-Linux2.6.24_for_utu2440_2009-07-18/ 命令改为自己的内核编译目录
接下来就是测试代码(其实就是控制代码了)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <sys/ioctl.h>
5
6 void car_advance();
7 void car_sternway();
8 void car_turn_left();
9 void car_turn_right();
10 void car_brake();
11
12 int main(int argc, char **argv)
13 {
14 int control_num;
15 if(argc!=2){printf("cmd error\n");return 1;}
16 fd=open(argv[1],O_RDWR);
17 //fd = open("/dev/goj", O_RDWR);
18
19 if(fd < 0)
20 {
21 printf("Open PWM Device Faild!\n");
22 exit(1);
23 }
24 printf("please enter a control number:\n");
25 while(1)
26
27 {
28 //输入参数
29 scanf("%d", &control_num);
30 printf("control_num = %d\n", control_num);
31 //IO控制
32 switch(control_num)
33 {
34 case 0:
35 car_advance();
36 break;
37 case 1:
38 car_sternway();
39 break;
40 case 2:
41 car_turn_left();
42 break;
43 case 3:
44 car_turn_right();
45 break;
46 case 4:
47 car_brake();
48 break;
49 default:
50 break;
51 }
52 }
53 //关闭设备
54 close(fd);
55 return 0;
56 }
57
58 /*---------------------------------说 明----------------------------------------*/
59 // * @ 接口对应
60 // * @ Gpj0:I1
61 // * @ Gpj1:I2
62 // * @ Gpj2:I3
63 // * @ Gpj3:I4
64 /*---------------------------------前 进----------------------------------------*/
65 void car_advance()
66 {
67 ioctl(fd,true, 0);
68 ioctl(fd,false, 1);
69 ioctl(fd,true, 2);
70 ioctl(fd,false, 3);
71 }
72
73 /*---------------------------------后 退----------------------------------------*/
74 void car_sternway()
75 {
76 ioctl(fd,true, 1);
77 ioctl(fd,false, 0);
78 ioctl(fd,true, 3);
79 ioctl(fd,false, 2);
80 }
81
82 /*---------------------------------左 转----------------------------------------*/
83 void car_turn_left()
84 {
85 ioctl(fd,true, 0);
86 ioctl(fd,false, 1);
87 ioctl(fd,true, 3);
88 ioctl(fd,false, 2);
89 }
90
91 /*---------------------------------右 转-----------------------------------------*/
92 void car_turn_right()
93 {
94 ioctl(fd,true, 1);
95 ioctl(fd,false, 0);
96 ioctl(fd,true, 2);
97 ioctl(fd,false, 3);
98 }
99
100 /*---------------------------------刹 车-----------------------------------------*/
101 void car_brake()
102 {
103 ioctl(fd,false, 0);
104 ioctl(fd,false, 1);
105 ioctl(fd,false, 2);
106 ioctl(fd,false, 3);
107 }
先声明上面的测试程序我是在项目整合中拷贝过来的,虚拟机已经关闭就没有经过编译,希望有错的下面留言,本人必将改之,不过一般来说不会出太大的或太多的错误。

浙公网安备 33010602011771号