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通信的话就不能用。这里有三个方法,两个软件的方法,一个硬件的方法。先说那两个软件方法。
法一:修改内核,并重新编译,把串口一不当做调试用,然后如果要调试时可以用两种方法,一个就是用telnet,另一个就是使用jlink。
Character devices —>
Serial drivers —>
S3C2410 serial port support
[ ] Console on S3C2410 serial port
把那个去掉就可以,这显然不适合我,因为我的网口到时候还是有其他用处。
法二:重新写串口的驱动程序,天嵌提供的驱动程序是开源的,我曾经试着尝试UART的进行串口切换驱动,但都是失败告终,目前也没有发现又成功的例子,所以只是理论上的方法。
第三个方法就是硬件方法,简单而粗暴,直接把TQ2440的TTL串口电平转换成RS232的串口接口,作为硬件菜鸟,是肯定不会自己买各种线和MAX232然后去接起来,使用的是天嵌公司自己生产的扩展板子。网址是:http://detail.china.alibaba.com/buyer/offerdetail/987340147.html。
这里不得不吐槽一下,你特么的什么破玩意,搞个一个串口,其他的还得去买,而且这个串口又不是标准的RS232串口。最后在附录(附录2)中再贴上我的测试代码。
附录1:
串口线也分直通和交叉,直通一般用于延长PC与设备,将2、3、5分别连接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和COM2串行接口采用DB-9连接器。ELA-RS-232C 标准规定,当误码率小于4%时,允许导线长度15m 。实际应用中,当使用9600b /s、普通双绞屏蔽线时,传输距离可达30m ~35m 。PC 机的COM1和COM2两个串行接口采用的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 功率。
看一个开发板上的串口是标准串口还是非标准串口,根本还是要看原理图是怎么连的!
附录二:
38 | fd = open( "/dev/tq2440_serial1" , O_RDWR | O_NOCTTY | O_NDELAY); |
40 | printf ( "\nfd = %d\n\n" , fd); |
52 | if (fcntl(fd, F_SETFL, 0) < 0) |
96 | struct termios newtio, oldtio; |
100 | if (tcgetattr(fd, &oldtio) != 0) |
112 | newtio.c_cflag |= CLOCAL | CREAD; |
116 | newtio.c_cflag &= ~CSIZE; |
118 | newtio.c_cflag |= CS8; |
122 | newtio.c_cflag &= ~PARENB; |
126 | cfsetispeed(&newtio, B115200); |
128 | cfsetospeed(&newtio, B115200); |
132 | newtio.c_cflag &= ~CSTOPB; |
136 | newtio.c_cc[VTIME] = 0; |
138 | newtio.c_cc[VMIN] = 0; |
142 | tcflush(fd, TCIFLUSH); |
146 | if (tcsetattr(fd, TCSANOW, &newtio) != 0) |
162 | char cmd[] = "ATD 18970952060;\r" ; |
168 | printf ( "write: %d\n" , write(fd, cmd, sizeof (cmd))); |
172 | printf ( "read: %d\n" , read(fd, cmd, sizeof (cmd))); |