您的位置:首页 > 编程语言 > Qt开发

Tiny6410与RFID读卡器通信,并实现LED模拟控制和QT显示(阶段总结)

2014-03-12 09:02 495 查看
本装置现阶段实现的基本功能如下:(1)RFID读卡器接收到便签信息并通过串口发送给6410开发板,6410根据《XSS协议》对数据进行封装,其作为tcp client通过socket 与服务器进行通信,这类6410只是将串口数据转发给网口,只是一个单向的通信过程。
(2)另一类是是tcp client发给server后,还需要接收server的回复。接收到的回复信息后要进行两类操作:控制功能(LED灯)和界面显示(触摸屏显示)。
所有的源代码在http://download.csdn.net/detail/mashang123456789/7026585

(1)首先介绍通信功能

这里面包括单向和双向通信过程,在双向通信过程中控制LED和生成txt文件,供qt显示时使用。
注意:用了一些自己编写的API,后面会将所有工程文件上传,方便学习使用,这里只介绍核心代码。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "../wrap.h"

#define SERV_PORT  2000

int main(int argc,char ** argv)
{
int led_fd,k;//LEDs
int sockfd,n_selt;
int n,i;
FILE  *matchfile;   // declare FILE pointers生成的文件的描述符
int fp,comnum;//串口文件描述符,从串口读到的个数
//char buf[100];
char com_buf[17]={0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00};//存储从串口读到的设备号,天线号,ID号
char buf_send[18]={0xAA,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xEE};//通信协议2_1:向上位机发送设备号,ID号,请求下灰

char buf_rece[14];//通信协议2_2:上位机返回匹配信息,是否允许下灰14

struct sockaddr_in servaddr;

fd_set rfds;//,wfds;
struct timeval timeout={900,0};//900s

led_fd = open( "/dev/leds", 0); //  LED灯初始化
if (led_fd<0)
{
printf("opne device error\n");
exit(1);
}
else
printf("open successful\n");
for(k=0; k< 4; k++)   //关闭所有LEDS
ioctl(led_fd,0,k);//第二个参数是开1|关0,第三个参数是led标号 从0~3

fp=open_port(fp,2);//接ARM11Tiny6410开发板靠近USB口和黄色视频输出线的串口
/*设置串口:波特率9600,数据位8位,无校验位,停止位1位*/
if(set_opt(fp,9600,8,'N',1)<0)
{
perror("Set_opt error!\n");
return;
}

sockfd=Socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.1.100", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);

Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
while(1){
sleep(1);
while( (comnum=read(fp,com_buf,sizeof(com_buf))) == 0 ){//从串口读取RFID,没有就延时再读
sleep(1);
}
printf("reading for com is %d\n",comnum);
buf_send[2] = com_buf[1];        //将从串口读到的RFID数据存储,添加设备号
for(i=2; i<14; i++)
buf_send[i+1] = com_buf[i];  //添加ID号

printf("Sending to server:\n");
for(i=0; i< 18; i++)
printf("%X ",buf_send[i]);
printf("\n");

//tt:
write(sockfd, buf_send, sizeof(buf_send));

if(buf_send[2] > 0x03){ //4-15号设备对应的PLC才会收到数据
usleep(1000);
FD_ZERO(&rfds);
FD_SET(sockfd,&rfds);
//        FD_ZERO(&wfds);
//		FD_SET(sockfd,&wfds);

n_selt=select(sockfd+1,&rfds,NULL,NULL,&timeout);
switch(n_selt){
case -1:
perror("select error\n");
exit(0);break;
case 0:
perror("time out\n");break;
//goto tt ;
default:
if(FD_ISSET(sockfd,&rfds)){
printf("Receving from server:\n");
n = read(sockfd, buf_rece, sizeof(buf_rece));

if ( (matchfile = fopen("match.txt", "w")) == NULL ) //文件初始化match.txt,参数w:没有就新建,每次都覆盖
{
fprintf(stderr, "I couldn't open the file \"match.txt\"\n");
exit(2);
}

for(i=0;i<sizeof(buf_rece);i++){   //车牌号,灰级,匹配信息(控制台)显示部分
if((i>=3)&&(i<=8)){
printf("%c ",buf_rece[i]);
fprintf(matchfile,"%c",buf_rece[i]);   //保存6位车牌号到match.txt
}
else
printf("%X ",buf_rece[i]);
}
printf("\n");
fprintf(matchfile,"%c",',');  //写入一个分割符号
fprintf(matchfile,"%c",buf_rece[9]+0x30);  //灰级1 2 3
fprintf(matchfile,"%c",',');  //写入一个分割符号
if(0x11 == buf_rece[10])
fprintf(matchfile,"%c",'1');           //匹配  1
else
fprintf(matchfile,"%c",'2');		   //不匹配2

if (fclose(matchfile) != 0)                //不关闭的话,文件里面没有内容
fprintf(stderr,"Error matchfile closing files\n");

if(0x11 == buf_rece[10])               //控制部分
{
for(k=0; k< 4; k++)
ioctl(led_fd,1,k);  //匹配成功,开灯
sleep(10);
for(k=0; k< 4; k++)
ioctl(led_fd,0,k); //延时30s关闭
}
else
{

for(k=0; k< 4; k++)
ioctl(led_fd,0,k);
}

}

}

}

}

Close(sockfd);
return 0;

}


