app_uart10_nuvoton.c
/****************************************************************************
* *
* Copyright (c) 2014 Nuvoton Technology Corp. All rights reserved. *
* *
****************************************************************************/
/****************************************************************************
*
* FILENAME
* uart_test.c
*
* VERSION
* 1.0
*
* DESCRIPTION
* This is the test program used to test the UARTs on NUC970 EV board
*
* DATA STRUCTURES
* None
*
* FUNCTIONS
* None
*
* HISTORY
*
*
* REMARK
* None
****************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FALSE 0
#define TRUE 1
int fd[2];
pthread_t threads[10];
char buff[101];
static struct termios newtios,oldtios; /*termianal settings */
static int saved_portfd=-1; /*serial port fd */
static void reset_tty_atexit(void)
{
if(saved_portfd != -1)
{
tcsetattr(saved_portfd,TCSANOW,&oldtios);
}
}
/*cheanup signal handler */
static void reset_tty_handler(int signal)
{
if(saved_portfd != -1)
{
tcsetattr(saved_portfd,TCSANOW,&oldtios);
}
_exit(EXIT_FAILURE);
}
static int open_port(const char *portname)
{
struct sigaction sa;
int portfd;
printf("opening serial port:%s\n",portname);
/*open serial port */
if((portfd=open(portname,O_RDWR | O_NOCTTY)) < 0 )
{
printf("open serial port %s fail \n ",portname);
return portfd;
}
/*get serial port parnms,save away */
tcgetattr(portfd,&newtios);
memcpy(&oldtios,&newtios,sizeof newtios);
/* configure new values */
cfmakeraw(&newtios); /*see man page */
newtios.c_iflag |=IGNPAR; /*ignore parity on input */
newtios.c_oflag &= ~(OPOST | ONLCR | OLCUC | OCRNL | ONOCR | ONLRET | OFILL);
newtios.c_cflag = CS8 | CLOCAL | CREAD;
newtios.c_cc[VMIN]=1; /* block until 1 char received */
newtios.c_cc[VTIME]=0; /*no inter-character timer */
/* 115200 bps */
cfsetospeed(&newtios,B115200);
cfsetispeed(&newtios,B115200);
/* register cleanup stuff */
atexit(reset_tty_atexit);
memset(&sa,0,sizeof sa);
sa.sa_handler = reset_tty_handler;
sigaction(SIGHUP,&sa,NULL);
sigaction(SIGINT,&sa,NULL);
sigaction(SIGPIPE,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
/*apply modified termios */
saved_portfd=portfd;
tcflush(portfd,TCIFLUSH);
tcsetattr(portfd,TCSADRAIN,&newtios);
return portfd;
}
void * process1(void* arg)
{
int portfd = (int) arg;
unsigned char i, j;
int rev1, rev2;
char RxBuffer[101];
rev1 =0;
rev2 =0;
while(rev2 < 100)
{
rev1 = write(portfd,(buff+rev2),100);
rev2 += rev1;
}
printf("\n uart1 send %d byts\n", rev2);
rev1 = 0;
rev2 = 0;
while(rev2 < 100)
{
rev1 = read(portfd,(RxBuffer+rev2),100);
rev2 += rev1;
}
printf("\n uart1 receive %d bytes\n", rev2);
for(i = 0; i < 100; i++)
{
if(i != RxBuffer[i])
{
printf("\n uart1 compare Error!!");
while(1);
}
}
printf("\n uart1 compare correct!!\n");
printf("\n uart1 test done!!\n");
}
void * process2(void* arg)
{
int portfd = (int) arg;
unsigned char i, j;
int rev1, rev2;
char RxBuffer[101];
rev1 =0;
rev2 =0;
while(rev2 < 100)
{
rev1 = write(portfd,(buff+rev2),100);
rev2 += rev1;
}
printf("\n uart2 send %d bytes \n", rev2);
rev1 = 0;
rev2 = 0;
while(rev2 < 100)
{
rev1 = read(portfd,(RxBuffer+rev2),100);
rev2 += rev1;
}
printf("\n uart2 receive %d bytes \n", rev2);
for(i = 0; i < 100; i++)
{
if(i != RxBuffer[i])
{
printf("\n uart2 compare Error!!");
while(1);
}
}
printf("\n uart2 compare correct!!\n");
printf("\n uart2 test done!!\n");
}
/* PB12:TX PB13:RX */
void * process10(void* arg)
{
int portfd = (int) arg;
unsigned char i, j;
int rev1, rev2;
char RxBuffer[101];
rev1 =0;
rev2 =0;
while(rev2 < 100)
{
rev1 = write(portfd,(buff+rev2),100);
rev2 += rev1;
}
printf("\n uart10 send %d bytes \n", rev2);
rev1 = 0;
rev2 = 0;
while(rev2 < 100)
{
rev1 = read(portfd,(RxBuffer+rev2),100);
rev2 += rev1;
}
printf("\n uart10 receive %d bytes \n", rev2);
for(i = 0; i < 100; i++)
{
if(i != RxBuffer[i])
{
printf("\n uart10 compare Error!!");
while(1);
}
}
printf("\n uart10 compare correct!!\n");
printf("\n uart10 test done!!\n");
}
/**
*@breif main()
*/
int main(int argc, char **argv)
{
//char *dev[10]={"/dev/ttyS1", "/dev/ttyS2"};
char *dev[10]={"/dev/ttyS10", "/dev/ttyS2"};
unsigned int i;
printf("\n demo uart10 external loop back function \n");
for(i = 0; i < 100; i++)
{
buff[i] = (i & 0xff);
}
/*
for(i = 0; i < 2; i++)
{
if((fd[i] = open_port(dev[i]))<0)
return -1;
}
*/
if((fd[0] = open_port(dev[0]))<0)
{
printf("\n open_port error ...\n");
return -1;
}
pthread_create(&threads[0], NULL, process10, (void*)(fd[0]));
pthread_join(threads[0], NULL);
/*
pthread_create(&threads[0], NULL, process1, (void*)(fd[0]));
pthread_create(&threads[1], NULL, process2, (void*)(fd[1]));
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
*/
return 0;
}
Makefile
.SUFFIXES : .x .o .c .s
CC := arm-linux-gcc
STRIP := arm-linux-strip
TARGET = uart_demo
SRCS := app_uart10_nuvoton.c
LIBS = -lpthread -lc -lgcc
all:
$(CC) -static $(SRCS) -o $(TARGET) $(LIBS)
$(STRIP) $(TARGET)
clean:
rm -f *.o
rm -f *.x
rm -f *.flat
rm -f *.map
rm -f temp
rm -f *.img
rm -f $(TARGET)
rm -f *.gdb
直接编译不过,用makefile,里面有要添加的库
将PB12和PB13 短接测试,否则就是应用程序就死等
网上找到另一个例子改一下:
app_uart10.c
#include
#include
#include
#include
#include
#include
//为了保证用户输入的波特率是个正确的值,所以需要这两个数组验证,对于设置波特率时候,前面要加个B
int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,
B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300,
115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
/*-----------------------------------------------------------------------------
函数名: set_speed
参数: int fd ,int speed
返回值: void
描述: 设置fd表述符的串口波特率
*-----------------------------------------------------------------------------*/
void set_speed(int fd ,int speed)
{
struct termios opt;
int i;
int status;
tcgetattr(fd,&opt);
for(i = 0;i < sizeof(speed_arr)/sizeof(int);i++)
{
if(speed == name_arr[i]) //找到标准的波特率与用户一致
{
tcflush(fd,TCIOFLUSH); //清除IO输入和输出缓存
cfsetispeed(&opt,speed_arr[i]); //设置串口输入波特率
cfsetospeed(&opt,speed_arr[i]); //设置串口输出波特率
status = tcsetattr(fd,TCSANOW,&opt); //将属性设置到opt的数据结构中,并且立即生效
if(status != 0)
perror("tcsetattr fd:"); //设置失败
return ;
}
tcflush(fd,TCIOFLUSH); //每次清除IO缓存
}
}
/*-----------------------------------------------------------------------------
函数名: set_parity
参数: int fd
返回值: int
描述: 设置fd表述符的奇偶校验
*-----------------------------------------------------------------------------*/
int set_parity(int fd)
{
struct termios opt;
if(tcgetattr(fd,&opt) != 0) //或许原先的配置信息
{
perror("Get opt in parity error:");
return -1;
}
/*通过设置opt数据结构,来配置相关功能,以下为八个数据位,不使能奇偶校验*/
opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
opt.c_oflag &= ~OPOST;
opt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
opt.c_cflag &= ~(CSIZE | PARENB);
opt.c_cflag |= CS8;
tcflush(fd,TCIFLUSH); //清空输入缓存
if(tcsetattr(fd,TCSANOW,&opt) != 0)
{
perror("set attr parity error:");
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------------
函数名: serial_init
参数: char *dev_path,int speed,int is_block
返回值: 初始化成功返回打开的文件描述符
描述: 串口初始化,根据串口文件路径名,串口的速度,和串口是否阻塞,block为1表示阻塞
*-----------------------------------------------------------------------------*/
int serial_init(char *dev_path,int speed,int is_block)
{
int fd;
int flag;
flag = 0;
flag |= O_RDWR; //设置为可读写的串口属性文件
if(is_block == 0)
flag |=O_NONBLOCK; //若为0则表示以非阻塞方式打开
fd = open(dev_path,flag); //打开设备文件
if(fd < 0)
{
perror("Open device file err:");
close(fd);
return -1;
}
/*打开设备文件后,下面开始设置波特率*/
set_speed(fd,speed); //考虑到波特率可能被单独设置,所以独立成函数
/*设置奇偶校验*/
if(set_parity(fd) != 0)
{
perror("set parity error:");
close(fd); //一定要关闭文件,否则文件一直为打开状态
return -1;
}
return fd;
}
/*-----------------------------------------------------------------------------
函数名: serial_send
参数: int fd,char *str,unsigned int len
返回值: 发送成功返回发送长度,否则返回小于0的值
描述: 向fd描述符的串口发送数据,长度为len,内容为str
*-----------------------------------------------------------------------------*/
int serial_send(int fd,char *str,unsigned int len)
{
int ret;
if(len > strlen(str)) //判断长度是否超过str的最大长度
len = strlen(str);
ret = write(fd,str,len);
if(ret < 0)
{
perror("serial send err:");
return -1;
}
return ret;
}
/*-----------------------------------------------------------------------------
函数名: serial_read
参数: int fd,char *str,unsigned int len,unsigned int timeout
返回值: 在规定的时间内读取数据,超时则退出,超时时间为ms级别
描述: 向fd描述符的串口接收数据,长度为len,存入str,timeout 为超时时间
*-----------------------------------------------------------------------------*/
int serial_read(int fd, char *str, unsigned int len, unsigned int timeout)
{
fd_set rfds;
struct timeval tv;
int ret; //每次读的结果
int sret; //select监控结果
int readlen = 0; //实际读到的字节数
char * ptr;
ptr = str; //读指针,每次移动,因为实际读出的长度和传入参数可能存在差异
FD_ZERO(&rfds); //清除文件描述符集合
FD_SET(fd,&rfds); //将fd加入fds文件描述符,以待下面用select方法监听
/*传入的timeout是ms级别的单位,这里需要转换为struct timeval 结构的*/
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout%1000)*1000;
/*防止读数据长度超过缓冲区*/
//if(sizeof(&str) < len)
// len = sizeof(str);
/*开始读*/
while(readlen < len)
{
sret = select(fd+1,&rfds,NULL,NULL,&tv); //检测串口是否可读
if(sret == -1) //检测失败
{
perror("select:");
break;
}
else if(sret > 0)
{
ret = read(fd,ptr,1);
if(ret < 0)
{
perror("read err:");
break;
}
else if(ret == 0)
break;
readlen += ret; //更新读的长度
ptr += ret; //更新读的位置
}
else //超时
{
printf("timeout!\n");
break;
}
}
return readlen;
}
int main()
{
int fd;
int ret;
char str[]="hello linux serial!";
char buf[100];
fd = serial_init("/dev/ttyS10",115200,1);
if(fd < 0)
{
perror("serial init err:");
return -1;
}
ret = serial_send(fd,str,22);
printf("send %d bytes!\n",ret);
serial_read(fd,buf,100,5000);
printf("the buf is :%s\n",buf);
close(fd);
return 0;
}