Linux 下简单的串口编程

这两天用到串口开发,写了一个简单的串口(RS232)测试程序

硬件平台:i.MAX6UL

软件平台:Linux3.14.38

作者:scdlchen@163.com


先看目录结构

.
├── include
 |   └── uart .h
├── install
├── main.c
├── Makefile
├── serial
├── tags
└── uart.c

#########################################

uart.h

#ifndef __TEST_UART_H
#define __TEST_UART_H


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>



enum BOOL{
FALSE = 0,
TRUE = 1
};


typedef struct serial_config {
char port[64];
int fd;
int speed;
int databits;
int stopbits;
int parity;


ssize_t (*read)(int fd, void *buf, size_t nbytes, int timeout);
ssize_t (*write)(int fd, void *buf, size_t nbytes);

} serial_config_t;




int SetSpeed(int fd, int speed);
int SetParity(int fd, int databits, int stopbits, int parity);
int serial_open(const char *port);
int serial_init(serial_config_t *s_cfg);
ssize_t serial_read(int fd, void *buf, size_t nbytes, int timeout);
ssize_t serial_write(int fd, void *buf, size_t nbytes);


#endif

##########################################

uart.c

/*
 * uart.c
 */


#include "uart.h"


int SetSpeed(int fd, int speed)
{

int name_arr[] = {115200, 38400, 19200, 9600, 4800, 2400};
int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400};


int i; 
struct termios Opt;


if(tcgetattr(fd, &Opt) != 0){
perror("tcgetattr error:");
return FALSE;
}


for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++){
if(speed == name_arr[i]){
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
if (tcsetattr(fd, TCSADRAIN, &Opt) != 0) {
perror("tcsetattr error:");
return FALSE;
}
tcflush(fd, TCIOFLUSH);
}
}
return TRUE;
}


int SetParity(int fd, int databits, int stopbits, int parity)
{
struct termios Opt;
if(tcgetattr(fd, &Opt) != 0){
perror("tcgetattr err:");
return FALSE;
}


switch(databits){
case 5:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS5;
break;
case 6:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS6;
break;
case 7:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS7;
break;
case 8:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size.\n");
return FALSE;
}


switch(parity){
case 'n':
case 'N':
Opt.c_cflag &= ~PARENB;
Opt.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
Opt.c_cflag |= PARENB;
Opt.c_cflag |= PARODD;
Opt.c_iflag |= INPCK;
break;
case 'e':
case 'E':
Opt.c_cflag |= PARENB;
Opt.c_cflag &= ~PARODD;
Opt.c_iflag |= INPCK;
break;
case 's':
case 'S':
Opt.c_cflag &= ~PARENB;
Opt.c_cflag &= ~CSTOPB;
Opt.c_iflag |= INPCK;
break;
default:
fprintf(stderr, "Unsupported parity.\n");
return FALSE;
}


switch(stopbits){
case 1:
Opt.c_cflag &= ~CSTOPB;
break;
case 2:
Opt.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "Unsupported stopbits.\n");
return FALSE;
}


Opt.c_cflag |= (CLOCAL | CREAD); // 这个选项通常都要打开


Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);


Opt.c_oflag &= ~OPOST;
Opt.c_oflag &= ~(ONLCR | OCRNL);


Opt.c_iflag &= ~(ICRNL | INLCR);
Opt.c_iflag &= ~(IXON | IXOFF | IXANY);


tcflush(fd, TCIFLUSH);
Opt.c_cc[VTIME] = 0;
Opt.c_cc[VMIN] = 0;
if(tcsetattr(fd, TCSANOW, &Opt) != 0){
perror("tcsetattr fd!");
return FALSE;
}


return TRUE;
}


int serial_open(const char *port)
{
int fd = -1;
if ((fd = open(port, O_RDWR | O_NDELAY)) < 0) {
fprintf(stderr, "open %s error: %s\n", port, strerror(errno));
return -1;
}
return fd;
}


