Ultra High Speed Microcontroller Hardware Enhances Serial Port Capability
Abstract
This application note looks at the new serial port features found in the Dallas Semiconductor DS89C430 and DS89C450 ultra high-speed microcontrollers. The addition of a clock multiplier allows the user to benefit by selecting a crystal at one-forth the original frequency to produce the same baud rates with reduced EMI.
Overview
In contrast to the original 8051 architecture that required a minimum of 12 clocks per instruction cycle, the Ultra High-Speed Microcontroller features an advanced 8051 core architecture capable of executing instructions in as little as one clock cycle. To complement the high performance core, new hardware features were integrated into the standard 8051 on-chip peripherals. Two of the new features, the clock multiplier and selectable high-speed clock to the timers, can directly affect baud rate generation for the serial ports. The purpose of this document is to explain the interaction between these two new features and serial-port baud-rate generation.
Serial Port Modes
The DS89C430 serial ports offer four basic modes of operation. Mode 0 allows half-duplex synchronous communication of 8-bit data using a baud clock derived from the system clock. Mode 1 allows fullduplex asynchronous communication of 8-bit data with a baud clock derived from Timer 1 or Timer 2. Mode 3 differs from Mode 1 by supporting 9-bit data transmission and reception. Mode 2 similarly provides 9-bit data communication, but instead derives its baud clock directly from the oscillator frequency. To support Mode 1, 2, and 3 asynchronous communication, a start bit always precedes the data and a stop bit always follows. Full details of each serial port mode can be found in the Ultra High Speed Microcontroller User's Guide.
Clock Multiplier
The Ultra High Speed Microcontroller incorporates an on-chip clock multiplier to give increased performance at a reduced external crystal clock frequency. The multiplier can be configured to generate either a doubled (2X) or quadrupled (4X) internal system clock, controlled by the 2X/4X special function register bit (PMR.3). Please note that the resultant 2X or 4X multiplied system clock still cannot exceed the maximum operating frequency specified in the data sheet. Full details pertaining to the multiplier can be found in the Ultra High Speed Microcontroller User's Guide.
Once the clock multiplier output has been selected (CD1:0 = 00b) as the internal system clock, certain serial port baud clocks derived from the system clock (no longer equal to the external oscillator frequency) will change. Figure 1 highlights the serial port clocks potentially affected when using the 2X or 4X multiplied system clock. The Serial Mode 0 baud rate will always differ, Serial Mode 2 baud rate will never differ, and the Serial Mode 1, 3 baud rates can differ, depending upon the timer used and/or timer input clock selection. Table 1, as per Figure 1, denotes which serial port modes are affected by use of the clock multiplier. Appendix A contains detailed equations for performing baud rate calculations when using the 2X or 4X clock multiplier mode.
SERIAL PORT MODE | BAUD CLOCK SOURCE | BAUD CLOCK DEPENDENT ON THE INTERNAL SYSTEM CLOCK (CLOCK MULTIPLIER SELECTION) |
Mode 0 (synchronous - 8 bits) |
System Clock/4 System Clock/12 |
YES |
Mode 1 (asynchronous - 10 bits) |
Timer 1 Timer 2 |
YES¹ NO² |
Mode 2 (asynchronous - 11 bits) |
Oscillator Clock/32 Oscillator Clock/64 |
NO |
Mode 3 (asynchronous - 11 bits) |
Timer 1 Timer 2 |
YES¹ NO² |
¹ Only when the divide by 4 or divide by 1 Timer 1 input clock is enabled (T1M = 1 or T1MH = 1). For compatibility with the original 8051, the default Timer 1 input clock (T1MH, T1M = 00b) is fixed to the oscillator clock divided by 12. ² Available for baud rate generation on Serial Port 0 only. |
Benefits: Faster Baud Rates, Reduced EMI
When using the clock multiplier, the application benefits can be great. An external crystal clock of onefourth the original frequency can be used to produce the same Serial Mode 0 and (Timer 1 generated) Mode 1, 3 baud rates as before, but with much reduced EMI. Alternatively, the same external crystal, when multiplied internally by 2X or 4X, can now generate baud clocks up to four times faster!
High-Speed Input Clock to Timers
In order for the on-chip timers to be most useful to the application, each should be able to track time at a rate equivalent to the minimum instruction cycle. For the original 8051 architecture, which executed instructions in 12 oscillator clocks, the timers were clocked at an oscillator frequency divided by 12 rate. When Dallas Semiconductor introduced its high-speed microcontroller with a reduced machine cycle of four oscillator clocks, a selectable oscillator frequency divided by 4 input-clock control was provided for each timer. When the clock multiplier function was added to the high-speed microcontroller family, the selectable divide by 4 timer-input clock was modified to become a function of the system clock, not the oscillator clock. Now, the Ultra High-Speed Microcontroller boasts single clock-cycle instruction execution. Once again, each of the on-chip timers has been upgraded with the integration of a selectable system clock divide by 1 input.
The T0MH, T1MH, and T2MH bits, contained in the CKMOD (96h) SFR, respectively enable the system clock divide by 1 input to Timer 0, Timer 1, and Timer 2. Enabling the high-speed system-clock input to the timer (TxMH = 1) will automatically override the system clock divided by 4 input (TxM = 1) setting. The new system clock divide by 1 timer input, like the system clock divide by 4 input, factors into baud rate generation when using Timer 1. Figure 2 highlights the serial port clocks potentially affected by selection of the high-speed clock input to Timer 1.
Benefits: Faster Baud Rates, Increased Baud Rate Resolution
Relative to serial port operation, the divide by 1 input-clock feature translates into two user benefits. First, provided with the same system clock frequency, baud rates four times faster can now be generated for Serial Modes 1 and 3 when using Timer 1. Secondly, clocking Timer 1 faster allows higher baud rate resolution, potentially reducing error associated with baud rates already used by the application, or bringing new baud rates within an acceptable error range for application use.
For example, suppose a user currently has a Dallas high-speed microcontroller application running at a 20MHz system clock frequency. The application uses one of the serial ports for RS232 communication with a PC, and requires that the baud rate mismatch between the two be < 3%. If using Timer 1 (in the 8-bit auto-reload mode) for baud rate generation, Table 2 below gives a sampling of the "good" baud rates for the Dallas high-speed microcontroller versus those for the new Ultra High Speed Microcontrolle. The unacceptable baud rates (those with mismatch > 3%) have been shaded in gray. Table 3 makes the same "good" baud rate comparison for a system clock frequency of 25MHz. As one can plainly see, enabling the high-speed Timer 1 input clock gives much finer baud rate resolution. Appendix A contains detailed equations for performing baud rate calculations when utilizing the system clock input to Timer 1 (T1MH = 1).
PC UART (8250/16450) | HIGH-SPEED MICROCONTROLLER (Timer 1 with T1M = 1 used for baud rate generation, SMOD_x = 1) | ULTRA HIGH-SPEED MICROCONTROLLER (Timer 1 with T1MH = 1 used for baud rate generation, SMOD_x = 1) | ||||
Reload | Baud Rate | Baud Rate (TH1) | % Error | Baud Rate (TH1) | Error | |
1 | 115200 | 104166 (FD) | -9.6 | 113636 (F5) | -1.4 | |
2 | 57600 | 62500 (FB) | 8.5 | 56818 (EA) | -1.4 | |
3 | 38400 | 39062 (F8) | 1.7 | 37879 (DF) | -1.4 | |
4 | 28800 | 28409 (F5) | -1.4 | 29070 (D5) | 0.9 | |
5 | 23040 | 22321 (F2) | -3.1 | 23148 (CA) | 0.5 | |
6 | 19200 | 19531 (F0) | 1.7 | 19231 (BF) | 0.2 | |
7 | 16457 | 16447 (ED) | -0.1 | 16447 (B4) | -0.1 | |
8 | 14400 | 14204 (EA) | -1.4 | 14368 (A9) | -0.2 | |
9 | 12800 | 13020 (E8) | 1.7 | 12755 (9E) | -0.4 | |
10 | 11520 | 11574 (E5) | 0.5 | 11574 (94) | 0.5 | |
11 | 10472 | 10417 (E2) | -0.5 | 10417 (88) | -0.5 | |
12 | 9600 | 9469 (DF) | -1.4 | 9615 (7E) | 0.2 |
PC UART (8250/16450) |
HIGH-SPEED MICROCONTROLLER (Timer 1 with T1M = 1 used for baud rate generation, SMOD_x = 1) |
ULTRA HIGH-SPEED MICROCONTROLLER (Timer 1 with T1MH = 1 used for baud rate generation, SMOD_x = 1) |
|||
Reload | Baud Rate | Baud Rate (TH1) | % Error | Baud Rate (TH1) | Error |
1 | 115200 | 130208 (FD) | 13.0 | 111607 (F2) | -3.1 |
2 | 57600 | 55803 (F9) | -3.1 | 57870 (E5) | 0.4 |
3 | 38400 | 39062 (F6) | 1.7 | 38110 (D7) | -0.8 |
4 | 28800 | 27901 (F2) | -3.1 | 28935 (CA) | 0.5 |
5 | 23040 | 22978 (EF) | -0.3 | 22978 (BC) | -0.3 |
6 | 19200 | 19531 (EC) | 1.7 | 19290 (AF) | 0.5 |
7 | 16457 | 16276 (E8) | -1.1 | 16447 (A1) | -0.1 |
8 | 14400 | 14467 (E5) | 0.5 | 14335 (93) | -0.5 |
9 | 12800 | 12600 (E1) | -1.6 | 12807 (86) | 0.1 |
10 | 11520 | 11489 (DE) | -0.3 | 11489 (78) | -0.3 |
11 | 10472 | 10557 (DB) | 0.8 | 10487 (6B) | 0.1 |
12 | 9600 | 9527 (D7) | -0.8 | 9586 (5D) | -0.1 |
Application Example #1
SPI Mode (1,1) Interface Using Synchronous Serial Mode 0
While one can interface to an SPI™ device by "bit-banging" port pins, using synchronous Serial Mode 0 reduces software overhead and allows faster communication speed. The synchronous serial mode of operation provides a shift clock on the TXD pin and writes/reads serial data on the RXD pin at each rising edge of the shift clock (TXD). Since TXD idles in the high state, the synchronous serial mode aligns closely with the CPOL = 1, CPHA = 1 SPI Mode. Since the synchronous serial mode does not require a 3-sample majority-voting scheme for each bit (like the asynchronous serial modes), it is capable of achieving baud rates faster than any other serial mode. The figure below illustrates an interface between the DS89C430 microcontroller and an SPI mode (1,1) compatible EEPROM device.
Serial Port 0 is first placed into Mode 0 and configured to produce a system clock divide by 4 baud clock. Depending upon the timing restrictions of the attached SPI peripheral, a reduced system clock or system clock divide by 12 baud clock may need to be selected. Externally, the TXD pin (P3.1) provides the serial clock and connects to the SCK input of the EEPROM. The RXD pin (P3.0) handles all SPI data transactions via its connection to both the SI input and SO output of the EEPROM. The ability to use a shared SI/SO configuration will depend upon the I/O timing of the attached SPI peripheral. A third microcontroller port pin, not linked to the on-chip serial port hardware, serves as the SPI peripheral chip select input. In this example, port pin P3.2 will be connected to the EEPROM active-low CS input and will be manually asserted and de-asserted by the software. Since the serial port communicates LSB first and the SPI peripheral expects to communicate MSB first, a lookup table is used for byte translation in most cases.
Two routines, XRAM_store and XRAM_recall, have been created and do exactly as their names would simply. The XRAM_store routine writes the current contents of the internal 1kB SRAM to a specified 1kB range of EEPROM, while XRAM_recall reads the specified 1kB range of EEPROM into the DS89C430 on-chip SRAM. This code is intended only as an example and could easily be adapted to access different address ranges of the microcontroller or EEPROM memory, in smaller or larger blocks.
Code Listing: SPI Interface Using Synchronous Serial Port
;-------------------------------------------------------------- ; DS89C430 SPI I/F example code ; ; 420 pin SPI I/F pin ; --------- ----------- ; P3.2 Active-Low CS ; P3.1/TXD SCK ; P3.0/RXD SI,SO ;-------------------------------------------------------------- $include(420.def) ;SFR equates ee_cs bit p3.2 ;EEPROM Active-Low CS ;-------------------------------------------------------------- ; SPI EEPROM opcodes – (CAT25C64 used) ; ; (bits in each byte are reversed since serial communication ; is lsb-first whereas SPI communication is msb-first). ;-------------------------------------------------------------- ee_wren equ 01100000b ;=06h ee_rdsr equ 10100000b ;=05h ee_read equ 11000000b ;=03h ee_write equ 01000000b ;=02h ;-------------------------------------------------------------- ; constants ;-------------------------------------------------------------- eepg equ 64d ;64byte page writes (CAT25C64) xdb equ 1024d ;1KB xdata block ;-------------------------------------------------------------- ; Main Program ;-------------------------------------------------------------- org 0000h ;-------------------------------------------------------------- ; Serial Port 0: Mode 0, baud clock=sysclk/4 ; (Note: Tested @ sysclk = 25 MHz; SPI baud clock = 6.25 MHz. ; A reduced system clock frequency or sysclk/12 baud clock ; may be required depending on SPI device timing) ;-------------------------------------------------------------- mov scon, #20h ; mode 0, sysclk/4 clk ; mov scon, #00h ; mode 0, sysclk/12 clk ;-------------------------------------------------------------- ; XRAM store/recall example ;-------------------------------------------------------------- orl pmr, #01h ; Enable 1KB XRAM ;==> COPY CODE (0-03FFh) INTO XRAM DATA (0-03FFh) mov dps, #30h ; dptr auto-inc/tog <ON> mov dptr, #0000h ; code dptr mov dptr, #0000h ; xram dptr copy: clr a movc a, @a+dptr ; read from code movx @dptr, a ; write to data mov a, dph cjne a, #04h, copy ; dptr=0400h yet? mov dps, #00h ; dptr auto-inc/tog <OFF> ;==> STORE XRAM TO EEPROM BLOCK 0 (0000h - 03FFh) clr a ; a=00h (=EEPROM block 0) call XRAM_store ; store to EEPROM ;==> FILL XRAM WITH FFh DATA call fx ; fill XRAM with FFh data ;==> RECALL EEPROM BLOCK 0 (0000h - 03FFh) TO XRAM clr a ; a=00h (=EEPROM block 0) call XRAM_recall ; recall from EEPROM sjmp $ ;-------------------------------------------------------------- ; XRAM_store (a) ; acc: selects 1KB EEPROM block to store XRAM ; 00 -> 0000h-03FFh ; 01 -> 0400h-07FFh ; .. ; 07 -> 1C00h-1FFFh ; r5: local counter = pages left to write ;-------------------------------------------------------------- XRAM_store: mov dps, #01h ; dptr1= source (XRAM) mov dptr, #0000h ; dptr1= 0000h mov r5, #(xdb/eepg) ; 1024/64 = 16 rl a ; rotate block index left rl a ; twice to get msb addr mov dph, a ; dptr = dest (EEPROM) mov dpl, #00h write: call wren ; __________WREN___________ wel_wait: call rdsr ; __________RDSR___________ jnb acc.1, wel_wait ; poll for WEL bit = 1 clr ee_cs ; Active-Low CS = 0 mov sbuf, #ee_write ; __________WRITE__________ jnb ti, $ ; command sent clr ti mov a, dph ; get dest msb addr call bitrev ; use LUT to transpose byte mov sbuf, a ; __________<MSB>__________ jnb ti, $ ; <MSB> sent clr ti mov a, dpl ; get dest lsb addr call bitrev ; use LUT to transpose byte mov sbuf, a ; __________<LSB>__________ jnb ti, $ ; <LSB> sent clr ti orl dps, #30h ; dptr auto-inc/tog <ON> write_64: movx a, @dptr ; dptr1 XRAM read call bitrev ; use LUT to transpose byte mov sbuf, a ; __________<DATA>_________ inc dptr ; inc dest dptr mov a, dpl ; check dest dptr for page anl a, #(eepg-1) ; write multiple (64d) jnb ti, $ ; <DATA> sent clr ti jnz write_64 ; 64bytes written? setb ee_cs ; Active-Low CS=1 rdypoll: call rdsr ; __________RDSR___________ jb acc.0, rdypoll ; poll for RDY bit = 0 djnz r5, write ; all pages written? anl dps, #0cfh ; dptr auto-inc/tog <OFF> ret ;-------------------------------------------------------------- ; XRAM_recall (a) ; acc: selects 1KB EEPROM block to copy into XRAM ; 00 -> 0000h-03FFh ; 01 -> 0400h-07FFh ; .. ; 07 -> 1C00h-1FFFh ; r5: local counter of 256byte pages left to read ;-------------------------------------------------------------- XRAM_recall: mov dps, #01h ; dptr1 = dest (XRAM) mov dptr, #0000h ; dptr1 = 0000h mov r5, #(xdb/256) ; 1024/256 = 4 rl a ; rotate block index left rl a ; twice to get msb addr clr ee_cs ; Active-Low CS = 0 mov sbuf, #ee_read ; __________READ___________ jnb ti, $ ; command sent clr ti call bitrev ; use LUT to transpose byte mov sbuf, a ; __________<MSB>__________ jnb ti, $ ; msb sent clr ti mov sbuf, #00h ; __________<LSB>__________ jnb ti, $ ; lsb sent clr ti setb ri ; don't receive yet setb ren ; enable receive orl dps, #10h ; dptr auto-inc <ON> read: clr ri ; __________<DATA>_________ jnb ri, $ ; got data mov a, sbuf call bitrev ; use LUT to transpose byte movx @dptr, a ; dptr1 XRAM write mov a, dpl1 ; check dest dptr for 256 jnz read ; byte boundary djnz r5, read ; all pages read? clr ren ; disable receive clr ri setb ee_cs ; Active-Low CS = 1 anl dps, #0efh ; dptr auto-inc <OFF> ret ;-------------------------------------------------------------- ; EEPROM commands: WREN, RDSR ;-------------------------------------------------------------- wren: clr ee_cs ; Active-Low CS = 0 mov sbuf, #ee_wren ; __________WREN___________ jnb ti, $ ; command sent clr ti setb ee_cs ; Active-Low CS = 1 ret rdsr: clr ee_cs ; Active-Low CS = 0 mov sbuf, #ee_rdsr ; __________RDSR___________ jnb ti, $ ; command sent clr ti setb ren ; enable receive jnb ri, $ ; got data clr ren ; disable receive clr ri setb ee_cs ; Active-Low CS = 1 mov a, sbuf call bitrev ; use LUT to transpose byte ret ;-------------------------------------------------------------- ; fill XRAM with FFh data ;-------------------------------------------------------------- fx: mov dps, #10h ; dptr auto-inc <ON> mov dptr, #0000h fx1: mov a, #0ffh movx @dptr, a mov a, dph cjne a, #04h, fx1 mov dps, #00h ; dptr auto-inc <OFF> ret ;-------------------------------------------------------------- ; bit reversal LUT ;-------------------------------------------------------------- bitrev: jnz do_lookup ; no lookup if a=00h ret ; since 00h transposed = 00h do_lookup: movc a, @a+pc ret db 080h,040h,0C0h,020h,0A0h,060h,0E0h db 010h,090h,050h,0D0h,030h,0B0h,070h,0F0h db 008h,088h,048h,0C8h,028h,0A8h,068h,0E8h db 018h,098h,058h,0D8h,038h,0B8h,078h,0F8h db 004h,084h,044h,0C4h,024h,0A4h,064h,0E4h db 014h,094h,054h,0D4h,034h,0B4h,074h,0F4h db 00Ch,08Ch,04Ch,0CCh,02Ch,0ACh,06Ch,0ECh db 01Ch,09Ch,05Ch,0DCh,03Ch,0BCh,07Ch,0FCh db 002h,082h,042h,0C2h,022h,0A2h,062h,0E2h db 012h,092h,052h,0D2h,032h,0B2h,072h,0F2h db 00Ah,08Ah,04Ah,0CAh,02Ah,0AAh,06Ah,0EAh db 01Ah,09Ah,05Ah,0DAh,03Ah,0BAh,07Ah,0FAh db 006h,086h,046h,0C6h,026h,0A6h,066h,0E6h db 016h,096h,056h,0D6h,036h,0B6h,076h,0F6h db 00Eh,08Eh,04Eh,0CEh,02Eh,0AEh,06Eh,0EEh db 01Eh,09Eh,05Eh,0DEh,03Eh,0BEh,07Eh,0FEh db 001h,081h,041h,0C1h,021h,0A1h,061h,0E1h db 011h,091h,051h,0D1h,031h,0B1h,071h,0F1h db 009h,089h,049h,0C9h,029h,0A9h,069h,0E9h db 019h,099h,059h,0D9h,039h,0B9h,079h,0F9h db 005h,085h,045h,0C5h,025h,0A5h,065h,0E5h db 015h,095h,055h,0D5h,035h,0B5h,075h,0F5h db 00Dh,08Dh,04Dh,0CDh,02Dh,0ADh,06Dh,0EDh db 01Dh,09Dh,05Dh,0DDh,03Dh,0BDh,07Dh,0FDh db 003h,083h,043h,0C3h,023h,0A3h,063h,0E3h db 013h,093h,053h,0D3h,033h,0B3h,073h,0F3h db 00Bh,08Bh,04Bh,0CBh,02Bh,0ABh,06Bh,0EBh db 01Bh,09Bh,05Bh,0DBh,03Bh,0BBh,07Bh,0FBh db 007h,087h,047h,0C7h,027h,0A7h,067h,0E7h db 017h,097h,057h,0D7h,037h,0B7h,077h,0F7h db 00Fh,08Fh,04Fh,0CFh,02Fh,0AFh,06Fh,0EFh db 01Fh,09Fh,05Fh,0DFh,03Fh,0BFh,07Fh,0FFh end
Application Example #2
RS-485 Networking Using Asynchronous Serial Mode 3
The asynchronous serial port modes transmit and receive data in a format that is compatible with the universally accepted RS-232 protocol. The Ultra High Speed Microcontroller, when running at its maximum system clock frequency (33MHz) and using the system clock Timer input (T1MH = 1), can achieve asynchronous baud rates in excess of 2Mbaud. (The Ultra High Speed Microcontroller contains a table showing the maximum baud rates for each serial mode). Unfortunately, to comply with the physical requirements of the RS-232 standard, RS-232 transmitters must provide a minimum output voltage swing of ±5V and yet not exceed a 30V/µs slew rate. These restrictions generally confine RS-232 compliant communication to slower baud rates, and short line lengths. The limitations associated with the RS-232 standard should not, however, prevent the use of the asynchronous serial modes when higher transmission rates are required. First of all, RS-232 "compatible" (not compliant) transceivers, capable of MegaBaud™ operation, are currently available from Analog Devices. For details about MegaBaud RS-232-compatible transceivers, please visit the Analog Devices website (www.analog.com). Secondly, point-to-point connection between multiple microcontrollers and/or other asynchronous serial devices allows creation of user-defined networks that can communicate at faster baud rates. Additionally, there are physical layer protocols (e.g., RS-422 and RS-485) that support high-speed asynchronous serial communication over greater distances.
The figure above diagrams an RS-485 network interface between (3) DS89C430 microcontrollers. The asynchronous serial modes use the TXD pin for transmission and the RXD pin for reception. These pins connect directly to the DI (data input) and RO (receive output) pins of the RS-485 transceiver. A third microcontroller port pin, P1.4, is connected to both the DE (data enable) and active-low RE (receive enable) and will serve as the directional control for the half-duplex transceiver. The network uses a master/slave architecture (1 master, 2 slaves), where each slave device has its own unique address and must first be addressed by the master before transmitting on the bus. All devices are operated at a 22.1184MHz system clock frequency and use Timer 1 to produce a 1.38M baud rate. The settings needed to generate this baud rate can be found in Table 4 following the figure.
SYSTEM CLOCK (MHz) | EXTERNAL CRYSTAL OR CLOCK FREQUENCY (MHz) | CLOCK MULTIPLIER MODE² | TIMER 1 RELOAD VALUE | ||||
FB | FC | FD | FE | FF | |||
7.3728 | 7.3728 | - | 92,160 | 115,200 | 153,600 | 230,400 | 460,800 |
10.0000 | 10.0000 | - | 125,000 | 156,250 | 208,333 | 312,250 | 625,000 |
11.0592 | 11.0592 | - | 138,240 | 172,800 | 230,400 | 345,600 | 691,200 |
14.7456 | 7.3728 | 2X | 184,320 | 230,400 | 307,200 | 460,800 | 921,600 |
16.0000 | 16.0000 | - | 200,000 | 250,000 | 333,333 | 500,000 | 1,000,000 |
18.4320 | 18.4320 | - | 230,400 | 288,000 | 384,000 | 576,000 | 1,152,000 |
20.0000 | 10.0000 | 2X | 250,000 | 312,250 | 416,667 | 625,000 | 1,250,000 |
22.1184 | 11.0592 | 2X | 276,480 | 345,600 | 460,800 | 691,200 | 1,382,400¹ |
25.0000 | 25.0000 | - | 312,500 | 390,625 | 520,833 | 781,250 | 1,562,500 |
29.4912 | 7.3728 | 4X | 368,640 | 460,800 | 614,400 | 921,600 | 1,843,200 |
32.0000 | 16.0000 | 2X | 400,000 | 500,000 | 666,667 | 1,000,000 | 2,000,000 |
33.0000 | 33.0000 | - | 412,500 | 515,625 | 687,500 | 1,031,250 | 2,062,500 |
¹ Baud rate used in Application Example #2. ² The clock multiplier is used for illustration and is not required to generate these system clock frequencies. |
Code Example: Master Code
The master device is initialized as the transmitter and drives the DE, active-low RE pins of its transceiver to logic high. After transmitting the slave address, the master places the transceiver into receive mode. Upon reception of two data bytes from the slave, the master returns the transceiver to its transmit mode. The master uses 13-bit Timer 0 to time-out if two data bytes are not received from the addressed slave within a certain period of time. The master sends the slave address and received data bytes (or an indication that no response was received) to Serial Port 0 before addressing the other slave.
;------------------------------------------------------------- ; DS89C430 RS-485 I/F example ; Master Code ; ; 420 pin MAX3088 I/F pin ; --------- ----------- ; P1.4 DE, Active-Low RE ; P1.3/TXD DI ; P1.2/RXD RO ;------------------------------------------------------------- $include(420.def) ;SFR equates tx485 bit p1.4 ;MAX3088 DE, Active-Low RE ;------------------------------------------------------------- ; Main Program ;------------------------------------------------------------- org 0000h ljmp start ;------------------------------------------------------------- ; Timer 0 Interrupt ;------------------------------------------------------------- org 000bh ; slave didn't respond clr tr0 ; stop Timer0 mov th0, #00h ; reset Timer0 mov tl0, #00h setb tx485 ; MAX3088 into transmit mode pop acc ; get rid of address pushed pop acc ; to stack on interrupt pop acc ; get rid of address pushed pop acc ; to stack on 'call getch' pop acc ; get slave address call putbyt ; print slave address mov dptr, #no_data ; 'no response' string call puts ; print string mov a, #low(del) ; return to delay routine push acc mov a, #high(del) push acc reti ;------------------------------------------------------------- ; Start of Main ;------------------------------------------------------------- org 0100h start: setb tx485 ; MAX3088 in transmit mode ;------------------------------------------------------------- ; Timer 0 Configuration ; used for time-out when no response from addressed slave ;------------------------------------------------------------- mov tmod, #00h ; 13-bit timer mov tl0, #00h ; TH0:TL0 = 0000h mov th0, #00h setb et0 ; enable timer0 interrupt setb ea ; enable global interrupts ;------------------------------------------------------------- ; Serial Port 0 Configuration ; used to display slave address and returned databytes ;------------------------------------------------------------- orl t2con, #30h ; use Timer2 for tx/rx baud rate mov rcap2h, #0ffh ; RCAP2H:2L = FFFAh mov rcap2l, #0fah ; 115200 @22.1184 xtal freq mov th2, #0ffh mov tl2, #0fah mov scon, #40h ; serial mode 1 setb t2con.2 ; Timer2 run ;------------------------------------------------------------- ; Serial Port 1 Configuration ; used to tx/rx over RS-485 link ;------------------------------------------------------------- orl wdcon, #80h ; set baud rate doubler bit orl ckmod, #10h ; /1 input clk to Timer1 orl tmod, #20h ; Timer1: 8-bit autoreload mov th1, #0ffh ; fastest mov tl1, #0ffh ; setb tr1 ;timer run mov scon1, #0c8h ;mode 3, TB8=1 ;------------------------------------------------------------- ; RS-485 TX/RX routine ;------------------------------------------------------------- mov a, #01h ; slave uC address push acc ; save slave address tx: pop acc ; get previous slave address xrl a, #01h ; alternate 00h, 01h push acc ; save it twice push acc ; call putch1 ; send slave addr setb tr0 ; start Timer 0 for time-out clr tx485 ; MAX3088 into receive mode call getch1 ; get slave data byte mov r5, a ; store first data byte call getch1 ; get slave data byte mov r6, a ; store second data byte clr tr0 ; got both bytes mov th0, #00h ; reset Timer0 mov tl0, #00h setb tx485 ; MAX3088 into transmit mode ;------------------------------------------------------------- ; Output results over serial port 0 ;------------------------------------------------------------- pop acc ; get slave addr call putbyt ; print slave addr mov a, #' ' ; <space> call putch mov a, r5 ; get first data byte call putbyt ; print data byte mov a, r6 ; get second data byte call putbyt ; print data byte mov a, #0dh ; <CR/LF> call putch mov a, #0ah call putch ;------------------------------------------------------------- del: mov r0, #080h ; delay before next addr sent mov r1, #00h delay: mov r2, #00h delay1: djnz r2, $ djnz r1, delay1 djnz r0, delay sjmp tx no_data: db ' no response',0dh, 0ah, 0 $include(put_code.src) $include(putcode1.src) end
Code Example (continued): Slave #1, #2 Code
The slave devices are initially configured as receivers, driving the DE, acitve-low RE pins for their respective transceivers to logic low. The multiprocessor communication mode is used by both slave microcontrollers so that address transmissions over the network can be distinguished from data transmissions. When addressed, the slave device becomes a transmitter and responds to the master by sending two data bytes. Once these bytes have been sent, the slave returns the transceiver to receive mode and begins monitoring the network for its address.
;------------------------------------------------------------- ; DS89C430 RS-485 I/F example ; Slave #1, #2 code ; ; 420 pin MAX3088 I/F pin ; --------- ----------- ; P1.4 DE, Active-Low RE ; P1.3/TXD DI ; P1.2/RXD RO ;------------------------------------------------------------- $include(420.def) ;SFR equates tx485 bit p1.4 ;MAX3088 DE, Active-Low RE ;------------------------------------------------------------- ; Main Program ;------------------------------------------------------------- org 0000h clr tx485 ; MAX3088 in receive mode mov r1, #00h ; counter for slave data ;------------------------------------------------------------- ; Serial Port 1 Configuration ; used to tx/rx over RS-485 link ;------------------------------------------------------------- orl wdcon, #80h ; set baud rate doubler bit orl ckmod, #10h ; /1 input clk to Timer1 orl tmod, #20h ; Timer1: 8-bit autoreload mov th1, #0ffh ; fastest mov tl1, #0ffh ; setb tr1 ; Timer1 run mov scon1, #0e0h ; mode 3, multi-uC, TB8=0 mov saddr1, #00h ; slave#1 address ; mov saddr1, #01h ; slave#2 address mov saden1, #0ffh ; no mask - exact match ;------------------------------------------------------------- ; RS-485 RX/TX routine ;------------------------------------------------------------- rx: call getch1 ; waits until address match mov r0, #20h ; delay to ensure master djnz r0, $ ; gets into RX mode setb tx485 ; MAX3088 into transmit mode mov a, r1 ; get data for transmit call putch1 ; send 1st byte inc r1 ; update slave#1 data ; dec r1 ; update slave#2 data mov a, r1 ; get data for transmit call putch1 ; send 2nd byte inc r1 ; update slave#1 data ; dec r1 ; update slave#2 data clr tx485 ; MAX3088 into receive mode sjmp rx ; back looking for address $include(putcode1.src) end
Example Master Output to Serial Port 0
...* ...* 00 1213 01 EEED 00 1415 01 ECEB 00 no response (*** opened Slave #1 TXD-DI connection) 01 EAE9 00 1819 01 E8E7 00 1A1B 01 E6E5 00 1C1D 01 E4E3 00 1E1F 01 E2E1 00 2021 01 no response (*** opened Slave #2 TXD-DI connection) 00 2223 01 no response (*** Slave #2 TXD-DI connection still open) 00 2425 01 DCDB 00 2627 01 DAD9 ...* ...*
SERIAL MODE | BAUD CLOCK SOURCE | CLOCK MULTIPLIER SETTING 1X: CD1:0 = 10b 2X: CD1:0 = 00b 2X/4X = 0 4X: CD1:0 = 00b 2X/4X = 1 |
BAUD CLOCK FREQUENCY AS A FUNCTION OF THE EXTERNAL OSCILLATOR FREQUENCY (OSC) SMOD_x = Doubling Bit TH1 = Timer 1 Reload |
0 | System Clock/12 (SM2_x = 0) |
1X | OSC/12 |
2X | OSC/6 | ||
4X | OSC/3 | ||
System Clock/4 (SM2_x = 1) |
1X | OSC/4 | |
2X | OSC/2 | ||
4X | OSC | ||
1 or 3 | Timer 1 (T1MH, T1M = 00b) |
1X, 2X, or 4X | (2SMOD_x × OSC) [384 × (256 - TH1)] |
Timer 1 (T1MH, T1M = 01b) |
1X | (2SMOD_ × OSC) [128 × (256 - TH1)] |
|
2X | (2SMOD_x × OSC) [64 × (256 - TH1)] |
||
4X | (2SMOD_x × OSC) [32 × (256 - TH1)] |
||
Timer 1 (T1MH, T1M = 1Xb) |
1X | (2SMOD_x × OSC) [32 × (256 - TH1)] |
|
2X | (2SMOD_x × OSC) [16 × (256 - TH1)] |
||
4X | (2SMOD_x × OSC) [8 × (256 - TH1)] |
||
Timer 2 TCLK or RCLK = 1) |
1X, 2X, or 4X | OSC 32 × (65536 - RCAP2H:2L) |
|
2 | Oscillator Clock/64 | 1X, 2X, or 4X | (2SMOD_x × OSC) 64 |