分享

Linux下的串口编程

 Mytez 2017-03-09

    串口设备一般在/dev/ttyS0-ttyS4。Linux下一切皆文件,把ttyS0结点当做文件操作,当然,获取描述符后先配置一下,open、read、write、close你肯定会吧,那,串口编程,你也肯定会了。

    这代码我之前测试过,很ok,但发上来前,我可没测过哦,不过,看看,有思路也是不错的。

 

一:串口发送端程序

/***************************************************************************************************
**文件:w_uart.c
**编写者:huangminqiang
**编写日期:2012年10月15号
**简要描述:串口发送程序,在PC机上发送。
**修改者:
**修改日期:2012年11月12号
**注:
****************************************************************************************************/
#include
#include
#include
#include
#include
#include

#define COM '/dev/ttyS0'

typedef enum
{
 NON, //无校验
 ODD, //偶校验
 EVEN,//奇校验
}cal_t;

/****** 设置串口***************************************************************************************/
static int set_com(int fd, int speed, int bits, cal_t cal, int stop )
{
 struct termios curtio;

 memset(&curtio, 0, sizeof(curtio));

 //取得串口已有的属性
 if (0 != tcgetattr(fd, &curtio))
 {
  perror('Failed to tcgetattr');
  return -1;
 }

 //设置输入输出波特率
 cfsetispeed(&curtio, speed);
 cfsetospeed(&curtio, speed);

 //设置为原始模式
 curtio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | ECHOE | ECHOK | ECHONL);
 curtio.c_iflag &= ~(BRKINT | IUCLC | ICRNL | INLCR | IGNCR);

 //激活相应选项
 curtio.c_cflag |= CLOCAL | CREAD;

 //设置数据位
 curtio.c_cflag &= ~CSIZE;
 curtio.c_cflag |= bits;
 
 //设置校验位
 if (ODD == cal)
 {
  curtio.c_iflag |= (INPCK | ISTRIP);
  curtio.c_cflag |= PARENB;
  curtio.c_cflag |= PARODD;
 }
 else if(EVEN == cal)
 {
  curtio.c_iflag |= (INPCK | ISTRIP);
  curtio.c_cflag |= PARENB;
  curtio.c_cflag &= ~PARODD;
 }
 else
 {
  curtio.c_cflag &= ~PARENB;
 }

 //设置停止位
 if (2 == stop)
 {
  curtio.c_cflag |= CSTOPB;
 }
 else
 {
  curtio.c_cflag &= ~CSTOPB;
 }

 //设置最少字符等待时间
 curtio.c_cc[VTIME] = 0;
 curtio.c_cc[VMIN] = 0;

 //清空缓冲
 tcflush(fd, TCIOFLUSH);

 //设置新串口属性
 if (0 != tcsetattr(fd, TCSANOW, &curtio))
 {
  perror('Failed to tcgetattr');
  return -1;
 }

 printf('set done!\n');

 return 0;
}


/****** 写入串口信息 **********************************************************************************/
int WriteUartInfo(void)
{
 int fd;
 int cnt = 0;
 int w_cnt = 0;
 unsigned char w_buf[128];

 //打开串口
 fd = open(COM, O_RDWR);
 if(0 > fd)
 {
  perror('uart open err:');
  return -1;
 }
 
 #if 0
 //设置串口参数
 if (0 != set_com(fd, B115200, CS8, NON, 1))
 {
  printf('set_com failed!\n');
  goto _out;
 }
 #endif
 
 //发送信息
 while(1)
 {
  printf('plese input a buffer : ');
  memset(w_buf, 0, sizeof(w_buf));
  fgets(w_buf, sizeof(w_buf), stdin);
  w_cnt = write(fd, w_buf, sizeof(w_buf));
  if(0 > w_cnt)
  {
   perror('write error : ');
   goto _out;
  }
  printf('sent out ! \n');
  
  //结束判断
  if( !strncmp(w_buf, 'quit', 4) )
  {
   break;
  }
 }

 //关闭串口
 close(fd);
 return 0;
_out:
 close(fd);
 return -1;  
}


/****** 主函数 ****************************************************************************************/
int main(void)
{
 if( WriteUartInfo() )
 {
  printf('write uart data failed!\n');
  return -1;
 }
 
 return 0;
}

 

二:串口接收端程序

/***************************************************************************************************
 **文件:r_uart.c
 **编写者:huangminqiang
 **编写日期:2012年10月15号
 **简要描述:串口接收程序,在板子上运行。
 **修改者:
 **修改日期:2012年11月12号
 **注:
 ****************************************************************************************************/
#include
#include
#include
#include
#include
#include

#define COM '/dev/ttyAMA0'

/****** 读取串口信息 *********************************************************************************/
int ReadUartInfo(void)
{
 int fd;
 int cnt = 0;
 int r_cnt = 0;
 struct termios attr;
 fd_set r_fds;
 struct timeval tv;
 unsigned char r_buf[128] = {0};

 //打开串口
 fd = open(COM, O_RDWR);
 if(0 > fd)
 {
  perror('open uart error : ');
  return -1;
 }

 //由于串口设置已固化,故不需要设置。
 #if 0
 //设置串口参数
 if ( set_com(fd, B115200, CS8, NON, 1) )
 {
  printf('set_com failed!\n');
  goto _out;
 }
 #endif
 
 while(1)
 {
  //清除监测集合
  FD_ZERO(&r_fds);
  //将串口句柄加入到监测集合中
  FD_SET(fd, &r_fds);
  
  //设置超时为3秒
  tv.tv_sec = 3;
  tv.tv_usec = 0;
  
  //监测串口是否有数据接收到,超时为3秒
  cnt = select(fd + 1, &r_fds, NULL, NULL, &tv);
  switch(cnt)
  {
   case 0://超时
    //printf('time out !\n');
    break;
   case -1://错误
    perror('select : ');
    goto _out;

   default:
    if( FD_ISSET(fd, &r_fds) ) //有数据可读
    {
     //接收数据
     r_cnt = read(fd, r_buf, sizeof (r_buf));
     if(0 > r_cnt)
     {
      perror('read error : ');
      goto _out;
     }
     //printf('%s', r_buf);
     //system(r_buf);
    }
  }
  
  memset(r_buf, 0, sizeof(r_buf));  
 }
 
 //  关闭串口
 close(fd);
 return 0;
_out:
 close(fd);
 return -1; 
}


/****** 主函数 ***************************************************************************************/
int main(void)
{
 if( ReadUartInfo() )
 {
  printf('read uart data failed!\n');
  return -1;
 }
 
 return 0;
}

 

因为PC机上的串口设置已经固化,所以,没必要再配置了,串口的收发程序主要用于板子(新)上的,而上面的主要用于测试PC--板子间的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多