int serial_init(serial_config_t *s_cfg)
{
if ((s_cfg->fd = serial_open(s_cfg->port)) < 0) {
return -1;
}


SetSpeed(s_cfg->fd, s_cfg->speed);


if (SetParity(s_cfg->fd, s_cfg->databits, s_cfg->stopbits, s_cfg->parity) <= 0) {
fprintf(stderr, "SetParity for %s failed\n", s_cfg->port);
return -1;
}


s_cfg->read = serial_read;
s_cfg->write = serial_write;


printf("Set %s Config: %d%c%d%d\n", s_cfg->port, 
s_cfg->speed, s_cfg->parity, s_cfg->databits, s_cfg->stopbits);


return 0;
}




ssize_t serial_read(int fd, void *buf, size_t nbytes, int timeout)
{
int nfds;
fd_set readfds;
struct timeval tv;


tv.tv_sec = 0;
tv.tv_usec = timeout;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
nfds = select(fd + 1, &readfds, NULL, NULL, &tv);

if (nfds <= 0) {
fprintf(stderr, "select err: %s\n", strerror(errno));
return -1;
}
return read(fd, buf, nbytes);
}



ssize_t serial_write(int fd, void *buf, size_t nbytes)
{
return write(fd, buf, nbytes);
}

##########################################

main.c

#include "uart.h"


#define BUFSIZE 1024


int main(int argc, char *argv[])
{
if (argc < 4) {
fprintf(stderr, "Usage: <%s> <port>/- <speed>/- <databits>/- <parity>/- <stopbits>/-\n", argv[0]);
return 1;
}


serial_config_t s_cfg;
memset(&s_cfg, 0, sizeof(s_cfg));


if (argv[1][0] != '-') {
memcpy(s_cfg.port, argv[1], strlen(argv[1])); 
} else {
memcpy(s_cfg.port, "/dev/ttymxc3", strlen(argv[1])); 
}


if (argv[2][0] != '-') {
s_cfg.speed = atoi(argv[2]);
} else {
s_cfg.speed = 115200;
}


if (argv[3][0] != '-') {
s_cfg.databits = atoi(argv[3]);
} else {
s_cfg.databits = 8;
}


if (argv[4][0] != '-') {
s_cfg.parity = argv[4][0];
} else {
s_cfg.parity = 'N';
}


if (argv[5][0] != '-') {
s_cfg.stopbits = atoi(argv[5]);
} else {
s_cfg.stopbits = 1;
}


if (serial_init(&s_cfg) < 0) {
return -1;
}


int rbytes = 0, wbytes = 0;
char buf[BUFSIZE + 1] = {0};
char temp[] = "You failed on your promise, and I'm not gonna failed on mine, I don't wanna see you any more, take a hike!\n";
char test[] = "I should have tell you the day I met you, I love you! Hillar's running for the presentdent of the United States of America.  \
  Everything is gonna be fine, Ok Thank You from the bottom of my heart. That exactly what I wanted him to do. \
  I don't think I can change his mind. What the hell. We should do this more often. You know son, you can always come to me \
  Anyting you want, tell me, Holly shit. How embarrassing? Can you uh...you know what I mean Let's do it. Hey man, we got work to do\
  What kink of people do you think I am? The people who make big decision. How could you do that.Whose shirt is this? Can I have it?\
  Why? cause I am old? You have no idea about who I have just met. Can you understand? You don't understand\n";
//wbytes = s_cfg.write(s_cfg.fd, temp, strlen(temp));
wbytes = s_cfg.write(s_cfg.fd, test, strlen(test));
printf("%d bytes send\n", wbytes);

while (1) {
if ((rbytes = s_cfg.read(s_cfg.fd, buf, BUFSIZE, 5000000)) < 0) {
if (errno == ETIME) {
//printf("select timeout\n");
sleep(1);
continue ;
}
fprintf(stderr, "read serial error: %s\n", strerror(errno));
return 1;

if (rbytes == 0) {
printf("Read EOF from serial\n");
break ;
}

printf("get %d bytes: %s\n", rbytes, buf);
}

return 0;
}

##########################################

将程序下载到开发板上,开发板通过串口连接到PC的串口工具,程序运行正常。

程序目前只支持232,485有待后续更新。学艺不精,有纰漏错误之处请不吝赐教。

如有雷同,纯属巧合!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值