学习日志(十四)
基于Linux的串口开发
基于原生wiringPi库的串口开发
(一)直接用wiringPi库的范例
复制范例代码到当前文件夹下:
cp ../wringPiFromWindow/wiringOP-master/examples/serialTest.c .
感觉代码给的很乱:
这里我用的是串口5:ttyS5。
因此14行代码改成:
if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0)
测试现象:
(二)修改范例实现串口1
功能描述:可以双方互发。
直接上代码:
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include <wiringPi.h>
6 #include <wiringSerial.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9 int fd ;
10
11 void * send()
12 {
13 char *sendbuf = NULL;
14 sendbuf = (char *)malloc(32*sizeof(char));
15 while(1){
16 scanf("%s",sendbuf);
17 while(*sendbuf){
18 serialPutchar (fd, *sendbuf++) ;
19 }
20 }
21 }
22 int main ()
23 {
24
25 pthread_t sendt;
26 if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0)
27 {
28 fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
29 return 1 ;
30 }
31
32 if (wiringPiSetup () == -1)
33 {
34 fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
35 return 1 ;
36 }
37 pthread_create(&sendt,NULL,send,NULL);
38 while(1){
39 while (serialDataAvail (fd))
40 {
41 printf ("%c", serialGetchar(fd)) ;
42 fflush (stdout) ;
43 }
44 }
45
46 printf ("\n") ;
47 return 0 ;
48 }
同样串口要改成ttyS5
测试现象:
①:
②:
③:
(三)修改范例实现串口2
基于串口1 为 收发 都创建线程执行
功能描述:可以双方互发。
上代码:
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include <wiringPi.h>
6 #include <wiringSerial.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9 #include <unistd.h>
10
11 int fd ;
12
13 void * send()
14 {
15 char *sendbuf = NULL;
16 sendbuf = (char *)malloc(32*sizeof(char));
17 while(1){
18 scanf("%s",sendbuf);
19 while(*sendbuf){
20 serialPutchar (fd, *sendbuf++) ;
21 }
22 }
23 }
24 void* rev()
25 {
26 while(1){
27 while (serialDataAvail (fd))
28 {
29 printf ("%c", serialGetchar(fd)) ;
30 fflush (stdout) ;
31 }
32 }
33 }
34 int main ()
35 {
36
37 pthread_t sendt;
38 pthread_t revt;
39 if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0)
40 {
41 fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
42 return 1 ;
43 }
44
45 if (wiringPiSetup () == -1)
46 {
47 fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
48 return 1 ;
49 }
50 pthread_create(&sendt,NULL,send,NULL);
51 pthread_create(&revt,NULL,rev,NULL);
52 while(1){sleep(10);}
53 printf ("\n") ;
54 return 0 ;
55 }
测试现象:
①:
②:
③:
④:
自己基于C库的串口开发
代码:
uartTool.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <termios.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <sys/ioctl.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12
13 int serialOpen (const char *device, const int baud)
14 {
15 struct termios options ;
16 speed_t myBaud ;
17 int status, fd ;
18
19 switch (baud)
20 {
21 case 9600: myBaud = B9600 ; break ;
22 case 115200: myBaud = B115200 ; break ;
23 }
24 if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
25 return -1 ;
26
27 fcntl (fd, F_SETFL, O_RDWR) ;
28 tcgetattr (fd, &options) ;
29
30 cfmakeraw (&options) ;
31 cfsetispeed (&options, myBaud) ;
32 cfsetospeed (&options, myBaud) ;
33
34 options.c_cflag |= (CLOCAL | CREAD) ;
35 options.c_cflag &= ~PARENB ;
36 options.c_cflag &= ~CSTOPB ;
37 options.c_cflag &= ~CSIZE ;
38 options.c_cflag |= CS8 ;
39 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
40 options.c_oflag &= ~OPOST ;
41
42 options.c_cc [VMIN] = 0 ;
43 options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
44
45 tcsetattr (fd, TCSANOW, &options) ;
46
47 ioctl (fd, TIOCMGET, &status);
48
49 status |= TIOCM_DTR ;
50 status |= TIOCM_RTS ;
51
52 ioctl (fd, TIOCMSET, &status);
53
54 usleep (10000) ; // 10mS
55
56 return fd ;
57
58 }
uartTool.h
1 #ifndef _UART_H
2 #define _UART_H
3
4 int serialOpen (const char *device, const int baud);
5 void myserialSendString (const int fd, const char *s);
6 int myserialReadString(int fd,char *buffer);
7
8
9 #endif
uart.c(main.c)
1 #include "uartTool.h"
2 #include "pthread.h"
3 #include "string.h"
4 #include "unistd.h"
5 #include "stdlib.h"
6 #include "stdio.h"
7
8 int fd;
9
10 void* sendSerial()
11 {
12 char *sendbuf = NULL;
13 sendbuf = (char *)malloc(32*sizeof(char));
14 while(1){
15 memset(sendbuf,'\0',32);
16 scanf("%s",sendbuf);
17 myserialSendString(fd,sendbuf);
18 }
19 }
20 void* readSerial()
21 {
22 char readbuf[32];
23 int n_read =0;
24 while(1){
25 memset(readbuf,'\0',32);
26 n_read = myserialReadString(fd,readbuf);
27 if(n_read!=0){
28 printf("GET->%s\n",readbuf);
29 }
30 }
31 }
32 int main(int argc,char **argv)
33 {
34 char deviceName[32];
35 pthread_t sendt;
36 pthread_t readt;
37
38 if(argc<2){
39 printf("uage:%s /dev/ttyS?\n",argv[0]);
40 return -1;
41 }
42
43 strcpy(deviceName,argv[1]);
44 if((fd = serialOpen(deviceName,115200)) == -1){
45 printf("open %s error \n",deviceName);
46 return -1;
47 }
48
49 pthread_create(&sendt,NULL,sendSerial,NULL);
50 pthread_create(&readt,NULL,readSerial,NULL);
51 while(1){sleep(10);}
52
53 return 0;
54 }
编译的时候:
不需要在用我们的shell脚本了,因为是基于C库的,直接ggc编译C文件。
要注意的是:
所有的C文件必须全部编译,不仅仅是uart.c文件,包括调用的分层C文件uartTool.c。
gcc uart.c uartTool.c -lpthread
测试现象:
最后有个疑问:为什么不能这样编译:
gcc uart.c -lpthread -luartTool
。。。。。。