Linux下串口协议控制51单片机
上位机程序
/***************************************************************************
writen by jingshui 7-17 2011 12:53
说明:这是一个linux下串口,多线程测试程序
Version 0.26
***************************************************************************/
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <termios.h>
# include <fcntl.h>
# include <string.h>
# include <sys/time.h>
# include <sys/types.h>
# include <pthread.h>
int fd;
pthread_t thread[2];
pthread_mutex_t mutex;
/****************************************************************************
结构体说明:传送控制单片机的信息
成员1:select 选择功能模块
成员2:control 控制单片机相应的动作
*****************************************************************************/
struct protocal
{
unsigned char select;
unsigned char control;
};
struct protocal ptr[14]={{0xa1,0x01},{0xa1,0x02},{0xa1,0x03},{0xa1,0x04},{0xa1,0x05},
{0xa1,0x06},{0xa1,0x07},{0xa1,0x08},{0xb2,0x00},{0xb2,0x03},
{0xb2,0x06},{0xb2,0x09},{0xb2,0x0e},{0xc3,0xd4}};
/********************************************************************
功能说明:设置linux串口参数
传入参数:
fd nspeed nbit nevent nstop
文件句柄 波特率 数据位 奇偶校验 停止位
返回值: fd 文件句柄
********************************************************************/
int set_port(int fd ,int nspeed ,int nbits ,char nevent ,int nstop)
{
struct termios newtio,oldtio;
if (tcgetattr(fd,&oldtio)!= 0)
{
perror("setup serial");
return -1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL|CREAD;
newtio.c_cflag &= ~CSIZE;
switch (nbits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch (nevent)
{
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch (nspeed)
{
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
switch (nstop)
{
case 1:
newtio.c_cflag &= ~CSTOPB;
break;
case 2:
newtio.c_cflag |= CSTOPB;
break;
}
newtio.c_cc[VTIME]= 0;
newtio.c_cc[VMIN]= 14;
tcflush(fd,TCIFLUSH);
if ((tcsetattr(fd,TCSANOW,&newtio))!= 0)
{
perror("com set");
return -1;
}
return 0;
}
int open_port(int fd,int comport)
{
if (comport == 1){
fd = open ("/dev/ttyUSB0",O_RDWR);
if ( -1 == fd ){
perror("can't open serial port");
return -1;
}
}
return fd;
}
void write_port(void)
{
int nwrite,i;
for (i=0;i<14;i++)
{
nwrite = write(fd,&ptr[i],2);
usleep(200000);/*每200ms秒发一次数据*/
}
}
void read_port(void)
{
fd_set rd;
int nread,retval;
unsigned char msg[14];
struct timeval timeout;
FD_ZERO(&rd);
FD_SET(fd,&rd);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
retval = select (fd+1,&rd,NULL,NULL,&timeout);/*select 实现i/o复用*/
switch (retval)
{
case 0:
printf("no data input within 1 seconds.\n");
break;
case -1:
perror("select");
break;
default:
if((nread=read(fd,msg,14))>0)
{
printf("nread=%d,msg=%s\n",nread,msg);
}
break;
}
}
void *recv_thread(void )
{
pthread_mutex_lock(&mutex);
read_port();
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void *send_thread(void )
{
pthread_mutex_lock(&mutex);
write_port();
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void create_thread(void )
{
int temp;
memset(thread, 0, sizeof(thread));
if((temp = pthread_create(&thread[0], NULL,(void *)send_thread, NULL)) != 0)
printf("create send_thread failed!\n");
if((temp = pthread_create(&thread[1], NULL,(void *)recv_thread, NULL)) != 0)
printf("create recev_thread failed!\n");
}
void wait_thread(void )
{
if(thread[0] !=0)
{
pthread_join(thread[0],NULL);
printf("send_thread end\n");
}
if(thread[1] !=0)
{
pthread_join(thread[1],NULL);
printf("recev_thread end\n");
}
}
int main(void )
{
int i;
if((fd=open_port(fd,1))<0){
perror("open_port error");
}
if((i=set_port(fd,9600,8,'N',1))<0){
perror("set_opt error");
}
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mutex,NULL);
int num = 100;
while (num)
{
create_thread();
wait_thread();
num--;
}
pthread_mutex_destroy(&mutex);
close(fd);
return 0;
}