小胖熊酷数码GPS论坛 www.sosaw.com

 找回密码
 注册register

扫一扫,访问微社区

查看: 37262|回复: 20

[地图文件修改教程和工具] 关于端口、波特率的一种修改方法

[复制链接]
发表于 2010-2-6 13:33 | 显示全部楼层 |阅读模式
分享到:
本文仅献给像我这样初次接触GPS的菜鸟。

用IDA打开待修改的程序(EXE or DLL)。

1、修改串口号:
1)、首先查找特征函数 SetupComm
   该函数初始化一个指定的通信设备的通信参数。如设置串行通信端口的输入和输出缓冲区的大小。
   其中 R0 是一个已打开的串口的句柄,这样,我们可以通过R0来查找打开串口的函数,一般是CreateFileW。

2)、确定COMx 中的x
   找到 CreateFileW 函数后,其CreateFileW函数的R0就指向待打开的文件名(这里是 COMx名,如COM1、COM2...)。再通过R0查找到格式化字符串函数(即将 "COM%d:"中的 %d 改为具体的数值,如1、2...)
的函数,一般是形如 swprintf 这样的函数。
   swprintf函数中的R0指向一个缓冲区,字符串格式化后就放在这里,而R1则指向待格式化的字符串,重点:R2中的数值就是COMx中的x了!
   这时你可以修改它为你需要的数值。如 mov R2,#1 (十六进:01 20 A0 E3,这个机器码后面讲)

2、修改波特率:
1)、首先查找特征函数 SetCommState
  该函数将DCB结构中的内容写入串口设置,以便修改和设置串口工作状态的参数,如波特率、数据位、奇偶校验位等通信参数。

   其 DCB 结构如下:
DCB STRUCT
 DCBlength     DWORD        本结构的长度 = 1Ch
 BaudRate      DWORD        注意这里,波特率!
 fbits         BITRECORD      <>
 wReserved     WORD      
 XonLim        WORD          
 XoffLim       WORD        
 ByteSize      BYTE        
 Parity        BYTE          
 StopBits      BYTE        
 XonChar       BYTE        
 XoffChar      BYTE        
 ErrorChar     BYTE      
 EofChar       BYTE        
 EvtChar       BYTE        
 wReserved1    WORD      
DCB ENDS

  SetCommState 函数的前面会先调用 GetCommState 以获得当前系统的DCB结构,再按需要赋值给DCB的成员,如波特率、奇偶校验、数据位、停止位 等。
   函数 SetCommState 中的参数 R1 指向 DCB 结构,R0 是一个已打开的串口的句柄(就是前面打开的那个串口)。
   重点:注意R1的值(是一个堆栈地址),看上面的结构图,其R1+4(一个DWORD)的位置就是波特率了,这样你就可以查出是谁、在哪里给这个R1+4的地址赋值的了,从而将其改为你所需要的数值。
2)、代码修改:
  假如你要将波特率改为 4800,并且由 R2转储到上面所说的R1+4处,应先给R2赋值:MOV  R2, #0x12C0, 其代码为:十六进的 4B 2D A0 E3,其中后面的 A0 E3 是操作码,不用管它。
  那么4B 2D 是怎么来的呢,为什么不是 C0 12 呢?在CE中使用的精简代码,其一条语句都是固定的一个DWORD(即4字节),那么一个DWORD的立即数是没有办法赋给寄存器R的,否则再加上操作码就超过4字节了。
   你可以简单的这么计算:第二字节的高4位代表寄存器R的的编号,如这里为w=2,它的低4位为倍率y,第一字节为基数,我们先记为:xx wy, xx * y = 你要的波特率。 y的取值如下:
7 = 40000h   262144 不会有这么高的波特率!
8 = 10000h   65536 不会有这么高的波特率!
9 = 4000h     16384 不会有这么高的波特率!
A = 1000h     4096
B = 400h      1024
C = 100h      256
D = 40h       64
E = 10h       16
F = 4h         4
0 = 1h        1

例子:假设你要的波特率为 4800,则:
4800/4 = 1200,大于255 不行,此数值必须小于 255!
4800/16 = 300,也不行
4800/64 = 75,可以, (75 = 十六进的 4B,而64 对应的y值= D )
4800/256 = 18.75,不行,商必须是整数!
这样,我们就得到了 xx wy = 4B 2D,加上操作码就是:4B 2D A0 E3(ARM: mov R2,#0x12C0) 。

下面是几个常用波特率的数值:
4800[4B WD A0 E3]
9600[96 WD A0 E3]
14400[E1 WD A0 E3]
19200[4B WC A0 E3]
38400[96 WC A0 E3]
57600[E1 WC A0 E3
其中的W应根据你程序中要使用第几号寄存器进行相应的修改,如R1,则W =1,R2,W=2...

以上的计算,我说的是简单的计算,当然编码器可不是这样计算的。
当然,程序是千变万化的,我在这里只是提供一种方法,具体的还要依据你的程序而定。

修改代码要用 010Editor 或 Uedit,不在本文的讨论范围内。
发表于 2010-2-6 16:53 | 显示全部楼层
不懂帮顶,这个可能程序员才懂!
发表于 2010-2-6 14:17 | 显示全部楼层
学习了!
发表于 2010-2-6 17:18 | 显示全部楼层
晕了
 楼主| 发表于 2010-2-6 19:26 | 显示全部楼层
楼主端口COM的8,7 各如何表达AO是几谢谢!!
-- by 会员 jinnc (2/6/2010 6:46:50 PM)

没有固定的表达式
这要看您的程序中形如 swprintf 这样的函数的地方,在调用 swprintf函数时,R0指向一个缓冲区,字符串格式化后就放在这里,而R1则指向待格式化的字符串,如COM%d:(Unicode),而R2中的数值就是COMx中的x了!
   您可以在程序调用 swprintf函数之前,给R2赋值, 如mov R2,#7 (十六进:07 20 A0 E3,这个A0是A零,不是OK的O)
发表于 2010-2-6 18:46 | 显示全部楼层
楼主端口COM的8,7 各如何表达AO是几谢谢!!
发表于 2010-2-6 17:08 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2010-2-6 13:37 | 显示全部楼层
沙发
发表于 2014-9-6 18:34 | 显示全部楼层
不懂帮顶,这个可能程序员才懂
回复 支持 1 反对 0

使用道具 举报

发表于 2010-7-14 15:37 | 显示全部楼层
帮顶下,顶坏勿怪
回复 支持 1 反对 0

使用道具 举报

发表于 2010-2-6 14:26 | 显示全部楼层
能看懂你这篇文章的 其实已经不是初级菜鸟了,所以  楼主发的东西 还是得高级的菜鸟才有用
发表于 2010-2-6 17:21 | 显示全部楼层
是老鸟的楼主......
发表于 2010-2-6 17:23 | 显示全部楼层
技术贴!
发表于 2010-2-6 18:34 | 显示全部楼层
看不懂,帮顶
发表于 2010-7-14 14:29 | 显示全部楼层
我来UP下
发表于 2010-7-14 14:34 | 显示全部楼层
董事长顶的都是沉底的精品啊。
发表于 2010-7-14 14:46 | 显示全部楼层
加分感谢科普帖~
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册register

本版积分规则

百度SITEMAP|小黑屋|Archiver|手机版|小胖熊酷数码GPS论坛 www.sosaw.com ( 沪ICP备16050520号-1 )|网站地图 

GMT+8, 2019-6-24 21:23 , Processed in 0.231145 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表