此代码尝试自动检测用户的波特率,并初始化8051的内置UART -。更具体而言,采取这些步骤:- 如果代码是正确的波特率组装的,跳到第5步。
- 如果我们先前检测到的波特率,跳到第5步。
- 等待用户按下回车键(又名回车)及数位到达需要多长时间。
- 计算用户的波特率所需的定时器重载值。
- 商店的结果,使我们可以(希望)跳过检测波特率,如果这个代码又被称为。
- 各种特殊功能寄存器进行初始化。
它是如何工作当用户按下回车键,他们的终端仿真程序发送13字节,这将发送如下所示: 0 1 0 1 1 0 0 0 0 1 | | | |启动位---- + - LSB MSB - +----停止位[size=-2]注:有一天,我就画了这个漂亮的图片,以取代cheezy ASCII艺术。代码读取 P3.0,这是 RXD引脚,并等待,使其成为低,这被假定为起始位 。当它再次变高, timer1是在16位模式下启动 。等待上面显示的剩余转换的代码。在停止位的开始时,Timer1停止。如果一切顺利,在Timer1的16位值,应说明有多少个CPU周期,而代码等8 个数据位。 8051使用Timer1的生成其内置的UART时钟。虽然可以在任何模式中使用定时器,extreemly缓慢波特率需要是最有意义的,除非使用8位自动重装。此代码仅在8位自动重装模式下的Timer1配置。虽然这段代码使得配置内置的UART容易,应该注意到,8051的UART需要定时器产生波特率时钟,并不能在不影响UART的改变。 内置的UART需要16个时钟周期(由Timer1),每个位 。由于代码定时所有8位,将自动重载模式的定时器初始化需要的值是CPU周期数除以128计算。必须小心避免四舍五入的错误,将产生一个不准确的波特率值的。这种错误出现在PAULMON1。的代码提交,修复这个bug是相同的波特率自动检测代码 PAULMON2 。 可用的波特率因为8051的UART需要TIMER1,这是由晶体(12分),波特率8051的硬件可以产生时钟:波特率=水晶/(12 * 16 * N) 其中“N”是一个从1到255之间的整数。此代码将选择可用的波特率,这是最接近收到的。通常情况下,约2.5%的错误仍然会管理沟通无麻烦,但大大超出,将有问题的,如果它工作在所有。许多晶体可用标准波特率的确切倍数。通常情况下,这些晶体提供更快的波特率,不是简单地切换到更快的晶体。例如,一个4 MHz晶振提供1200波特。切换到8 MHz的最大升幅为2400波特,但切换到3.6864 MHz的晶振将允许19200波特! 下面是一些标准的晶体和最高标准波特率应该与他们的总结:
水晶(兆赫) | 最大波特率 | 错误 | 1.00 | 300 | 2.12% | 1.8432 | 9600 | 0.00% | 2.00 | 300 | 0.79% | 2.4576 | 300 | 0.78% | 3.00 | 1200 | 0.16% | 3.579545 | 300 | 0.23% | 3.6864 | 19200 | 0.00% | 4.00 | 1200 | 2.12% | 4.194304 | 2400 | 1.14% | 4.91520 | 1200 | 1.59% | 5.00 | 2400 | 1.36% | 5.0688 | 2400 | 0.00% | 6.00 | 2400 | 0.16% | 6.144 | 1200 | 1.23% | 7.3728 | 38400 | 0.00% | 8.00 | 2400 | 2.12% | 10.00 | 4800 | 1.36% | 10.738635 | 2400 | 1.32% | 11.00 | 57600 | 0.54% | 11.0592 | 57600 | 0.00% | 12.00 | 4800 | 0.16% | 12.288 | 2400 | 1.23% | 14.31818 | 2400 | 0.23% | 14.7456 | 38400 | 0.00% | 15.00 | 38400 | 1.73% | 16.00 | 4800 | 2.12% | 18.432 | 19200 | 0.00% | 20.00 | 9600 | 1.36% | 22.1184 | 115200 | 0.00% | 24.00 | 9600 | 0.16% | 24.576 | 4800 | 1.23% | 25.00 | 4800 | 0.47% | 28.00 | 9600 | 1.27% | 32.00 | 9600 | 2.12% | [size=-1]一个位的Perl代码生成此表 ...波特率(如发展与PAULMON)用晶体,它提供了一个更快的波特率可以是一个很大的改进,即使是较低的频率,速度是有限的应用。
- ; To set the baud rate, use this formula or set to 0 for auto detection
- ; baud_const = 256 - (crystal / (12 * 16 * baud))
- .equ baud_const, 0 ;automatic baud rate detection
- ;.equ baud_const, 255 ;57600 baud w/ 11.0592 MHz
- ;.equ baud_const, 253 ;19200 baud w/ 11.0592 MHz
- ;.equ baud_const, 252 ;19200 baud w/ 14.7456 MHz
- ;.equ baud_const, 243 ;4808 baud w/ 12 MHz
- ;to do automatic baud rate detection, we assume the user will
- ;press the carriage return, which will cause this bit pattern
- ;to appear on port 3 pin 0 (CR = ascii code 13, assume 8N1 format)
- ;
- ; 0 1 0 1 1 0 0 0 0 1
- ; | | | |
- ; start bit----+ +--l*** m***--+ +----stop bit
- ;
- ;we'll start timer #1 in 16 bit mode at the transition between the
- ;start bit and the LSB and stop it between the MBS and stop bit.
- ;That will give approx the number of cpu cycles for 8 bits. Divide
- ;by 8 for one bit and by 16 since the built-in UART takes 16 timer
- ;overflows for each bit. We need to be careful about roundoff during
- ;division and the result has to be inverted since timer #1 counts up. Of
- ;course, timer #1 gets used in 8-bit auto reload mode for generating the
- ;built-in UART's baud rate once we know what the reload value should be.
- autobaud:
- mov tmod, #0x11 ;get timer #1 ready for action (16 bit mode)
- mov tcon, #0x00
- clr a
- mov th1, a
- mov tl1, a
- mov a, #baud_const ;skip if user supplied baud rate constant
- jnz autoend
- mov a, 0x7B ;is there a value from a previous boot?
- xrl 0x7A, #01010101b
- xrl 0x79, #11001100b
- xrl 0x78, #00011101b
- cjne a, 0x7A, autob2
- cjne a, 0x79, autob2
- cjne a, 0x78, autob2
- sjmp autoend
- autob2: *** p3.0, * ;wait for start bit
- *** p3.0, autob2
- *** p3.0, autob2 ; check it a few more times to make
- *** p3.0, autob2 ; sure we don't trigger on some noise
- *** p3.0, autob2
- jnb p3.0, * ;wait for bit #0 to begin
- setb tr1 ;and now we're timing it
- *** p3.0, * ;wait for bit #1 to begin
- jnb p3.0, * ;wait for bit #2 to begin
- *** p3.0, * ;wait for bit #4 to begin
- jnb p3.0, * ;wait for stop bit to begin
- clr tr1 ;stop timing
- mov a, tl1
- mov c, acc.6 ;save bit 6 for rounding up if necessary
- mov f0, c
- mov c, acc.7 ;grab bit 7... it's the l*** we want
- mov a, th1
- rlc a ;do the div by 128
- mov c, f0
- addc a, #0 ;round off if necessary
- cpl a ;invert since timer #1 will count up
- inc a ;now acc has the correct reload value (I hope)
- autoend:mov 0x7B, a
- mov 0x7A, a ;store the baud rate for next wARM boot.
- mov 0x79, a
- mov 0x78, a
- xrl 0x7A, #01010101b
- xrl 0x79, #11001100b
- xrl 0x78, #00011101b
- mov th1, a
- mov tl1, a
- mov tmod, #0x21 ;set timer #1 for 8 bit auto-reload
- mov pcon, #0x80 ;configure built-in uart
- mov scon, #0x52
- setb tr1 ;start the baud rate timer
- mov r0, #0
- djnz r0, *
- djnz r0, *
- ret
复制代码
1
|
|
|
|