您的位置:首页 > 运维架构 > Linux

arm-linux_学习简单串口编程问题

2014-08-24 15:37 555 查看
# 本人所使用的是 ARM tiny6410开发板。

# 以下所属个人实际操作的来,若有不妥或是不对之处,请多多之处不足之处。

# 部分解释来源百度百科Termios

# 首先要明确:实现串口编程的要点在何处,只有明白才会简单明了。

#要验证编程是否成功,记得准备平台哦!不然怎么知道自己的对错呢!

一.准备ARM和一台宿主计算机,要能通信及编译哈~不会?请看此处

二.理解解释的代码,试着对比管道,回想下。

三.尝试自己加点 信号、线程、进程编译调试,看看结果和不和自己的意思,但不需要强求。

——————————————————————————————————————————————————————————

程序头文件提供

#include <stdio.h>

#include <errno.h>

#include <fcntl.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <termios.h>

#include <sys/stat.h>

#include <sys/types.h>

#include "serial.h" //自己编写的头文件

——————————————————————————————————————————————————————————

基层的代码 serial.c中的串口数据初始化函数 set_opt。(后面会给出相关代码)

函数定义 int set_opt(int fd, int nspeed, int nbits, char nevent, int nstop)

fd:文件描述符。

nspeed:波特率设置。

nbits:数据位传输格式。

nevent:传输协议方式。

nstop:设置停止位。

函数大致内容:

1.定义termios 变量,保存初始化数据。

2.变量值清空,大致是置全零的意思。

3.根据自己的ARM设置波特率。

4.设置传输格式。

5.设置传输协议。

6.设置停止位。

7.设置传输模式

实现内容:c_cflag—控制模式 c_cc—控制字符

定义两个 struct termios类的变量 new_state old_state

termios 是记录有大量数据的参数的结构体,里面包括了许许多多的状态标志。

old_state 是保存现有状态值,如果串口操作乱套了,要回复不是很麻烦?所以养成好习惯吧!就算用不到!

new_state 则就是用来使用的啦~

清零 new_state

bzero(&new_state,sizeof(new_state));//将new_state这一个内存空间清零

new_state.c_cflag |= CLOCAL | CREAD; //此句是可以不要的,因为这句是为了以前串口发展还不成熟用的

new_state.c_cflag &= ~CSIZE; //将字符长度掩码

设置波特率

cfsetispeed(&new_state,B115200);//设置 输入 波特率是115200

cfsetospeed(&new_state,B115200);//设置 输出 波特率是115200

设置传输格式

new_state.c_cflag |= CS8; //设置传输以8位bit位为传输方式

设置传输协议

new_state.c_cflag |= PARENB; //允许输出产生奇偶信息以及输入的奇偶校验。我的理解就是“开启”

new_state.c_cflag |= PARODD; //输入输出是奇校验

new_state.c_cflag |= (INPCK | ISTRIP);//启用输入奇偶检测 | 去掉第8位 //想知道为什么去掉第八位请百度奇偶检验吧~

设置停止位

new_state.c_cflag |= CSTOPB;//设置为2位停止位

设置传输模式

new_state.c_cc[VTIME] = 0;//非 canonical 模式非 canonical 模式读的最小字符数。

new_state.c_cc[VMIN] = 0; //非 canonical 模式读的最小字符数。

清空串口里面数据

tcflush(fd,TCIFLUSH);

以下是set_opt参考代码

int set_opt(int fd, int nspeed, int nbits, char nevent, int nstop){

struct termios old_state, new_state;

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

perror("SetupSerial old");

return -1;

}

bzero(&new_state,sizeof(new_state));

// new_state.c_cflag |= CLOCAL | CREAD;

new_state.c_cflag &= ~CSIZE;

switch(nspeed){

case 2400:

cfsetispeed(&new_state,B2400);

cfsetospeed(&new_state,B2400);

break;

case 4800:

cfsetispeed(&new_state,B4800);

cfsetospeed(&new_state,B4800);

break;

case 9600:

cfsetispeed(&new_state,B9600);

cfsetospeed(&new_state,B9600);

break;

case 115200:

cfsetispeed(&new_state,B115200);

cfsetospeed(&new_state,B115200);

break;

case 460800:

cfsetispeed(&new_state,B460800);

cfsetospeed(&new_state,B460800);

break;

default:

cfsetispeed(&new_state, B9600);

cfsetospeed(&new_state, B9600);

break;

}

switch(nbits){

case 7:

new_state.c_cflag |= CS7;

break;

case 8:

new_state.c_cflag |= CS8;

break;

}

