TQ2440(ARM)和SIM300(GPRS串口通信模块)
最近,我在做串口通信方面遇到了很大的麻烦。现在写一篇文章作为总结。
先介绍一下我的环境,ARM板是TQ2440的,内核是linux-2.6.30.4,GPRS模块用的是SIM300,完全包装PPP拨号和TCP/IP协议,是一块GPRS DTU。
第一个问题是,ARM板可以和PC机通信,GPRS模块也可以和解PC机通信,但使用ARM板和PC机器无法通信,可以写入串口,但根本看不到串口。说明ARM板和GPRS模块完全不通。作为一个硬件新手,在使用论坛和各种搜索后,我发现很多人都有这个问题,这可能是由于线路问题,然后硬头皮TQ2440(ARM板)和SIM300(GPRS看了看模块)串口电路的原理图,果然。没有截图,直接写结果。
PC:2脚RXD,3脚TXD (公头)
TQ2440:2脚TXD,3脚RXD (公头)
SIM300:2脚TXD,3脚RXD (母头)
这样就可以解释为什么不能通信,我用的串口线都是直通的,PC和TQ2440以及PC和SIM300可以通信,但当TQ2440和SIM300通信时,TXD对的是TXD,而RXD对的是TXD,当然,方法是使用交叉串口线。这个知识在最后的附录中(附录1)。
第二个问题是,TQ2440实际上有一些通用的异步手法装置(UART)有三个,也就是说,有三个串口,但只有一个串口RS232被引出,串口2,3都是TTL电平作为扩展,更假的是,该串口已经在天嵌公司提供的核心和文件系统中编译成调试串口,即作为控制台。所以我想用5线和我的SIM300通信不能用。这里有三种方法,两种软件方法,一种硬件方法。先说两种软件方法。
方法1:修改内核,重新编译,将串口不作为调试,然后如果要调试,可以使用两种方法,一种是使用telnet,另一种是使用jlink。
Character devices —> Serial drivers —> S3C2410 serial port support [ ] Console on S3C2410 serial port
去掉那个,显然不适合我,因为我的网口到时候还有其他用途。
法二:重写串口驱动程序。天嵌提供的驱动程序是开源的。UART的进行串口切换驱动,但都是失败告终,目前也没有发现又成功的例子,所以只是理论上的方法。
第三种方法是硬件方法,简单粗暴,直接TQ2440的TTL串口电平转换成RS作为硬件菜鸟,232串口接口肯定不会自己买各种线和MAX然后用天嵌公司自己生产的扩展板接起来。网址是:http://detail.china.alibaba.com/buyer/offerdetail/987340147.html。
这里不得不吐槽一下,你特么的什么破玩意,搞个一个串口,其他的还得去买,而且这个串口又不是标准的RS232串口。最后,在附录(附录2)中粘贴我的测试代码。
附录1:
串口线也分为直通线和交叉线,通常用于延长PC与设备分别连接2、3、5,因为PC它通常是公头,而设备大多是母头,所以它们是通用的,可以用于延长或连接;交叉通常用于PC与PC对接,2对3,3对2,5对5,一般两端都是母头!
而CPU 采用和终端TTL 电平和正逻辑,TTL 电平用 5V 表示逻辑1,0V 表示逻辑0,它们和EIA电平和负逻辑不兼容,需要在接口电路中转换。EIA-RS-232C 标准没有定义连接器的物理特性。DB-25、DB-15 和DB-9 各种类型的连接器,PC 机的COM1和COM采用串行接口DB-9连接器。ELA-RS-232C 标准规定,当误码率小于4%时,允许导线长度为15m 。在实际应用中,当使用9600b /s、传输距离可达30m ~35m 。PC 机的COM1和COM采用两个串行接口DB-9连接器是公( 针) 头,提供异步通信 9 引脚功能。分别为:①脚 (DCD) 数据载波检测,②脚 (RXD)接收数据,③脚(TXD) 发送数据,④脚 (DTR) 数据终端准备,⑤脚 (SG) 信号地,⑥脚 (DSR) 准备好数据设备,⑦脚(RaS)请求发送,⑧脚 (CTS) 清除发送,⑨脚 (RI) 振铃指示。DB-9 公 ( 针 ) 头部排列顺序如下图所示,DB-9母座排列顺序如下右下,针 ( 座 ) 朝向自己。在连接器上标记数字。EIA-RS-232C 标准中 , 三个发送信号:TXD 、RTS 和DTR,每根线的典型输出电流是± 8mA/±12V 。通常由 RTS 和 DTR 供电时,可提供约192mW 功率。
看开发板上的串口是标准串口还是非标准串口,根本要看原理图是怎么连接的!
附录二:
1 |
</pre> |
2 |
#include <stdio.h> |
3 |
|
4 |
#include <string.h> |
5 |
|
6 |
#include <sys/types.h> |
7 |
|
8 |
#include <error.h> |
9 |
|
10 |
#include <sys/stat.h> |
11 |
|
12 |
#include <fcntl.h> |
13 |
|
14 |
#include <termios.h> |
15 |
|
16 |
#include <stdlib.h> |
17 |
|
18 |
int fd; |
19 |
|
20 |
/* |
21 |
|
22 |
* 打开串口1 |
23 |
|
24 |
*/ |
25 |
|
26 |
int open_serial() |
27 |
|
28 |
{ |
29 |
|
30 |
//O_RDWR:以读写的方式打开设备 |
31 |
|
32 |
//O_NOCTTY:如果欲打开的文件为终端设备时,则不会将该终端当成当前进程控制终端 |
33 |
|
34 |
//O_NDELAY:以不可阻断的方式打开文件,即无论有无数据读取或等待,都会立即返回进程之中 |
35 |
|
36 |
//fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); //PC机测试 |
37 |
|
38 |
fd = open( "/dev/tq2440_serial1" , O_RDWR | O_NOCTTY | O_NDELAY); //tq2440 Linux测试 |
39 |
|
40 |
printf ( "\nfd = %d\n\n" , fd); |
41 |
|
42 |
if (fd < 0) //打开失败 |
43 |
|
44 |
{ |
45 |
|
46 |
return -1; |
47 |
|
48 |
} |
49 |
|
50 |
//恢复串口为阻塞状态 |
51 |
|
52 |
if (fcntl(fd, F_SETFL, 0) < 0) //F_SETFL:改变open设置的标志 |
53 |
|
54 |
{ |
55 |
|
56 |
close(fd); |
57 |
|
58 |
return -2; |
59 |
|
60 |
} |
61 |
|
62 |
//测试是否为终端设备 |
63 |
|
64 |
if (0 == isatty(fd)) //isatty:检查设备类型 |
65 |
|
66 |
{ |
67 |
|
68 |
close(fd); |
69 |
|
70 |
return -3; |
71 |
|
72 |
} |
73 |
|
74 |
return fd; |
75 |
|
76 |
} |
77 |
|
78 |
/* |
79 |
|
80 |
* 设置串口,共9步 |
81 |
|
82 |
* 数据位:8 |
83 |
|
84 |
* 校验位:无 |
85 |
|
86 |
* 波特率:115200 |
87 |
|
88 |
* 停止位:1 |
89 |
|
90 |
*/ |
91 |
|
92 |
int set_serial() |
93 |
|
94 |
{ |
95 |
|
96 |
struct termios newtio, oldtio; |
97 |
|
98 |
//1、保存原有串口配置 |
99 |
|
100 |
if (tcgetattr(fd, &oldtio) != 0) |
101 |
|
102 |
{ |
103 |
|
104 |
return -1; |
105 |
|
106 |
} |
107 |
|
108 |
//2、激活本地连接和接受使能 |
109 |
|
110 |
newtio=oldtio; |
111 |
|
112 |
newtio.c_cflag |= CLOCAL | CREAD; |
113 |
|
114 |
//3、设置字符大小 |
115 |
|
116 |
newtio.c_cflag &= ~CSIZE; //除去数据位中的位掩码 |
117 |
|
118 |
newtio.c_cflag |= CS8; //设置数据位 |
119 |
|
120 |
//4、设置奇偶校验位:无奇偶校验位 |
121 |
|
122 |
newtio.c_cflag &= ~PARENB; //激活校验位使能标志 |
123 |
|
124 |
//5、设置波特率 |
125 |
|
126 |
cfsetispeed(&newtio, B115200); |
127 |
|
128 |
cfsetospeed(&newtio, B115200); |
129 |
|
130 |
//6、设置停止位:1 |
131 |
|
132 |
newtio.c_cflag &= ~CSTOPB; |
133 |
|
134 |
//7、设置等待时间和最小接收字符 |
135 |
|
136 |
newtio.c_cc[VTIME] = 0; |
137 |
|
138 |
newtio.c_cc[VMIN] = 0; |
139 |
|
140 |
//8、处理要写入的引用对象 |
141 |
|
142 |
tcflush(fd, TCIFLUSH); //处理未接收字符串,TCIFLUSH:刷新收到的数据但不读 |
143 |
|
144 |
//9、激活新配置 |
145 |
|
146 |
if (tcsetattr(fd, TCSANOW, &newtio) != 0) //TCSANOW:改变的配置立即生效 |
147 |
|
148 |
{ |
149 |
|
150 |
return -2; |
151 |
|
152 |
} |
153 |
|
154 |
return 0; |
155 |
|
156 |
} |
157 |
|
158 |
int main() |
159 |
|
160 |
{ |
161 |
|
162 |
char cmd[] = "ATD 18970952060;\r" ; |
163 |
|
164 |
open_serial(); |
165 |
|
166 |
set_serial(); |
167 |
|
168 |
printf ( "write: %d\n" , write(fd, cmd, sizeof (cmd))); |
169 |
|
170 |
sleep(2); |
171 |
|
172 |
printf ( "read: %d\n" , read(fd, cmd, sizeof (cmd))); |
173 |
|
174 |
return 0; |
175 |
|
176 |
} |
177 |
|
178 |
返回是: |
179 |
|
180 |
fd=3 |
181 |
|
182 |
write:18 |
183 |
|
184 |
read:18 |