直流电机驱动c语言程序,WiFi遥控小车(四):简单直流电机驱动及UDP通信程序...

之前说过只要能控制高低电平就可以控制电机的正反转,我想通过修改友善官方的LED驱动程序来达到控制GPIO高低电平的目的,但是看了很久都没有怎么看懂,就去网上找看有没有比较好理解的程序,找到一个,原帖地址如下,十分感谢intel版主的无私分享:

原帖作者的小车是通过左右轮子的差速来实现转向的,可我的小车是后轮驱动,靠前轮转向的,所以对源程序做了些修改:

C代码

#include 

#include 

#include 

//#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

//#include 

#include 

#include 

#include 

#define DEVICE_NAME "car"

//控制前后的电机

#define MOTOR_QH_ENA    S3C64XX_GPM(4)

#define MOTOR_QH_ENB    S3C64XX_GPM(5)

//控制方向的电机

#define MOTOR_FX_ENA    S3C64XX_GPE(3)

#define MOTOR_FX_ENB    S3C64XX_GPE(4)

#define debug 1

static unsigned long motor_table [] = {

MOTOR_QH_ENA,

MOTOR_QH_ENB,

MOTOR_FX_ENA,

MOTOR_FX_ENB

};

//初始化GPIO口

static int car_motor_init(void)

{

int ret=0,i;

for (i = 0; i 

{

if(gpio_is_valid(motor_table[i])==-EINVAL)

{

printk("ERROR,GPIO used by other devices ! \n");

break;

}

//上拉GPIO

s3c_gpio_setpull(motor_table[i], S3C_GPIO_PULL_UP);

//设置为输出

s3c_gpio_cfgpin(motor_table[i], S3C_GPIO_OUTPUT);

//设置默认值为低电平

gpio_set_value(motor_table[i],0);

}

return ret;

};

static void car_motor_status(void)

{

printk("MOTOR_QH_ENA=%d\nMOTOR_QH_ENB=%d\nMOTOR_FX_ENA=%d\nMOTOR_FX_ENB=%d\n",

gpio_get_value(MOTOR_QH_ENA),

gpio_get_value(MOTOR_QH_ENB),

gpio_get_value(MOTOR_FX_ENA),

gpio_get_value(MOTOR_FX_ENB));

};

static void car_motor_run(void)

{

gpio_set_value(MOTOR_QH_ENA,1);

gpio_set_value(MOTOR_QH_ENB,0);

};

static void car_motor_stop(void)

{

#if debug

car_motor_status();

#endif

gpio_set_value(MOTOR_QH_ENA,0);

gpio_set_value(MOTOR_QH_ENB,0);

};

static void car_motor_back(void)

{

gpio_set_value(MOTOR_QH_ENA,0);

gpio_set_value(MOTOR_QH_ENB,1);

};

static void car_motor_left(void)

{

gpio_set_value(MOTOR_FX_ENA,1);

gpio_set_value(MOTOR_FX_ENB,0);

};

static void car_motor_right(void)

{

gpio_set_value(MOTOR_FX_ENA,0);

gpio_set_value(MOTOR_FX_ENB,1);

};

static void car_motor_zheng(void)

{

gpio_set_value(MOTOR_FX_ENA,0);

gpio_set_value(MOTOR_FX_ENB,0);

};

static long car_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

#if debug

printk("cmd=%d\n",cmd);

#endif

long ret=0;

switch(cmd)

{

case '0': case 0:

//小车停止

car_motor_stop();

break;

case '1': case 1:

//小车前进

car_motor_run();

break;

//小车后退

case '2': case 2:

car_motor_back();

break;

//左转

case '3': case 3:

car_motor_left();

break;

//右转

case '4': case 4:

car_motor_right();

break;

//直走

case '5': case 5:

car_motor_zheng();

break;

//小车后退

case '6': case 6:

car_motor_back();

break;

return 0;

default:

return -EINVAL;

}

return ret;

}

static struct file_operations dev_fops = {

.owner          = THIS_MODULE,

.unlocked_ioctl = car_ioctl,

};

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

};

