备份文档:
1通信协议:《西塞山PLC相关通信协议及规则》
下载链接:http://download.csdn.net/detail/mashang123456789/8128879
协议说明:通信协议分为两种类型,第一种类型是单向通信,ARM版通过串口采集到RFID读卡器信息,并转发给服务器即可。适用于排队读卡器和磅房的两台读卡器。
第二种类型的是双向通信,适用于灰库中的读卡器,ARM板通过串口采集到RFID读卡器信息,做相应处理并按协议转发给中心服务器,中心服务器回复是否匹配信息。
2arm版程序源代码
下面程序需要修改的是两点(已经标红):
1串口号fp=open_port(fp,4);
2中心服务器ip地址inet_pton(AF_INET, "192.168.1.6", &servaddr.sin_addr);
整个工程文件下载链接:http://download.csdn.net/detail/mashang123456789/8128905
其中的核心文件为client.c,即下面的源码,下载链接:http://download.csdn.net/detail/mashang123456789/8128917
/*******************************************************************************
Copyright (C), 2014-2015, FreeTeam Lab, Wuhan University Of Technology.
File name:client.c
Author:LongHui Version:12.2 Date:2014-5-27 15:00:21
Description:(1)串口接收RFID读卡器数据,网口TCP发送数据,接收1-15号设备回复
并保存成一条记录。
Others:
Function List:
1.void *read_com( void *arg )
2.void *socket_send( void *arg )
3.void *socket_rece( void *arg )
History:
1.Date:
Author:
Modification:
2.
*******************************************************************************/
#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 <sqlite3.h>
#include <pthread.h>
#include "../wrap.h"
#define SERV_PORT 2000
//#define DEBUG 0
pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER; // 初始化互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // 初始化条件变量
int sockfd; //网口文件描述符
int fp; //串口文件描述符
int i;
int comnum=0,n_socket=0;//从串口读到的个数,socket 接收到的数据个数,必须初始化
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};//向上位机发送设备号,ID号
char buf_rece[14]={0xAA,0x01,
0x09,66,'S','H',0X41,'2','6',0x03,0x11, //设备号,车牌号(BFHA89说明ASCII码,十六进制,字符都可以发送),灰级,匹配信息。
0x00,0x00,0xEE};//上位机返回匹配信息
/*sqlite数据库相关的全局声明*/
sqlite3 *db;
sqlite3_stmt *stmt;
int rc;
char *zErr;
char name[7]={0}; //临时存储车牌号 龙辉时间格式timestarmp 万学超时间格式timstamp
const char *CREATE="create table if not exists xxs(Id integer primary key, WriterTime timestarmp not null default (datetime('now','localtime')), ReaderNo varchar(3), CarNo varchar(20), GradeCode varchar(3), IsMatch varchar(3))";
/*******************************************************************************
Function:(1)void *read_com( void *arg )
Description:从串口读取RFID数据
Calls:
Calls By:main function
Input:
Output:
Return:
Others:
*******************************************************************************/
void *read_com( void *arg ) //(1)读取串口数据线程
{
while(1){
pthread_mutex_lock( &mutex);
if((comnum=read(fp,com_buf,sizeof(com_buf))) > 0){
pthread_cond_signal( &cond);
comnum=0;//如果不清零,串口读一次,socket会发送两次
}
pthread_mutex_unlock( &mutex);
sleep(1);
}
}
/*******************************************************************************
Function:(2)void *socket_send( void *arg )
Description:将从串口读取到的RFID数据(12字节)经过网口发送给TCP SERVER
Calls:
Calls By:main function
Input:
Output:
Return:
Others:
*******************************************************************************/
void *socket_send( void *arg ) //(2)串口数据socket发送线程
{
while(1){
pthread_mutex_lock( &mutex);
if(comnum == 0){
pthread_cond_wait( &cond, &mutex);
}
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");
write(sockfd, buf_send, sizeof(buf_send));//socket发送数据
pthread_mutex_unlock( &mutex);
sleep(1);
}
}
/*******************************************************************************
Function:(3)void *socket_rece( void *arg )
Description:接收TCP SERVER回复的数据
Calls:
Calls By:main function
Input:
Output:
Return:
Others:
*******************************************************************************/
void *socket_rece( void *arg ) //(3)socket接收线程和相关处理
{
while(1){
if((n_socket=read(sockfd, buf_rece, sizeof(buf_rece))) > 0){
/*********调试:收到的数据打印到屏幕上********/
printf("Receving from server:\n");
for(i=0;i<sizeof(buf_rece);i++){ //车牌号,灰级,匹配信息(控制台)显示部分
if((i>=3)&&(i<=8)){
printf("%c ",buf_rece[i]);
}
else
printf("%X ",buf_rece[i]);
}
printf("\n");
/********************************************/
/********************sqlite数据库存储模块**********************/
if((buf_rece[2] > 0x00)&&(buf_rece[2] < 0x10)){ //4-15号设备对应的PLC才会收到数据,现在改为1-15号都生成一条记录
rc = sqlite3_open("match.db", &db); //打开sqlite数据库,若没有就创建
if(rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
rc = sqlite3_exec(db, CREATE, NULL, NULL, &zErr); //在库中创建一张表,若存在就不用创建了
if(rc != SQLITE_OK) {
if (zErr != NULL) {
fprintf(stderr, "SQL error(create): %s\n", zErr);
sqlite3_free(zErr);
}
}
strncpy(name,buf_rece+3,6);
name[6]='\0';
rc = sqlite3_prepare_v2(db, "insert into xxs (ReaderNo, CarNo, GradeCode, IsMatch) values (?, ?, ?, ?)", -1, &stmt, 0);
if (rc != SQLITE_OK){
fprintf(stderr, "sql error:%s\n", sqlite3_errmsg(db));
}
sqlite3_bind_int(stmt, 1, buf_rece[2]); //保存设备号
sqlite3_bind_text(stmt, 2, name, strlen(name),SQLITE_STATIC);//保存车牌号
sqlite3_bind_int(stmt, 3, buf_rece[9]); //保存灰等级
sqlite3_bind_int(stmt, 4, buf_rece[10]); //保存匹配信息:17(0X11)匹配,34(0X22)不匹配
rc = sqlite3_step(stmt);
if( rc != SQLITE_DONE){
printf("%s",sqlite3_errmsg(db));
}
sqlite3_reset(stmt); //复位sqlite3_bind_text绑定的语句,可重用stat,提高运行速度
sqlite3_close(db); //关闭数据库
}
/******************************************************************/
}
}
}
int main(int argc,char ** argv)
{
pthread_t tid_com; //线程1:读取串口标签数据
pthread_t tid_send; //线程2:将读到的串口数据通过socket发送出去
pthread_t tid_rece; //线程3:接收socket回复的数据,独立运行
struct sockaddr_in servaddr;
// fp=open_port(fp,2); //接ARM11Tiny6410开发板靠近USB口和黄色视频输出线的串口, mini2440
fp=open_port(fp,4); //Tiny4412只有COM0和COM3已经引出来,COM0是靠近电源的,右边是COM3
/*设置串口:波特率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.6", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if(pthread_create( &tid_com, NULL, read_com, NULL ) !=0 ){ //(1)创建读取串口数据线程
printf("pthread_creat error with reading com!\n");
exit(EXIT_FAILURE );
}
if(pthread_create( &tid_send, NULL, socket_send, NULL ) !=0 ){ //(2)创建socket发送线程
printf("pthread_creat error with socket sending!\n");
exit(EXIT_FAILURE );
}
if(pthread_create( &tid_rece, NULL, socket_rece, NULL ) !=0 ){ //(3)创建读取串口数据线程
printf("pthread_creat error with socket_rece!\n");
exit(EXIT_FAILURE );
}
pthread_join( tid_com, NULL);
pthread_join( tid_send, NULL);
pthread_join( tid_rece, NULL);
pthread_mutex_destroy( &mutex);//销毁自旋锁
pthread_cond_destroy( &cond); //销毁条件变量
Close(sockfd);
return 0;
}