注释:上面标红的if判断语句
if(buf_send[2] > 0x03){ //4-15号设备对应的PLC才会收到数据
,说明1 2 3号设备进行单项通信;4号及4号以上的设备进行的是双向通信。

(2)然后介绍qt显示部分

其工作原理是每隔500ms读取match.txt文件一次并把其内容显示到触摸屏上

1)介绍main.cpp,标红的
//中文支持
三行语句是让程序支持中文显示的。

#include <QtGui/QApplication>
#include "widget.h"

#include <QTextCodec>  //UTF-8 Head file
int main(int argc, char *argv[])
{
QApplication a(argc, argv);

//中文支持
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));       //支持Tr中文
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));//支持中文文件名显示

Widget w;
w.show();

return a.exec();
}
2)介绍widget.h,标红的语句
void on_fileChanged();
是声明一个自定义的槽函数

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
Q_OBJECT

public:
explicit Widget(QWidget *parent = 0);
~Widget();

private slots:
void on_fileChanged();

private:
Ui::Widget *ui;

};

#endif // WIDGET_H
3)介绍widget.cpp,这是程序最核心的部分

#include "widget.h"
#include "ui_widget.h"

#include <QTextCodec>
#include <QTextStream>
#include <QFile>
#include <QString>
#include <QDebug>
#include <QFileSystemWatcher>
#include <QtGui>
#include <QTimer>
#include <QBitArray>

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(on_fileChanged()));
timer->start(500);

}

Widget::~Widget()
{
delete ui;
}

void Widget::on_fileChanged()
{
QTextCodec * code=QTextCodec::codecForName("utf8");

QFile file("match.txt");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"QT Cannot open file for Reading";
return;
}
QTextStream stream(&file);
stream.setCodec(code);
ui->lineEdit->clear();
ui->lineEdit_2->clear();
ui->lineEdit_3->clear();

while(stream.atEnd()==0)
{
QString line=stream.readLine();

QStringList list=line.split(",");

ui->lineEdit->setText(tr("鄂")+list.at(0));

int i=list.at(1).toInt();
switch(i)
{
case 1: ui->lineEdit_2->setText(tr("一级"));break;
case 2: ui->lineEdit_2->setText(tr("二级"));break;
case 3: ui->lineEdit_2->setText(tr("三级"));break;
case 4: ui->lineEdit_2->setText(tr("原灰"));break;
default: break;

}

switch(list.at(2).toInt())
{
case 1:ui->lineEdit_3->setText(tr("匹配"));break;
case 2:ui->lineEdit_3->setText(tr("不匹配"));break;
default: break;

}
}

}
match。txt文件内容如下图



(3)最后进行整合

要让所有的程序按照预期的运行,第一步是关掉Tiny6410开机自启动的led流水灯,不然不能获得led灯的控制权了;第二步关掉Tiny6410开机自启动的Qtopia,不然回造成显示界面的重叠混乱;第三步后台运行我们自己写的qt程序;第四步启动arm版上的通信程序(注:需要先启动tcp server),至此整个通信所有的准备工作都完成了。

我将上面的四步工作整合成一个sh文件,操作更加简便。

start_qt_client.sh

#!/bin/sh

/etc/rc.d/init.d/leds stop

killall qpe
killall quicklauncher
killall qss       # Three to close Qtopia

qt ./match &  # run in background

./all_client
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