static int __init dev_init(void)

{

int ret;

car_motor_init();

//  car_motor_run();

ret = misc_register(&misc);

printk (DEVICE_NAME"\tinitialized\n");

return ret;

}

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Lintel.");

为了测试驱动,根据友善的LED测试程序进行了修改,修改的程序如下:

C代码

#include 

#include 

#include 

#include 

#include 

#include 

#include 

int main(int argc, char **argv)

{

int cmd;

int led_no;

int fd;

if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &cmd) != 1 ||

cmd  9 || led_no  3) {

fprintf(stderr, "Usage: car led_no 0|1\n");

exit(1);

}

fd = open("/dev/car0", 0);

if (fd 

fd = open("/dev/car", 0);

}

if (fd 

perror("open device car");

exit(1);

}

printf("CMD=%d\n",cmd);

ioctl(fd, cmd, led_no);

close(fd);

return 0;

}

这个测试程序有个小问题,当传入的参数为‘0’‘1’时没有问题,但是当参数为‘2’时,怎么也传不进去,所以我把驱动代码的‘6’设置为了和‘2’一样的行为。

下面进行连线,按照驱动的GPIO口连接到电机驱动模块上,因为没有买到间距为2mm的接口,先用一根一根的线代替了,小车现在是这个样子:

0818b9ca8b590ca3270a3433284dd417.png

接下来马上就进行UDP通信部分,我也买了友善的SDWIFI模块,插上就能用,按照文档连上了我的路由器,用ifconfig命令查看开发板ip,开发板和笔记本互相能ping通,接下来就是写程序来监听指定端口上得到的数据并做出相应的反应,这部分不是很难,我是借了本书《嵌入式Linux案例开发指南》按照上面的例程修改的,源码如下:

C代码

/*

* main.c

*

*  Created on: 2012-10-18

*      Author: micro

*/

#include

#include

#include

#include

#include

#include

#include 

#define MAXLINE 5

#define SERV_PORT 12345

void do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen) {

int n;

socklen_t len;

char mesg[MAXLINE];

for (;;) {

len = clilen;

printf("Waiting for Data...\n");

//等待数据

n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

//将数据返回

//sendto(sockfd, mesg, n, 0, pcliaddr, len);

//打印数据

//printf("%s\n", mesg);

colcars(mesg[0]);

}

}

//根据收到的信息执行操作

void colcars(char cmd) {

if (cmd  '10') {

printf("cmd error\n");

} else {

if (cmd == '2') {

//          printf("car back\n");

car_col('6');

} else {

car_col(cmd);

}

}

}

void car_col(char cmd) {

int fd;

fd = open("/dev/car0", 0);

if (fd 

fd = open("/dev/car", 0);

}

if (fd 

perror("open device car");

return;

}

ioctl(fd, cmd, 0);

close(fd);

}

int main(void) {

int sockfd;

struct sockaddr_in servaddr, cliaddr;

//建立socket

sockfd = socket(AF_INET, SOCK_DGRAM, 0);

//初始化服务器地址

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY );

servaddr.sin_port = htons(SERV_PORT);

//为socket绑定端口

if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) {

perror("bind error");

exit(1);

}

//执行服务器程序

do_echo(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr));

return 0;

}          而我之前做过控制端的程序,包括安卓、黑莓上的控制程序现在都可以直接拿过来用,只需要把发送的字符串修改一下就好了,下图是我用台式机向开发版发送指令(在同一个路由器连接下),笔记本的终端只相当于一个通过串口显示的作用。

0818b9ca8b590ca3270a3433284dd417.png

至此,我已经基本把我之前的学习内容总结了一遍,我的小车已经基本实现了通过WiFi来远程控制前后左右运动的目的。但是现在我还不会用PWM信号来调速或者控制舵机,而且现在的程序相对粗糙,控制协议也很简单,还存在着每次重启开发板都要手动连接wifi、手动安装驱动与运行服务器程序等不足,这些都是我接下来所要解决的,另外还有块难啃的骨头——视频实时传输……谢谢大家对于我的关注,我会继续努力~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值