赞
踩
其实我更想用32的板子来完成这个项目,但是老师要求只能用GEC6818的板子,虽然这个板子功能更加全面,但本人还是对32熟悉一些,所以前期还是花了很多时间来研究这块板子,总的来说其实步骤还是差不多的。实现代码在文章最底下。
1、总体设计任务框图
2、设计任务:
本设计是基于粤嵌gec6818开发板完成远端操控小车的操作,小车需要纯手工组装。
要求:
完成各模块功能的构建,使用QT的界面设计和安卓配置作为客户端给服务器端发送数据,在服务器端接收数据并创建子线程处理数据。通过看6818底板电路图发现可使用GPIO_C7、C8、C17和GPIO_E13输出电平给电机供电,并且可通过调节占空比来控制小车速度。
3、功能要求及技术指标
4、 总体设计方案
运用QT实现基本的TCP客户端和服务器端的基本通信,客户端实现与服务器端建立连接、发送数据与断开,服务器端接收客户端数据并创建子线程来处理接收到的数据。再通过UI和安卓界面设计来实现按钮控制小车,再通过给四个GPIO口输出高低电平来控制电机转动和速度,最后实现控制小车。
5 系统测试
客户端:QT版与安卓版
(ps:奥迪rs7是不是你的终极梦想,哈哈哈)
服务器端:基于粤嵌6818的智能小车
6 使用说明
当你在输入框内输入正确的IP地址以及端口号,点击链接即可成功并在显示窗口显示连接成功,然后就可以通过点击前进,后退,左转,右转,停止来实现控制小车运动,点击断开及失去控制权。
7.附录代码
服务器端:
int port = 6666;
// GPIOC7的编号为: PAD_GPIO_C + 7
enum {
PAD_GPIO_A = (0 * 32),
PAD_GPIO_B = (1 * 32),
PAD_GPIO_C = (2 * 32),
PAD_GPIO_D = (3 * 32),
PAD_GPIO_E = (4 * 32),
PAD_GPIO_ALV = (5 * 32),
};
//GPIO模式
#define GPIO_MODE_INPUT 1
#define GPIO_MODE_OUTPUT 0
#define THREAD_NUMBER 1
typedef struct gpio_cfg_t
{
unsigned int gpio_no; //gpio的编号
unsigned int gpio_mode; // input/output
unsigned int init_value; // 当gpio配置成output模式时
//指定输出的初始值。
}gpio_cfg_t;
typedef struct gpio_value
{
unsigned int gpio_no; //gpio的编号
unsigned int gpio_value;
} gpio_value_t;
#define GPIO_CONFIG _IOW('G', 1, gpio_cfg_t)
#define GPIO_SET_VALUE _IOW('G', 2, gpio_value_t)
#define GPIO_GET_VALUE _IOWR('G', 3, gpio_value_t)
gpio_cfg_t gpio_init;
gpio_value_t gpio_clear;
void GPIO_Init(int fd)
{
gpio_init.gpio_no = PAD_GPIO_C + 7;
gpio_init.gpio_mode = GPIO_MODE_OUTPUT; //输出模式
gpio_init.init_value = 0; //初始输出 低电平
ioctl(fd, GPIO_CONFIG, &gpio_init);
gpio_init.gpio_no = PAD_GPIO_C + 8;
gpio_init.gpio_mode = GPIO_MODE_OUTPUT; //输出模式
gpio_init.init_value = 0; //初始输出 低电平
ioctl(fd, GPIO_CONFIG, &gpio_init);
gpio_init.gpio_no = PAD_GPIO_C + 17;
gpio_init.gpio_mode = GPIO_MODE_OUTPUT; //输出模式
gpio_init.init_value = 0; //初始输出 低电平
ioctl(fd, GPIO_CONFIG, &gpio_init);
gpio_init.gpio_no = PAD_GPIO_E + 13 ;
gpio_init.gpio_mode = GPIO_MODE_OUTPUT; //输出模式
gpio_init.init_value = 0; //初始输出 低电平
ioctl(fd, GPIO_CONFIG, &gpio_init);
}
void clear(int fd)
{
gpio_clear.gpio_no = PAD_GPIO_C + 7;
gpio_clear.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_clear);
gpio_clear.gpio_no = PAD_GPIO_C + 8;
gpio_clear.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_clear);
gpio_clear.gpio_no = PAD_GPIO_C + 17;
gpio_clear.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_clear);
gpio_clear.gpio_no = PAD_GPIO_E + 13;
gpio_clear.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_clear);
}
void forward(int fd)
{
gpio_value_t gpio_value_1;
gpio_value_1.gpio_no = PAD_GPIO_C + 7;
gpio_value_1.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_1);
gpio_value_t gpio_value_2;
gpio_value_2.gpio_no = PAD_GPIO_E + 13;
gpio_value_2.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_2);
gpio_value_t gpio_value_C8;
gpio_value_C8.gpio_no = PAD_GPIO_C + 8;
gpio_value_C8.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C8);
gpio_value_t gpio_value_C17;
gpio_value_C17.gpio_no = PAD_GPIO_C + 17;
gpio_value_C17.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C17);
}
void back(int fd)
{
gpio_value_t gpio_value_3;
gpio_value_3.gpio_no = PAD_GPIO_C + 8;
gpio_value_3.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_3);
gpio_value_t gpio_value_4;
gpio_value_4.gpio_no = PAD_GPIO_C + 17;
gpio_value_4.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_4);
gpio_value_t gpio_value_C7;
gpio_value_C7.gpio_no = PAD_GPIO_C + 7;
gpio_value_C7.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C7);
gpio_value_t gpio_value_E13;
gpio_value_E13.gpio_no = PAD_GPIO_E + 13;
gpio_value_E13.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_E13);
}
void turn_left(int fd)
{
gpio_value_t gpio_value_5;
gpio_value_5.gpio_no = PAD_GPIO_C + 7;
gpio_value_5.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_5);
gpio_value_t gpio_value_6;
gpio_value_6.gpio_no = PAD_GPIO_C + 8;
gpio_value_6.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_6);
gpio_value_t gpio_value_C17;
gpio_value_C17.gpio_no = PAD_GPIO_C + 17;
gpio_value_C17.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C17);
gpio_value_t gpio_value_E13;
gpio_value_E13.gpio_no = PAD_GPIO_E + 13;
gpio_value_E13.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_E13);
// sleep(1);
// forward(fd);
}
void turn_right(int fd)
{
gpio_value_t gpio_value_7;
gpio_value_7.gpio_no = PAD_GPIO_C + 17;
gpio_value_7.gpio_value = 1;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_7);
gpio_value_t gpio_value_8;
gpio_value_8.gpio_no = PAD_GPIO_E + 13;
gpio_value_8.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_8);
gpio_value_t gpio_value_C7;
gpio_value_C7.gpio_no = PAD_GPIO_C + 7;
gpio_value_C7.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C7);
gpio_value_t gpio_value_C8;
gpio_value_C8.gpio_no = PAD_GPIO_C + 8;
gpio_value_C8.gpio_value = 0;
ioctl(fd, GPIO_SET_VALUE, &gpio_value_C8);
// sleep(1);
// forward(fd);
}
/*处理接收客户端消息函数*/
int ret;
void *recv_message(void *fd)
{
int sockfd = *(int *)fd;
int i,j,k,n;
printf("received from client:%d\n", ret);
while(1)
{
switch(ret)
{
case 0:clear(sockfd);break;
case 1:
for(i = 0;i < 10;i++)
{
if(i == 0 | i == 4 | i == 7)
{
forward(sockfd);
}
else
{
clear(sockfd);
}
}
// forward(sockfd);
break;
case 2:
for(j = 0;j < 10;j++)
{
if(j == 0 | j == 4 | j == 7)
{
back(sockfd);
}
else
{
clear(sockfd);
}
}
// back(sockfd);
break;
case 3:
for(k = 0;k < 10;k++)
{
if(k == 0 |k == 4 |k ==7)
{
turn_left(sockfd);
}
else
{
clear(sockfd);
}
}
// turn_left(sockfd);
break;
case 4:
for(n = 0;n < 10;n++)
{
if(n == 0 | n == 4 | n == 7)
{
turn_right(sockfd);
}
else
{
clear(sockfd);
}
}
// turn_right(sockfd);
break;
default:printf("recivice error");break;
}
}//while
}
int main()
{
int fd = open("/dev/gec6818_gpios", O_RDWR);
if (fd == -1)
{
perror("failed to open:");
return -1;
}
//声明套接字
int listenfd , connfd;
socklen_t clilen;
//声明线程ID
pthread_t recv_tid , send_tid;
//定义地址结构
struct sockaddr_in servaddr , cliaddr;
GPIO_Init(fd);
/*(1) 创建套接字*/
if((listenfd = socket(AF_INET , SOCK_STREAM , 0)) == -1)
{
perror("socket error.\n");
exit(1);
}//if
/*(2) 初始化地址结构*/
bzero(&servaddr , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
/*(3) 绑定套接字和端口*/
if(bind(listenfd , (struct sockaddr *)&servaddr , sizeof(servaddr)) < 0)
{
perror("bind error.\n");
exit(1);
}//if
/*(4) 监听*/
if(listen(listenfd , LISTENQ) < 0)
{
perror("listen error.\n");
exit(1);
}//if
/*(5) 接受客户请求,并创建线程处理*/
clilen = sizeof(cliaddr);
if((connfd = accept(listenfd , (struct sockaddr *)&cliaddr , &clilen)) < 0)
{
perror("accept error.\n");
exit(1);
}//if
printf("server: got connection from %s\n", inet_ntoa(cliaddr.sin_addr));
/*创建子线程处理该客户链接接收消息*/
if( pthread_create(&recv_tid , NULL , recv_message, &fd) == -1)
{
perror("pthread create error.\n");
exit(1);
}
while(1)
{
char buf[MAX_LINE];
memset(buf , 0 , MAX_LINE);
int n;
if((n = recv(connfd , buf , MAX_LINE , 0)) == -1)
{
perror("recv error.\n");
exit(1);
}
sscanf(buf,"%d",&ret);
}
}
客户端:
安卓:
ui->ctnForward->setFixedSize(200,200);
ui->ctnBack->setFixedSize(200,200);
ui->ctnLeft->setFixedSize(200,200);
ui->ctnRight->setFixedSize(200,200);
ui->textshow->setFixedSize(800,500);
ui->ctnStop->setFixedSize(200,200);
ui->ctnStop->move(400,1000);
ui->ctnForward->move(400,770);
ui->ctnBack->move(400,1230);
ui->ctnLeft->move(100,1000);
ui->ctnRight->move(700,1000);
ui->textshow->move(150,100);
ui->lineEditip->setFixedSize(600,100);
ui->lineEditport->setFixedSize(600,100);
ui->lineEditip->move(360,1500);
ui->lineEditport->move(360,1650);
ui->labelip->setFixedSize(150,100);
ui->labelport->setFixedSize(150,100);
ui->labelip->move(150,1500);
ui->labelport->move(150,1650);
ui->ctnConnect->setFixedSize(200,100);
ui->ctnDisconnect->setFixedSize(200,100);
ui->ctnConnect->move(200,1900);
ui->ctnDisconnect->move(600,1900);
//连接小车
void TCPcar2::on_ctnConnect_clicked()
{
//获取IP和端口号
QString ip=ui->lineEditip->text();
qint16 port = ui->lineEditport->text().toInt();//字符串转换成整形
//主动与服务器建立连接
tcpSocket->connectToHost(QHostAddress(ip),port);
}
//断开连接
void TCPcar2::on_ctnDisconnect_clicked()
{
//断开连接
tcpSocket->disconnectFromHost();
tcpSocket->close();
}
//前进
void TCPcar2::on_ctnForward_pressed()
{
QString str1="1";
tcpSocket->write(str1.toUtf8().data());//给小车发送数据 Utf8将qstring转qbytearray .data()转char
ui->textshow->setText("向前冲冲冲");
//qDebug()<<"1";
}
void TCPcar2::on_ctnForward_released()
{
// QString str0="0";
// tcpSocket->write(str0.toUtf8().data());
// qDebug()<<"0";
}
//后退
void TCPcar2::on_ctnBack_pressed()
{
QString str2="2";
tcpSocket->write(str2.toUtf8().data());
ui->textshow->setText("倒车请注意哟");
//qDebug()<<"2";
}
void TCPcar2::on_ctnBack_released()
{
// QString str0="0";
// tcpSocket->write(str0.toUtf8().data());
// qDebug()<<"0";
}
//左转
void TCPcar2::on_ctnLeft_pressed()
{
QString str3="3";
tcpSocket->write(str3.toUtf8().data());//给小车发送数据
ui->textshow->setText("左转啦");
//qDebug()<<"3";
}
void TCPcar2::on_ctnLeft_released()
{
// QString str0="0";
// tcpSocket->write(str0.toUtf8().data());
// qDebug()<<"0";
}
// 右转
void TCPcar2::on_ctnRight_pressed()
{
QString str4="4";
tcpSocket->write(str4.toUtf8().data());
ui->textshow->setText("右转啦");
//qDebug()<<"4";
}
void TCPcar2::on_ctnRight_released()
{
// QString str0="0";
// tcpSocket->write(str0.toUtf8().data());
// qDebug()<<"0";
}
//添加绘图事件,QPixmap(":/image/2.png"));里面加的
//是添加资源的路径,
//添加背景图
//void TCPcar2::paintEvent(QPaintEvent *event)
//{
// QPainter painter(this);
// painter.drawPixmap(0,0,width(),height(),QPixmap("C:/Users/12085/Pictures/Saved Pictures/rs7.jpg"));
//}
void TCPcar2::on_ctnStop_clicked()
{
QString str0="0";
tcpSocket->write(str0.toUtf8().data());
//qDebug()<<"0";
ui->textshow->setText("刹车啦!!!!!!");
}
驱动:
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <cfg_type.h>
#include <linux/miscdevice.h>
MODULE_LICENSE("GPL");
#define GPIO_MODE_INPUT 1
#define GPIO_MODE_OUTPUT 0
typedef struct gpio_cfg_t
{
unsigned int gpio_no; //gpio的编号
unsigned int gpio_mode; // input/output
unsigned int init_value; // 当gpio配置成output模式时
//输出的初始值。
}gpio_cfg_t;
typedef struct gpio_value
{
unsigned int gpio_no; //gpio的编号
unsigned int gpio_value; //
} gpio_value_t;
#define GPIO_CONFIG _IOW('G', 1, gpio_cfg_t)
#define GPIO_SET_VALUE _IOW('G', 2, gpio_value_t)
#define GPIO_GET_VALUE _IOWR('G', 3, gpio_value_t)
long gec6818_gpio_ioctl (struct file *_file, unsigned int cmd, unsigned long arg)
{
gpio_cfg_t gpio_cfg;
gpio_value_t gpio_value;
char gpio_name[12];
int ret;
switch(cmd)
{
case GPIO_CONFIG:
{
void __user *ptr = (void __user *)arg;
ret = copy_from_user( (void*)&gpio_cfg, ptr, sizeof(gpio_cfg) );
sprintf(gpio_name, "GPIO%c%d", 'A' + gpio_cfg.gpio_no/32,
gpio_cfg.gpio_no%32);
printk(KERN_INFO "gpio num: %s mode:%s\n", gpio_name,
gpio_cfg.gpio_mode == GPIO_MODE_INPUT ? "INPUT" : "OUTPUT");
if (gpio_cfg.gpio_mode == GPIO_MODE_INPUT)
{
gpio_direction_input(gpio_cfg.gpio_no);
}
else
{
gpio_direction_output(gpio_cfg.gpio_no, gpio_cfg.init_value);
}
break;
}
case GPIO_SET_VALUE:
{
void __user *ptr = (void __user *)arg;
ret = copy_from_user( (void*)&gpio_value, ptr, sizeof(gpio_value) );
sprintf(gpio_name, "GPIO%c%d", 'A' + gpio_value.gpio_no/32,
gpio_value.gpio_no%32);
printk(KERN_INFO "SET %s -> %d\n",
gpio_name, gpio_value.gpio_value);
__gpio_set_value( gpio_value.gpio_no, gpio_value.gpio_value);
break;
}
case GPIO_GET_VALUE:
{
void __user *ptr = (void __user *)arg;
ret = copy_from_user( (void*)&gpio_value, ptr, sizeof(gpio_value) );
gpio_value.gpio_value = __gpio_get_value(gpio_value.gpio_no);
sprintf(gpio_name, "GPIO%c%d", 'A' + gpio_value.gpio_no/32,
gpio_value.gpio_no%32);
printk(KERN_INFO "GET %s's state is %d\n",
gpio_name, gpio_value.gpio_value);
ret = copy_to_user(ptr, (void*)&gpio_value, sizeof(gpio_value));
break;
}
default:
break;
}
return 0;
}
static struct file_operations gec6818_gpio_ops =
{
.unlocked_ioctl = gec6818_gpio_ioctl
};
static struct miscdevice gec_misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "gec6818_gpios", // /dev/gec6818_gpios
.fops = &gec6818_gpio_ops //文件操作
};
static int __init gec6818_gpio_drv_init(void)
{
return misc_register(&gec_misc);
}
static void __exit gec6818_gpio_drv_exit(void)
{
misc_deregister(&gec_misc);
}
module_init(gec6818_gpio_drv_init);
module_exit(gec6818_gpio_drv_exit);
#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>
MODULE_INFO(vermagic, VERMAGIC_STRING);
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
#endif
.arch = MODULE_ARCH_INIT,
};
static const char __module_depends[]
__used
__attribute__((section(".modinfo"))) =
"depends=";
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。