串口通信之简单协议-----结构体的发送

来源:互联网 发布:java面试宝典2017 编辑:程序博客网 时间:2024/05/01 17:58

吃饭完了再来写哟!

吃了两碗泡面,和迪哥聊了会,接着干活啊。

 

我的这个例子其实就是把单片机和PC机之间要传送的内容打包成一个结构体,结构体的各个成员分别充当不同的角色(指令号,指令参数)

所以关键在于结构体的打包和解包,其实很简单,就用到了一个强制类型转换。

 

单片机机部分:

 

#include <reg52.h>

 

typedef unsigned char uint8;

typedef unsigned int  uint16;

 

sbit s1 = P2^0;    //选通数码管1

sbit en = P2^5;    //573锁存使能位

sbit be = P2^4;     //蜂鸣器选通位

 

uint8 i=0;

uint8 recv_txt[2];   //用来接收数据的缓冲区

 

init_serial()   //初始化串口

{

TMOD = 0x20;   //设置定时器1工作方式1;

TH1  = 0xFD;   //波特率发生器,产生9600的波特率

TL1  = 0xFD;

PCON = 0x00;

SCON = 0x50;   //选择串口工作方式1,允许接收

EA = 1;   //开中断

ES = 1;

TR1 = 1;   //启动定时器

 

}

 

 

 

void delay(void)//10ms

 

{

 

       unsigned char i,j,k;

 

        for(i=5;i>0;i--)

 

        for(j=4;j>0;j--)

 

        for(k=248;k>0;k--);

 

}

 

 

led_control(uint8 i)   //led控制模块

{

      if(i == 0)  //流水灯

     {

          int k,j;

          for(j=0;j<100;j++)

          {

                 P1 = 0xFF;

                 for(k=0;k<8;k++)

                 {

                      P1 = P1 << 1;//左移运算符

                      delay();

                       delay();

                       delay();

                       delay();

                       delay();

                 }

           }

     }

     else if(i == 1)  //花样灯

     {

           uint8 k,j;

           for(j=0;j<100;j++)

          {

                P1 = 0xFF;

 

                for(k=0;k<4;k++)

                {

                     P1 = 0xAA;

                     delay();

                     delay();

                     delay();

                     delay();

                     delay();

                     P1 = 0x55;

                     delay();

     delay();

                     delay();

                     delay();

                     delay();

                }

           }

    }

    else

   {

       return ;

   }

 

}

 

 

seg_control(uint8 i)  //数码管控制模块

{

en = 1;

s1 = 0;

P0 = i; 

 

}

 

buzzer_control()  //蜂鸣器控制模块

{

be = 0;

delay();

delay();

delay();

delay();

delay();

be = 1;

}

 

 

 

handle_date()    //数据处理函数---对串口接收到的数据进行处理

{

uint8 i = recv_txt[0];   //recv_txt[0] 为指令号, 对功能模块进行选择

switch(i)

{

case 0x00:

led_control(recv_txt[1]);   //recv_txt[1]为参数,对应各功能模块不同的反应

break;

case 0x01:

seg_control(recv_txt[1]);

break;

case 0x02:

buzzer_control();

default:

break;

 

}

}

 

 

server() interrupt 4 

{

 EA = 0;

P0 = 0xFF;

P1 = 0xFF;

P2 = 0xFF;

RI = 0;

TI = 0;

recv_txt[i] = SBUF;//这个地方我之前是加了这个段的 while(!RI); RI =0; 结果接收到的数据和PC机发送过来的数据总是不一致,去掉后                                //就好了,感觉还是延时的问题

SBUF = recv_txt[i];

while(!TI);

TI = 0;

 

if(2 == ++i)  //当指令号和参数都获取后,就开始对数据进行处理 , 这里要格外注意, 串口接收数据是一位一位的接收的,每接收一次

{                                                                  都会产生一个中断,所以我这里是产生两次中断之后 才进行一次数据处理

handle_date();

i = 0;

}

EA = 1;

}

 

 

main()

{  

init_serial();

while(1);

}

 

 

 

上位机(PC机)部分:

 

 

#include <stdio.h>

#include <pthread.h>

#include <stdlib.h>

 

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <errno.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <termios.h>

#include <stdlib.h>

 

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)

{

struct termios newtio,oldtio;

if ( tcgetattr( fd,&oldtio) != 0) { 

perror("SetupSerial 1");

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 'O':

newtio.c_cflag |= PARENB;

newtio.c_cflag |= PARODD;

newtio.c_iflag |= (INPCK | ISTRIP);

break;

case 'E': 

newtio.c_iflag |= (INPCK | ISTRIP);

newtio.c_cflag |= PARENB;

newtio.c_cflag &= ~PARODD;

break;

case 'N': 

newtio.c_cflag &= ~PARENB;

break;

}

 

switch( nSpeed )

{

case 2400:

cfsetispeed(&newtio, B2400);

cfsetospeed(&newtio, B2400);

break;

case 4800:

cfsetispeed(&newtio, B4800);

cfsetospeed(&newtio, B4800);

break;

case 9600:

cfsetispeed(&newtio, B9600);

cfsetospeed(&newtio, B9600);

break;

case 115200:

cfsetispeed(&newtio, B115200);

cfsetospeed(&newtio, B115200);

break;

default:

cfsetispeed(&newtio, B9600);

cfsetospeed(&newtio, B9600);

break;

}

if( nStop == 1 )

newtio.c_cflag &= ~CSTOPB;

else if ( nStop == 2 )

newtio.c_cflag |= CSTOPB;

newtio.c_cc[VTIME] = 0;

newtio.c_cc[VMIN] = 0;

tcflush(fd,TCIFLUSH);

if((tcsetattr(fd,TCSANOW,&newtio))!=0)

{

perror("com set error");

return -1;

}

printf("set done!/n");

return 0;

}

 

int open_port(int fd,int comport)

{

char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};

long vdisable;

if (comport==1)

{ fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);

if (-1 == fd){

perror("Can't Open Serial Port");

return(-1);

}

else 

printf("open ttyS0 ...../n");

}

else if(comport==2)

{ fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);

if (-1 == fd){

perror("Can't Open Serial Port");

return(-1);

}

else 

printf("open ttyS1 ...../n");

}

else if (comport==3)

{

fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);

if (-1 == fd){

perror("Can't Open Serial Port");

return(-1);

}

else 

printf("open ttyS2 ...../n");

}

if(fcntl(fd, F_SETFL, 0)<0)

printf("fcntl failed!/n");

else

printf("fcntl=%d/n",fcntl(fd, F_SETFL,0));

if(isatty(STDIN_FILENO)==0)

printf("standard input is not a terminal device/n");

else

printf("isatty success!/n");

printf("fd-open=%d/n",fd);

return fd;

}

 

struct date

{

char command_no;

char arg;

}date1;

 

int main()

{

int fd;

int i,nwrite;

if((fd=open_port(fd,1))<0)

{

perror("open_port error");

return;

}//这里必须要用Com1,其他的试了,都不行。

if((i=set_opt(fd,9600,8,'N',1))<0)

{

perror("set_opt error");

return;

}

while(1)

{

 

printf("please input the command_no:/n");

scanf("%x",&date1.command_no);

 

printf("please input the arg:/n");

scanf("%x",&date1.arg);

nwrite=write(fd,(char*)&date1,sizeof(date1));

}

 

return 0;

}

 

 

原创粉丝点击