Linux下串口协议控制51单片机.docx
《Linux下串口协议控制51单片机.docx》由会员分享,可在线阅读,更多相关《Linux下串口协议控制51单片机.docx(16页珍藏版)》请在冰豆网上搜索。
![Linux下串口协议控制51单片机.docx](https://file1.bdocx.com/fileroot1/2023-1/23/cd70d2f3-4bed-4a5c-b393-83c87dca8fa6/cd70d2f3-4bed-4a5c-b393-83c87dca8fa61.gif)
Linux下串口协议控制51单片机
linux下串口协议控制51单片机(涉及多线程操作)
/***************************************************************************
writenbyjingshui7-17201112:
53
说明:
这是一个linux下串口,多线程测试程序
Version0.26
***************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
intfd;
pthread_tthread[2];
pthread_mutex_tmutex;
/****************************************************************************
结构体说明:
传送控制单片机的信息
成员1:
select选择功能模块
成员2:
control控制单片机相应的动作
*****************************************************************************/
structprotocal
{
unsignedcharselect;
unsignedcharcontrol;
};
structprotocalptr[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串口参数
传入参数:
fdnspeednbitneventnstop
文件句柄波特率数据位奇偶校验停止位
返回值:
fd文件句柄
********************************************************************/
intset_port(intfd,intnspeed,intnbits,charnevent,intnstop)
{
structtermiosnewtio,oldtio;
if(tcgetattr(fd,&oldtio)!
=0)
{
perror("setupserial");
return-1;
}
bzero(&newtio,sizeof(newtio));
newtio.c_cflag|=CLOCAL|CREAD;
newtio.c_cflag&=~CSIZE;
switch(nbits)
{
case7:
newtio.c_cflag|=CS7;
break;
case8:
newtio.c_cflag|=CS8;
break;
}
switch(nevent)
{
case'N':
newtio.c_cflag&=~PARENB;
break;
}
switch(nspeed)
{
case9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
switch(nstop)
{
case1:
newtio.c_cflag&=~CSTOPB;
break;
case2:
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("comset");
return-1;
}
return0;
}
intopen_port(intfd,intcomport)
{
if(comport==1){
fd=open("/dev/ttyUSB0",O_RDWR);
if(-1==fd){
perror("can'topenserialport");
return-1;
}
}
returnfd;
}
voidwrite_port(void)
{
intnwrite,i;
for(i=0;i<14;i++)
{
nwrite=write(fd,&ptr[i],2);
usleep(200000);/*每200ms秒发一次数据*/
}
}
voidread_port(void)
{
fd_setrd;
intnread,retval;
unsignedcharmsg[14];
structtimevaltimeout;
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)
{
case0:
printf("nodatainputwithin1seconds.\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);
}
voidcreate_thread(void)
{
inttemp;
memset(thread,0,sizeof(thread));
if((temp=pthread_create(&thread[0],NULL,(void*)send_thread,NULL))!
=0)
printf("createsend_threadfailed!
\n");
if((temp=pthread_create(&thread[1],NULL,(void*)recv_thread,NULL))!
=0)
printf("createrecev_threadfailed!
\n");
}
voidwait_thread(void)
{
if(thread[0]!
=0)
{
pthread_join(thread[0],NULL);
printf("send_threadend\n");
}
if(thread[1]!
=0)
{
pthread_join(thread[1],NULL);
printf("recev_threadend\n");
}
}
intmain(void)
{
inti;
if((fd=open_port(fd,1))<0){
perror("open_porterror");
}
if((i=set_port(fd,9600,8,'N',1))<0){
perror("set_opterror");
}
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mutex,NULL);
intnum=100;
while(num)
{
create_thread();
wait_thread();
num--;
}
pthread_mutex_destroy(&mutex);
close(fd);
return0;
}
51单片机程序
#include
typedefunsignedcharuint8;
typedefunsignedintuint16;
sbitkey=P3^2;
sbits1=P2^0;//选通数码管1
sbits2=P2^1;
sbits3=P2^2;
sbits4=P2^3;
sbiten=P2^5;//573锁存使能位
sbitbuzzer=P2^4;//蜂鸣器选通位
sbitkey1=P3^2;
sbitkey2=P3^3;
sbitkey3=P3^4;
sbitkey4=P3^5;
sbitkey5=P3^7;
uint8i=0;
uint8r_data[2];//用来接收数据的缓冲区
uint8codesmg[16]={0xC0,0xF9,0xA4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsignedcharcodepmd[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedcharcodes_data1[]="key1pressed\n";
unsignedcharcodes_data2[]="key2pressed\n";
unsignedcharcodes_data3[]="key3pressed\n";
unsignedcharcodes_data4[]="key4pressed\n";
unsignedcharcodes_data5[]="key5pressed\n";
voidinit_serial(void)//初始化串口
{
TMOD=0x20;//设置定时器1工作方式1;
TH1=0xFD;//波特率发生器,产生9600的波特率
TL1=0xFD;
PCON=0x00;
SCON=0x50;//选择串口工作方式1,允许接收
EA=1;//开中断
ES=1;
TR1=1;//启动定时器
}
voiddelay(uint16i)//20ms
{
unsignedcharj,k;
for(j=i;j>0;j--)
for(k=115;k>0;k--);
}
voidtest_serial1(void)
{
inti;
EA=0;
for(i=0;i{
SBUF=s_data1[i];
while(TI==0);
TI=0;
}
EA=1;
}
voidtest_serial2(void)
{
inti;
EA=0;
for(i=0;i{
SBUF=s_data2[i];
while(TI==0);
TI=0;
}
EA=1;
}
voidtest_serial3(void)
{
inti;
EA=0;
for(i=0;i{
SBUF=s_data3[i];
while(TI==0);
TI=0;
}
EA=1;
}
voidtest_serial4(void)
{
inti;
EA=0;
for(i=0;i{
SBUF=s_data4[i];
while(TI==0);
TI=0;
}
EA=1;
}
voidtest_serial5(void)
{
inti;
EA=0;
for(i=0;i{
SBUF=s_data5[i];
while(TI==0);
TI=0;
}
EA=1;
}
voidled_control(uint8i)//led控制模块
{
unsignedcharx;
if(i>8)
{
P1=0xff;
delay(10);
}
else
{
x=i-1;
P1=pmd[x];
delay(80);
P1=0xff;
}
}
voidseg_control(uint8i)//数码管控制模块
{
en=1;
s1=0;
s3=0;
s2=0;
s4=0;
if(i>0x0f)
{
P0=0xff;
delay(10);
}
else
{
P0=smg[i];
delay(80);
P0=0xff;
}
}
voidbuzzer_control(uint8i)//蜂鸣器控制模块
{
if(i==0xd4)
buzzer=0;
delay(100);
buzzer=1;
}
voidhandle_date()
{
uint8i=r_data[0];
switch(i)
{
case0xa1:
led_control(r_data[1]);
break;
case0xb2:
seg_control(r_data[1]);
break;
case0xc3:
buzzer_control(r_data[1]);
default:
break;
}
}
voidreadkey(void)
{
RI=0;
if(!
key1)
{
delay(30);
if(!
key1)
{
test_serial1();
while(!
key1);
}
}
if(!
key2)
{
delay(30);
if(!
key2)
{
test_serial2();
while(!
key2);
}
}
if(!
key3)
{
delay(30);
if(!
key3)
{
test_serial3();
while(!
key3);
}
}
if(!
key4)
{
delay(30);
if(!
key4)
{
test_serial4();
while(!
key4);
}
}
if(!
key5)
{
delay(30);
if(!
key5)
{
test_serial5();
while(!
key5);
}
}
}
voidmain(void)
{
init_serial();
while
(1)
{
readkey();
}
}
voidserver(void)interrupt4
{
ES=0;
RI=0;
r_data[i]=SBUF;
if(2==++i)
{
handle_date();
i=0;
}
ES=1;
}
/*******************************************************************************
writenbyjingshui
说明:
51单片机检测程序,把从上位机接收的数据发回去。
*******************************************************************************/
#include
bitflag;
unsignedchara,i;
voidinit_serial(void)
{
TMOD=0x20;//定时器1的工作方式2
TL1=0xfd;//装载计数初值
TH1=0xfd;
SCON=0x50;//采用串口工作方式1,无奇偶校验
PCON=0x00;//串口波特率不加倍
IE=0x90;//开总中断,开串口中断
TR1=1;//启动定时器1
}
voidmain()
{
init_serial();
while
(1)
{
if(flag==1)
{
ES=0;
SBUF=a;
while(!
TI);
TI=0;
ES=1;
flag=0;
}
}
}
voidisr()interrupt4
{
RI=0;
a=SBUF;
flag=1;
}
编程经验:
1.51相对来说是一个很低端的处理器,所以上位机要注意加延时,下位机程序不应有很复杂的语法。
2.调试时应一步步追踪。
3.从最简单朴素的例子开始,先搭一个简单的框架,再一步步添加其他功能。
4.注意实践和理论的结合,理论不行先实践,实践受挫在看理论。