switch(nevent){

case 'O':

new_state.c_cflag |= PARENB;

new_state.c_cflag |= PARODD;

new_state.c_cflag |= (INPCK | ISTRIP);

break;

case 'E':

new_state.c_cflag |= PARENB;

new_state.c_cflag |= (INPCK | ISTRIP);

new_state.c_cflag &= ~PARODD;

break;

case 'N':

new_state.c_cflag &= ~PARENB;

break;

}

if(nstop==1)

new_state.c_cflag &= ~CSTOPB;

else

if(nstop==2)

new_state.c_cflag |= CSTOPB;

new_state.c_cc[VTIME] = 0;

new_state.c_cc[VMIN] = 0;

tcflush(fd,TCIFLUSH);

if((tcsetattr(fd,TCSANOW,&new_state))!=0){

perror("con set error");

return -1;

}

printf("set done!\n");

return 0;

}

——————————————————————————————————————————————————————————

基层的代码 serial.c中连接端口设置函数 open_port。(后面会给出相关代码)

函数定义int open_port (int fd, int comport)

fd:文件描述符

comport:端口选择

函数大致内容

1.选择端口,建立连接

2.提供描述符控制参数 //具体我还不清楚是做什么的

实现内容:

open("端口",O_RDWR|O_NOCTTY|O_NDELAY)

//读写模式

//如果路径指向终端设备,不要把设备用作控制终端

//如果路径名FIFO/块文件/字符文件,则文件的打开和后继I/O

fcntl和isatty 不会哈……以后修改

以下是open_port参考代码

int open_port (int fd, int comport){

char *dev[]={"/dev/ttySAC3","/dev/ttyUSB1"};

long vdisable;

if (comport==1){

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

if (-1 ==fd ){

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

return (-1);

}

}

else if(comport==2){

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

if (-1 == fd){

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

return(-1);

}

}

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;

}

——————————————————————————————————————————————————————————

基于上述serial.c文件,我们生成一个简单.h文件吧

int set_opt(int,int,int,char,int);

int open_oprt(int,int);

——————————————————————————————————————————————————————————

读的代码 read.c(后面会给出相关代码)

select 函数相关用法

FD_ZERO(&rd) //设立分组rd为一个组

FD_SET(fd,&rd)//绑定描述符

FD_ISSET(fd,&rd)//判断描述符fd是否在给定的描述符集fdset中

实现代码 以下我是想加入signal的程序 不过都已注释

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <errno.h>

#include <stdlib.h>

#include <fcntl.h>

#include <unistd.h>

#include <termios.h>

#include <sys/stat.h>

#include "serial.h"

#include <signal.h>

/*

int k=1;

void sig(int sig){

k=0;

printf("this system will be exit!\n");

}

*/

int main(){

int fd;

int nread,i;

char buff[8];

fd_set rd;

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

perror("open_port");

return;

}

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

perror("set_pot error");

return;

}

FD_ZERO(&rd);

FD_SET(fd,&rd);//归并集合

// signal(SIGINT,sig);

// while(k){

while(FD_ISSET(fd,&rd)){

if(select(fd+1,&rd,NULL,NULL,NULL)<0)

perror("select");

else {

while ((nread=read(fd, buff, 8))>0){

printf("nread=%d,%s\n",nread,buff);

}

}

}

// }

close(fd);

return;

}

——————————————————————————————————————————————————————————

写的代码write.c(相关代码)

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <error.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <termios.h>

#include <stdlib.h>

#include "serial.h"

#include <malloc.h>

#include <signal.h>

/*

int k=1;

void sig(int sig){

k=0;

printf("this system will be exit!\n");

}

*/

int main(){

int fd;

int nwrite,i;

printf("please give me Ctrl+c that exit system!\n");

// getchar();

// signal(SIGINT,sig);

// char *p=NULL;

char p[]="Hello\n";

if((fd=open_port(fd,2))<0){

perror("open_port error");

return;

}

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

perror("set_opt error");

return;

}

/* p=(char*)malloc(sizeof(char)*8);

if(p==NULL){

printf("create malloc that is fail!\n");

exit(0);

}

*/

printf("fd=%d\n\n",fd);

// while(k){

puts("please give message\n");

// gets(p);

nwrite=write(fd,p,8);

printf("nwrite=%d\n",nwrite);

// }

// free(p);

close(fd);

return;

}

下面说下我的见解
串口编程 与 进程见通信、管道等基本上都是相同的

建立fd 描述符,打开“通道”,对通道的读与写的操作都是一致的。

不同用的是所利用的“通道”建立方式不一样。具体……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: