开发环境:
开发环境如下图所示:
开发PC:开发PC上运行超级终端,编写、编译串口程序
Tiny6410:运行串口程序,其中/dev/ttySAC0通过串口线与开发PC相连接,/dev/ttySAC3通过串口线与测试PC相连接
测试PC:测试PC上运行串口调试工具,进行串口数据的收发
程序功能描述:Tiny6410通过/dev/ttySAC3串口与测试PC进行串口数据的收发。这个程序是在友善之臂提供的串口应用程序的基础上精简来的。原来的程序看起来有些复杂,初学者读起来有一定难度。经过精简之后,只保留了串口收发数据的关键部分。
源代码
-
/*==========================================================================
-
*Name: uart_S3C6410.c
-
*Desc: 友善之臂开发板串口收发程序,根据友善之臂提供的串口程序精简而来
-
* 在超级终端输入要发送的字符,通过串口发送;串口接收的数据由超级
-
* 终端显示出来。交叉编译后,下载到开发板,执行./uart_S3C6410
-
*Parameter:
-
*Return:
-
*Author: yoyoba(stuyou@126.com)
-
*Date: 2016-11-03
-
*Modify: 2016-12-07
-
*=========================================================================*/
-
-
# include <stdio.h>
-
# include <stdlib.h>
-
# include <termio.h>
-
# include <unistd.h>
-
# include <fcntl.h>
-
# include <getopt.h>
-
# include <time.h>
-
# include <errno.h>
-
# include <string.h>
-
-
//错误消息提示函数
-
static void Error(const char *Msg)
-
{
-
fprintf (stderr, "%s\n", Msg);
-
fprintf (stderr, "strerror() is %s\n", strerror(errno));
-
exit(1);
-
}
-
-
//警告消息提示函数
-
static void Warning(const char *Msg)
-
{
-
fprintf (stderr, "Warning: %s\n", Msg);
-
}
-
-
//使用select监视FD是否可写
-
static inline void WaitFdWriteable(int Fd)
-
{
-
fd_set WriteSetFD;
-
FD_ZERO(&WriteSetFD);
-
FD_SET(Fd, &WriteSetFD);
-
if (select(Fd + 1, NULL, &WriteSetFD, NULL, NULL) < 0) {
-
Error(strerror(errno));
-
}
-
}
-
-
int main()
-
{
-
int UART_fd, tty_fd;
-
struct termios TtyAttr;
-
struct termios BackupTtyAttr;
-
-
UART_fd = open("/dev/ttySAC3", O_RDWR, 0);//打开ttySAC3串口
-
if (UART_fd < 0)
-
Error("Unable to open device");
-
if (fcntl(UART_fd, F_SETFL, O_NONBLOCK) < 0)//设置串口为非阻塞
-
Error("Unable set to NONBLOCK mode");
-
-
memset(&TtyAttr, 0, sizeof(struct termios));//清空ttyattr
-
//配置串口:
-
TtyAttr.c_iflag = IGNPAR; //忽略校验
-
TtyAttr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL;//115200波特率,数据位8,启用接收
-
TtyAttr.c_cc[VMIN] = 1; //最小可读取字符数
-
if (tcsetattr(UART_fd, TCSANOW, &TtyAttr) < 0)//配置串口
-
Warning("Unable to set comm port");
-
-
tty_fd = open("/dev/tty", O_RDWR | O_NDELAY, 0); //打开终端/dev/tty,当前shell终端
-
if (tty_fd < 0)
-
Error("Unable to open tty");
-
TtyAttr.c_cflag = B115200 | HUPCL | CS8 | CREAD | CLOCAL;//和开发板超级终端属性的配置一致,否则会有问题
-
if (tcgetattr(tty_fd, &BackupTtyAttr) < 0)//把终端属性保存在BackupTtyAttr,程序退出时恢复终端使用
-
Error("Unable to get tty");
-
if (tcsetattr(tty_fd, TCSANOW, &TtyAttr) < 0)//设置终端属性
-
Error("Unable to set tty");
-
-
//启动循环,串口接收和发送数据
-
while(1){
-
unsigned char buf = 0;
-
fd_set ReadSetFD;
-
-
//select监控串口和终端是否可读
-
FD_ZERO(&ReadSetFD);
-
FD_SET(UART_fd, &ReadSetFD);
-
FD_SET( tty_fd, &ReadSetFD);
-
#define max(x,y) ( ((x) >= (y)) ? (x) : (y) )
-
if (select(max(UART_fd, tty_fd) + 1, &ReadSetFD, NULL, NULL, NULL) < 0) {
-
Error(strerror(errno));
-
}
-
#undef max
-
-
//如果串口可读
-
if (FD_ISSET(UART_fd, &ReadSetFD)){
-
while (read(UART_fd, &buf, 1) == 1) {
-
WaitFdWriteable(tty_fd);//等待终端可写
-
if (write(tty_fd, &buf, 1) < 0) {//把从串口读取的字符输出到终端显示
-
Error(strerror(errno));
-
}
-
}
-
}
-
-
//如果终端可读,在终端中输入发送的数据
-
if (FD_ISSET(tty_fd, &ReadSetFD)) {
-
while (read(tty_fd, &buf, 1) == 1) {//读取终端中输入的字符
-
static int EscKeyCount = 0;//统计按下ESC键的次数,如果连续按下三次ESC键,则退出程序
-
WaitFdWriteable(UART_fd);//如果串口可写,就通过串口发送
-
if (write(UART_fd, &buf, 1) < 0) {
-
Error(strerror(errno));
-
}
-
if(buf != '\x1b')//如果输入的不是ESC键,则在超级终端显示输入的字符
-
fwrite((char*)&buf, 1, 1, stderr);//如果不执行这句,超级终端看不到输入的字符
-
-
if (buf == '\x1b') {
-
EscKeyCount ++;
-
if (EscKeyCount >= 3)
-
goto ExitLabel;
-
// 跳出到退出label
-
} else
-
EscKeyCount = 0;
-
}
-
}
-
}
-
ExitLabel:
-
if (tcsetattr(tty_fd, TCSANOW, &BackupTtyAttr) < 0)//退出程序之前,恢复超级终端的配置
-
Error("Unable to set tty");
-
-
return 0;
-
}
编译
在开发PC上对串口程序进行交叉编译:arm-linux-gcc -o uart_S3C6410 uart_S3C6410.c
运行测试
把开发PC上编译好的uart_S3C6410下载到开发板,并添加执行权限:chmod +x uart_S3C6410,
执行:./uart_S3C6410
1.接收测试:在测试PC的串口调试工具中,发送数据,在开发PC的超级终端中可以看到接收的数据;
2.发送测试:在开发PC的超级终端中输入要发送的数据,在测试PC的串口调试工具中看到接收的数据
3.退出程序:在开发PC超级终端中连续输入三个“ESC”键,则退出程序。
阅读(1246) | 评论(0) | 转发(0) |