最近一段时间做了一个项目,客户要使用串口进行通信,接收上位机的数据,根据数据控制一些外围器件和传递数据。下位机串口通信已写好,上位机使用windos的串口小助手进行调试,也已经OK。 还需要写一个linux端的应用程序,由于之前几年从事过linux android驱动调试,故调试起来很顺利。摸鱼之际,写下此篇博客记载之:
1.总体目录 见图:
main.c为主程序,接收参数进行处理。
uart.c为串口通信功能函数
inband.c为串口协议数据处理
makefile脚本----你懂得。。。
2.主程序
废话不多说,直接上代码:
void main(int argc, char **argv)
{
char *uart1 ="/dev/ttyUSB0"; //USB串口 插入后 ls -l /dev/ttyUSB* 查看
int fd, uartfd;
printf("this is the test file! \n");
for (int i = 0; i < argc; i++)
printf(" the argv[%d]:%s \n", i, argv[i]);
if ((uartfd = open(uart1, O_RDWR | O_NOCTTY)) < 0)//非阻塞读方式 打开串口
{
printf("open %s is failed", uart1);
exit(1);
}
if (set_opt(uartfd, 9600, 8, 'N', 1) != 0)
{
printf("init uart fail \n");
exit(1);
}
if(argc==1) //只有一个参数的情况下
{
printf("wrong paramters given \n");
}
printf("enter the cmd...\n");
if (strcmp(argv[1], "READ") == 0) //
{
if(strcmp(argv[2], "brd_name") == 0)
{
write(uartfd, cmdGetFruBsn1, 9); //
read_fru();
}
else if(strcmp(argv[2], "brd_sn") == 0)
write(uartfd, cmdfru1, 8);
else if(strcmp(argv[2], "brd_pn") == 0)
write(uartfd, cmdfru2, 8);
else if(strcmp(argv[2], "brd_mfr") == 0)
write(uartfd, cmdfru3, 8);
else if(strcmp(argv[2], "prd_name") == 0)
write(uartfd, cmdfru4, 8);
else if(strcmp(argv[2], "prd_pn") == 0)
write(uartfd, cmdfru5, 8);
else if(strcmp(argv[2], "prd_sn") == 0)
write(uartfd, cmdfru6, 8);
else if(strcmp(argv[2], "prd_mfr") == 0)
write(uartfd, cmdfru7, 8);
else if(strcmp(argv[2], "prd_pv") == 0)
write(uartfd, cmdfru8, 8);
else if(strcmp(argv[2], "prd_pmn") == 0)
write(uartfd, cmdfru9, 8);
if(strcmp(argv[2], "all") == 0)
write(uartfd, cmdfru10, 8);
else
{
printf("wrong paramters given \n");
exit(0);
}
read_uart();
}
else if (strcmp(argv[1], "mc") == 0)
{
write(uartfd, cmdGetBmcVersion, 8);
read_uart();
}
else if (strcmp(argv[1], "sensor") == 0)
{
write(uartfd, cmdsensor, 8);
read_uart();
}
else if (strcmp(argv[1], "param") == 0)
{
write(uartfd, cmdparam, 8);
read_uart();
}
else if (strcmp(argv[1], "raw") == 0)
{
for (int i=0;i<=argc-2;i++ )
{
cmdraw[i]=argv[2+i];
}
write(uartfd, cmdfru, argc-2);
}
else
{
printf("wrong paramters given \n");
}
close(uartfd);
printf("the end ! \n");
exit(0);
}//end main
//读取串口数据函数
void read_uart(){
BYTE n=0;
while (1) {
while ((nByte = read(uartfd, recbuffer, 128)) > 0) {
recbuffer[nByte + 1] = 0;//
printf(" the fur information len:%d \n", nByte);
printf(" the fur information is :%s \n", recbuffer);
if ((recbuffer[0] == 0x5C) && (recbuffer[1] == 0x8D) && (recbuffer[2] == 0x1) &&
(recbuffer[nByte - 2] == 0x5C) && (recbuffer[nByte-1] == 0xD8))
{
In_band_process(recbuffer, nByte); //数据处理
Rev_Data[Rev_Real_DataLen + 1] = 0;
memset(Rev_Data, 0, strlen(Rev_Data));
memset(recbuffer, 0, strlen(recbuffer));
nByte = 0;
close(uartfd);
return; //读完毕,退出
}
close(uartfd);
return;//exit(0);
}
n++;
if (n>=2)
return ;
} //end while(1)
}
2.串口设置函数
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
//#include <time.h>
#include <sys/types.h>
#include <termios.h>
#include <errno.h>
#include "uart.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;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
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] = 100;///* 设置超时10 seconds*/
newtio.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
{
perror("com set error");
return -1;
}
// printf("set done!\n\r");
return 0;
}
3.数据处理,校验函数。没有参考价值,依具体情况而处理数据。故略之……
4.makefile脚本
test:main.o uart.o inband.o
gcc main.o uart.o inband.o -o test
uart.o:uart.c uart.h
gcc -c uart.c -o uart.o
inband.o:inband.c inband.h
gcc -c inband.c -o inband.o
main.o:main.c
gcc -c main.c -o main.o
clean:
rm -rf *.o test
测试可正常通信,获取到数据。
重点:在linux下需要root权限下,方可调用成功。
执行 ./test mc