To improve running speed, inline assembly instructions can be embedded into the C programs we developed in the last section. We can embed inline assembly code into both the master and the slave projects. The projects will operate more efficiently if we replace the original C instructions FIGURE 2.40 The plotting result of the received data.
with assembly instructions for the lower-level subroutines, such as the sinial(), sends() and reces() functions. The main function and other functions used on the master and the slave computers are identical to those functions in the last section. First let’s take a look at the master project.
2.5.1 EMBEDDING INLINE ASSEMBLY CODE WITH THE MASTER ANDTHE SLAVE COMPUTERS
Launch Visual C++ 6.0 and create a new project with the following properties: • Project type: Win32 Console Application
• Project name: SerialCommEmb • Project location: C:\Chapter 2
All of the functions in this project except the three low-level functions sinial(), sends(), and reces() are identical to those developed in the preceding section for the master computer. In the following sections, we will concentrate only on these three functions. Copy all of the functions from the last project, SerialComm, and modify the three functions sinial(), sends(), and reces(), as shown in Figures 2.41, 2.42, 2.43 and 2.44.
Figure 2.41 shows a part of the modified header file. The only changes in the file have been made to the functions sends() and reces(). The function sends() has only one argument, and the function reces() now has no argument.
Figure 2.42 shows the sinial() function, which is used to initialize the serial port before data communication can be started.
The workings of this piece of code are straightforward and require no explanation. Figures 2.43 and 2.44 show the sends() and reces() functions for the master side.
Both of these functions were discussed in Section 2.3.10. By compiling and building the project, we create an executable file, SerialCommEmb.exe.
The same modifications are performed for the slave computer. Create a new Win32 Console Application project named SerialCommEmbs on the slave computer; then copy all functions from the SerialComms program and paste them into the newly created project. Modify the header file and three functions as you have just done for the master computer project. A new project with embedded inline assembly instructions is generated. Compile and build the project. Now the project is ready to be run on both the master computer and the slave computer.
FIGURE 2.41 A part of the modified header file.
…… struct serialDATA { char pos[64]; char ang[64]; double dpos; double dang; }; void sinial(); BYTE sends(char c); BYTE reces(); int comm_start();
int comm_collect(serialDATA* res); int send_index(int max);
After connecting the two computers with a null modem cable, run the program on the master computer by clicking Build|Execute SerialCommEmb.exe from the menu bar. After the master-side program has started, we can run the slave-side program. When prompted, enter 100 into the master computer for the size of the data segment to be transmitted. The two computers will yield similar results.
FIGURE 2.42 The function sinial() in the master computer.
FIGURE 2.43 The sends() function in the master computer. void sinial()
{ _asm {
mov dx, LCR ; Select the Line Control Register to set up the comm. parameters.
mov al, 80h ; Bit7 = 1, 3f8h & 3f9h registers can access the baud rate divisor.
out dx, al ; Nominal baud rate = 1843200/(baud rate*16).
mov dx, COM1 ;
mov al, 60h ; b7 - b0 = (60h) = (01100000b) -> 3f8h (baud rate low-byte)
out dx, al ;
mov dx, IER ;
mov al, 00h ; b7 - b0 = (00h) = (00000000b) -> 3f9h (baud rate high-byte)
out dx, al ; Set up the baud rate high & low bytes (0060h -> 1200 baud rate).
mov dx, LCR ; Finish set up the Line Controller Register.
mov al, 0bh ; b7 - b0 = 0bh = (00001011b) -> odd parity, 1 stop bit, 8 data bits.
out dx, al ; Set up LCR based on the above control parameters.
mov dx, MCR ; Set up MCR to set DTR & RTS to 1 (space or active).
mov al, 03h ; Self-test sub. if this line becomes "mov al,13h".
out dx, al ; Finish set up the MCR.
mov dx, IER ; Set up the Interupt Enable Register.
mov al, 0 ; No interrupt utilized.
out dx, al ; } } BYTE sends(char c) { char feedback; _asm {
done: mov dx, LSR ; Check the Line Status Register.
in al, dx ; Inspect the state word.
test al, 20h ; THR is empty? (when b5 = 1: THR is empty).
jz done ; No, continuing to check it and waiting.
mov dx, COM1 ; THR is empty & ready to send the next character.
mov al, c ; Assign character c to lower-byte in A register.
mov feedback, al ; Return the sent-out character as a feedback
out dx, al ; Send the character to the 8250.
jmp end
mov al, '?' ; Error occurs, send '?' as a feedback
mov feedback, al ; Return the error information.
end: nop }
return feedback; }
One of advantages of this project over the original serial port communication project we developed in Section 2.4 is that the execution speed is relatively faster because assembly code is used to replace the C code.
The complete code for this version of the master project, including the source file, header file, and executable file, can be found in the folder Chapter 2\SerialCommEmb located on the attached CD. The complete code, including the source file, header file, and executable file for the slave project can be found in Chapter 2\SerialCommEmbs.
2.6 AN INTERRUPT-DRIVEN SERIAL COMMUNICATIONS