Файл: Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 3556
Скачиваний: 1
50 3 TESTING THE PARALLEL PORT
The first argument “%2X\n” is a format specifier that is used when printing the value of InputData on your screen. The characters %2X specify that a hexadecimal format of field width 2 is to be used. A carriage return and a line feed are specified by the two characters \n, the character ‘n’ known as the new line character.
To represent a byte of incoming data, two hexadecimal digits are needed since each hexadecimal digit represents 4 bits. Therefore, a field width of 2 is appropriate. After printing the number, the cursor on your screen will be positioned at the start of the next line.
The line:
getch();
is used to make the program wait for a key press and give us time to read what has been printed on the screen. The getch() function waits to receive a character from the keyboard and so the program will not proceed until a key is pressed. When this happens the program will terminate since there are no more statements to execute.
The operation of the program can be verified by interpreting the bit pattern of the hexadecimal value printed on-screen and then checking that this bit pattern corresponds to the actual signals generated on the interface board. You can change the connections on the interface board by changing the connections shown in the right-most column of Table 3-2. That is, you can re-arrange the connection of signals to ground and to +5V. If you run the program again, you should see a different result on the screen.
3.6 Compensating for Internal Inversions
Consider the program shown in Listing 3-2. When we read the port at address BASE+1 (0x379), one of the signals (bit D7) we read from the interface board was inverted by the parallel port hardware. Similarly, some of the signals at port address BASE+2 (0x37A) will be inverted by the hardware when output through this port (bits D0, D1, and D3). In this section we will learn how to modify our software to compensate for such inversions. This compensation can be done in software by simply inverting the affected bits to counteract the inversions that are made by the hardware.
3.6.1 Output Operation
The program shown in Listing 3-3 will write data to the port at address BASE+2. Note that this port only controls bits 0, 1, 2 and 3; bits 4, 5, 6 and 7 are not dedicated for internal use by the port at address BASE+2. Some of these bits that can be controlled are inverted internally by the parallel port electronics when output; bits 0, 1, and 3. Therefore, to nullify this inversion by hardware we must
3 TESTING THE PARALLEL PORT 51
invert bits 0, 1 and 3 in software. Bit 2 is not inverted internally by the parallel port hardware, and so we do not not need to invert it in software.
The that need to be made on the interface board are shown in Table 3-3.
Table 3-3 Connections to the LED Circuit.
BASE+2 Address† |
ULN2803A |
(Driver IC, U3) |
|
/D0 |
D0 (1) |
/D1 |
D1 (2) |
D2 |
D2 (3) |
/D3 |
D3 (4) |
† The signals preceded with a slash ( / ) are internally inverted by the parallel port hardware.
Listing 3-3 Writing to the port at BASE+2 with compensation for internal inversions.
/***************************************************** WRITING TO PORT @ BASE+2, INTERNAL INVERSIONS COMPENSATED
This program outputs 4 bits of data to the port at address BASE+2, compensating for the inverted bits 0, 1 and 3.
You can change the value of the actual bit pattern you want to see output to the interface board.
*****************************************************/
#include <dos.h> #define BASE 0x378
void main()
{
//BASE+2 bits 0,1 and 3 are internally inverted by
//the parallel port hardware before being output. This
//can be compensated in software by carrying out an
//exclusive OR operation with the output data and 0x0B
//(0000 1011). Bits 4-7 do not matter as they are not
//connected. outportb(BASE+2,0x0B ^ 0x0F);
//NOTE: In binary 0x0F = 0000 1111
//The number being output (0x0F) can be changed to any
//value between 0x00 and 0x0F. The four output signals
//will correspond to the binary bit pattern represented by
//the number.
52 3 TESTING THE PARALLEL PORT
// Examples: |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
// |
Bit No: |
||||||||
// |
0x0F |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
// |
0x05 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
} |
|||||||||
In this program, the only line that requires explanation is:
outportb(BASE+2,0x0B ^ 0x0F);
The outportb()function writes data to the port in a manner similar to its use before. In this case, the address of the port is BASE+2. The define statement defines BASE to be a placeholder for 0x378. Therefore, the value of the first parameter is 0x378+2, which is 0x37A. The value of the second parameter is the data we want to send out the port. This data is obtained, by evaluating:
0x0B ^ 0x0F
The operator ‘^’ used in the above expression is known as the Exclusive-OR (XOR) operator. It is one of the many bit-wise operators available in C and C++ that is used to operate at bit level. You will have a better understanding of how bitwise operators work once the operation shown in Table 3-5 has been explained. The operation of the exclusive OR operator will be described with the aid of Table 3-4. This operator requires two operands when used.
Table 3-4 Exclusive OR operation.
Operand A |
0 |
0 |
1 |
1 |
|
Operand B |
0 |
1 |
0 |
1 |
|
Result |
0 |
1 |
1 |
0 |
NOTE
In the simple arithmetic operation:
3 + 5
the operator is ‘+’ and the two operands are 3 and 5.
For a bit-wise operator, the operands must be bits. In Table 3-4 the two operands are given the names Operand A and Operand B. The results produced by the XOR operation for all four possible combinations of the two operands are listed in the ‘Result’ row. As can be seen, the result is 1, only when just one of the two operands in a column is 1. When both operands in a column are identical, the result
3 TESTING THE PARALLEL PORT 53
is zero. So when the operands differ, the result is 1. As shown by columns 2 and 4 of Table 3-4, if we hold the Operand B at 1, the result will be the inversion of operand A. Operand B acts as a ‘filter’ for inverting specific bits of Operand A.
We use this operation to perform software inversions to counteract the internal inversions generated by the parallel port hardware. Table 3-5 explains the result of evaluating:
0x0B ^ 0x0F
Here Operand A contains the data to be sent out and Operand B is the “filter” used to invert the bits already inverted by the parallel port.
Table 3-5 Evaluation of 0x0B ^ 0x0F.
Bit No. Æ |
7 6 5 4 3 2 1 0 |
|||||||
Operand A (0x0F) |
0 0 0 0 1 1 1 1 |
|||||||
Operation |
XOR |
|||||||
Operand B (0x0B) |
0 0 0 0 1 0 1 1 |
|||||||
Result |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
As explained earlier, bit-wise operators operate on a bit-by-bit basis. In other words, bit 0 of Operand A and bit 0 of Operand B are put through an exclusive OR operation. Likewise, another exclusive OR operation takes place between bit 1 of Operand A and bit 1 of Operand B, and so forth.
The filter comprises data bits that we want inverted set to 1, and bits to be left as is set to 0. Thus, to invert bits 0, 1 and 3 of data to be sent out, the bits 0, 1 and 3 of the filter are set to 1. As can be seen, in the ‘Result’ row of Table 3-5, bits 0, 1 and 3 are the opposite values of bits 0, 1 and 3 of Operand A. Therefore, when we write the exact bit pattern we want as Operand A, the affected bits will be inverted by software to become the ‘Result’. When those affected bits of the ‘Result’ are then sent to the parallel port hardware and internally inverted, the data arriving at the interface board will correspond to Operand A that we originally want to send out.
To verify operation of the program, you can change the data (i.e. 0x0F) to any value between 0x00 and 0x0F. The LEDs that light up will correspond to the binary bit pattern of the data specified in the program. Note that the filter value 0x0B must not be changed – otherwise not all those specific bits we want to invert (0, 1, and 3) will actually be inverted in software.
3.6.2 Input Operation
In program Listing 3-2, one of the signals being read in through the port at address BASE+1 was internally inverted by the parallel port hardware. Note that the port BASE+1 can only input the bits numbered 3, 4, 5, 6 and 7. Of these bits, bit 7 is
54 3 TESTING THE PARALLEL PORT
internally inverted. Similar to the operation performed in the previous section, this internal inversion can also be compensated in software. This is done by performing an Exclusive OR operation using a ‘filter’ bit to toggle bit 7 as soon as the port is read. The value of the filter to be used is:
0x80 = 1 0 0 0 0 0 0 0
The required operation is shown in Table 3-6. Note that the unused and therefore invalid data bits D0, D1 and D2 are shown as ‘x’ in the example. These bits can be in either logic state and therefore the Exclusive OR result will also be indeterminate for these bits.
Table 3-6 Inversion of bit 7.
Bit no. |
7 6 5 4 3 |
2 1 0 |
||
Operand A (data received) |
1 0 1 1 1 |
x x x |
||
Operation |
XOR |
|||
Operand B (the filter, 0x80) |
1 0 0 0 0 |
0 |
0 |
0 |
Result (corrected data) |
0 0 1 1 1 |
x |
x |
x |
Listing 3-4 Reading the port BASE+1 with internal inversions compensated.
/***************************************************** READING THE PORT @ BASE+1, INTERNAL INVERSIONS COMPENSATED
This program reads the port at address BASE+1 (0x379). It compensates for the hardware inversion of bit 7 after reading the data. The net result is as if the hardware inversions had not taken place.
*****************************************************/
#include <dos.h> #include <conio.h> #include <stdio.h>
#define BASE 0x378
void main()
{
unsigned char InputPort1;
InputPort1 = inportb(BASE+1);
InputPort1 ^= 0x80;
3 TESTING THE PARALLEL PORT 55
printf("%2X\n",InputPort1);
getch();
}
The only line that needs explanation in the program given in Listing 3-4 is:
InputPort1 ^= 0x80;
This statement is equivalent to the following statement:
InputPort1 = InputPort1 ^ 0x80;
And is of the form:
Result = Operand A ^ Filter;
Operand A stands for the raw data read from the port. Result stands for the compensated value. Consider the statement:
InputPort1 = InputPort1 ^ 0x80;
InputPort1 on the right-hand side contains the raw data affected by the internal inversion of the parallel port hardware. The InputPort1 shown on the left-hand side is the result obtained by carrying out an Exclusive OR operation between the raw data and the filter value 0x80. In other words, the value of InputPort1 is Exclusive-ORed with the filter value and then this result is stored back into the InputPort1 variable. The printf() statement then prints the compensated value on the screen. As a result, the number appearing on the screen should represent the actual signal levels connected on the interface board.
3.7 Summary
In this chapter we have explained the operation of the interface board power supply, port interface, and LED Driver circuits. These circuits allow the parallel port of the PC to interface with the interface board and test operation of programs.
We learned how to develop C++ programs for sending and receiving bytes of data through the three addresses associated with the parallel port of the PC. These programs printed their results to the screen using either the cout object (as we did in Chapter 1), or using the functions of the printf() family. We also explained a small subset of the format specifiers that the printf() function uses.
The Exclusive OR bitwise operator was used to toggle some of the data bits we transmitted through the parallel port. Bitwise operators are a very useful part of the C and C++ languages and allow us to manipulate specific bits within a byte.