// NOTE: calculations are in TICKS (not milliseconds)
for (Index = 0; Index < SCH_MAX_TASKS; Index++)
{
// Check if there is a task at this location
if (SCH_tasks_G[Index].pTask)
{
if (SCH_tasks_G[Index].Delay == 0)
{
// The task is due to run
SCH_tasks_G[Index].RunMe += 1; // Inc. the ‘RunMe’ flag
if (SCH_tasks_G[Index].Period)
{
// Schedule periodic tasks to run again - zero based so dec.
SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period - 1;
}
}
else
{
// Not yet ready to run: just decrement the delay
SCH_tasks_G[Index].Delay -= 1;
}
}
}
[Thanks to Tim Edwards and Balasubramanya Bellur Hiriyannaiah]
I have confused the IDs for “slaves” and “previous slaves” in this code section.
The correct version is as follows:
[code lang=”c”]
// Check that the appropriate slave responded to the previous message:
// (if it did, store the data sent by this slave)
if (SCC_A_MASTER_Process_Ack(Previous_slave_index) == RETURN_ERROR)
{
Error_code_G = ERROR_SCH_LOST_SLAVE;
Network_error_pin = NETWORK_ERROR;
// If we have lost contact with a slave, we attempt to
// switch to a backup device (if one is available)
if (Current_Slave_IDs_G[Previous_slave_index] != BACKUP_SLAVE_IDs[Previous_slave_index])
{
// There is a backup available: switch to backup and try again
Current_Slave_IDs_G[Previous_slave_index] = BACKUP_SLAVE_IDs[Previous_slave_index];
}
else
{
// There is no backup available (or we are already using it)
// Try main device.
Current_Slave_IDs_G[Previous_slave_index] = MAIN_SLAVE_IDs[Previous_slave_index]; }
// Try to connect to the slave
Slave_replied_correctly = SCC_A_MASTER_Start_Slave(Current_Slave_IDs_G[Previous_slave_index]);
if (!Slave_replied_correctly)
{
// No backup available (or backup failed too) - we shut down
// OTHERBEHAVIOURMAYBEMOREAPPROPRIATEINYOURAPPLICATION
SCC_A_MASTER_Shut_Down_the_Network();
} }
// Send ‘tick’ message to all connected slaves
// (sends data to the current slave)
SCC_A_MASTER_Send_Tick_Message(Slave_index_G); [/code]
The second sentence in the 4th paragraph is a mess.
It will make a little more sense as follows:
Specifically, we measure the error between the desired system output (that is, the desired speed of the vehicle in this case) and the current system output (the current vehicle speed in this case).
John correctly spotted that the description of the technique used to calculate the sample rate (based on the system rise time) contains an arithmetic error.
In addition, the equation on p.871 provides a sample rate that is close to the minimum required to ensure stability for many systems.
To solve both problems, the text beginning “Having determined the rise time …” (at the bottom of p.871) through to the start of the “Hardware Resources” section (on p.873) will be more useful if replaced with the following:
Having determined the rise time (measured in seconds), we can approximate the required sample rate as follows:
Sample rate (Hz) = 40 / Rise time (seconds)
Thus, if the rise time measured in Figure 35-11 was 0.1 second, the required sample frequency would be around 400 Hz.
Please note that this value is approximate, and involves several assumptions about the nature of the system. See Franklin et al. (1994), for further details.
Page 11
Figure 1.5 has the labels for ‘Background’ and ‘Foreground’ the wrong way round.
Page 89
The first line in Table 6.1 should read “64k x 8-bit data” (not 640 x 8-bit).
Pages 96-107
[Thanks to Gary Kennedy]
The label ‘74x573’ has been mixed-up during the production process, and has been consistently replaced with ‘74x375’. This occurs in several places.
The first error is on Page 96, in Figure 6.3: here the latch should read 74x373/573.
The error is repeated on Page 96 (in the text), Page 97 (Table 9.2), Page 99 (Figures 6.4 and 6.5), Page 100 (Table 6.3), Page 101 (Table 6.3 cont.) and Page 104 (Figure 6.6, Figure 6.7) and Page 107 (Figure 6.10).
Page 120
[Thanks to Javier Vega]
There are some errors in Figure 7.11.
Page 140
[Thanks to Javier Vega]
The first paragraph is repeated from the page before.
Page 154
[Thanks to Javier Vega]
In Figure 8.6 the capacitor in the snubber is not shown (although the label is present).
Page 178
There are some errors in Figure 10.1.
Page 264
[Thanks to Mohammad Attari]
The [code]SCH_Update[/code] function sets the delay incorrectly when it must be reset. The updated function should look like this:
[code type=”c”] void SCH_Update(void) interrupt INTERRUPT_Timer_2_Overflow { tByte Index;
TF2 = 0; // Have to manually clear this.
// NOTE: calculations are in TICKS (not milliseconds) for (Index = 0; Index < SCH_MAX_TASKS; Index++) { // Check if there is a task at this location if (SCH_tasks_G[Index].pTask) { if (SCH_tasks_G[Index].Delay == 0) { // The task is due to run SCH_tasks_G[Index].RunMe += 1; // Inc. the ‘RunMe’ flag
} [/code]
Page 291 onwards
Listing “2_01_12g.c” is printed twice.
Page 299
[Thanks to Yeow Heng Seow]
On the third line, the code should read:
[code lang=”c” linenumbers=”off”] unsigned int Timeout_loop = 0; [/code]
Pages 337 and 346
[Thanks to Ayman Gendy]
This line in Listing 17.3 does no harm but is NOT required:
[code lang=”c” linenumbers=”off”] hSCH_tasks_G[Index].RunMe -= 1; // Reset / reduce RunMe flag [/code]
Page 381
The code on the CD is a later (and better) version than that reproduced in the book.
Page 402
[Thanks to Javier Vega]
The caption should read “normally open”.
Page 497
[Thanks to Chisanga Mwelwa]
Figure 23.4 shows a DS1621 (incorrectly labelled 24C64).
Pages 614-615
[Thanks to Chisanga Mwelwa]
The captions for Figures 27.5a and 27.5b have been swapped during the production process.
Pages 694-695
[Thanks to Tim Edwards and Balasubramanya Bellur Hiriyannaiah]
I have confused the IDs for “slaves” and “previous slaves” in this code section.
The correct version is as follows:
[code lang=”c”] // Check that the appropriate slave responded to the previous message: // (if it did, store the data sent by this slave) if (SCC_A_MASTER_Process_Ack(Previous_slave_index) == RETURN_ERROR) { Error_code_G = ERROR_SCH_LOST_SLAVE; Network_error_pin = NETWORK_ERROR;
// If we have lost contact with a slave, we attempt to // switch to a backup device (if one is available) if (Current_Slave_IDs_G[Previous_slave_index] != BACKUP_SLAVE_IDs[Previous_slave_index]) { // There is a backup available: switch to backup and try again Current_Slave_IDs_G[Previous_slave_index] = BACKUP_SLAVE_IDs[Previous_slave_index]; } else { // There is no backup available (or we are already using it) // Try main device. Current_Slave_IDs_G[Previous_slave_index] = MAIN_SLAVE_IDs[Previous_slave_index]; }
// Try to connect to the slave Slave_replied_correctly = SCC_A_MASTER_Start_Slave(Current_Slave_IDs_G[Previous_slave_index]);
if (!Slave_replied_correctly) { // No backup available (or backup failed too) - we shut down // OTHER BEHAVIOUR MAY BE MORE APPROPRIATE IN YOUR APPLICATION SCC_A_MASTER_Shut_Down_the_Network(); } }
// Send ‘tick’ message to all connected slaves // (sends data to the current slave) SCC_A_MASTER_Send_Tick_Message(Slave_index_G); [/code]
Page 706
First line should read: “This Slave is triggered by CAN interrupts”.
Page 715
[Thanks to Trent Lillehaugen]
The last line of the example code:
[code lang=”c” linenumbers=”off”] printf(“Original data is %f\n”, X.Float); [/code]
should read:
[code lang=”c” linenumbers=”off”] printf(“Transferred data is %f\n”, Y.Float); [/code]
Page 721
[Thanks to Trent Lillehaugen]
“Worse, if we make the reasonable assume that…”
should read:
“Worse, if we make the reasonable assumption that…”
Also on this page:
In Figure 29.6, Processor 1 should be shown to run Task A, Task A, Task A, Task A, …
Page 764
[Thanks to Chisanga Mwelwa and Andrew Norman]
There is an error in the file “Port.H” The file should read as follows:
[code lang=”c”] /—————————————————————————————————-
Port.H (v1.00)
‘Port Header’ (see Chap 10) for project SPI_ADC (see Chap 32)
-—————————————————————————————————/
// ——— SPI_Core.C ———————————————————————-
// Create sbits for all required chip selects here
sbit SPI_CS = P1^3; // ***** NB ******
// NOTE: pins P1.4, P1.5, P1.6 and P1.7 also used - see text
/—————————————————————————————————-
—— END OF FILE ————————————————————————-
-—————————————————————————————————/ [/code]
Pages 777-781
[Thanks to John Moyer and Yukuan Jiang]
The pattern ADC Pre-Amp contains a number of errors and inconsistencies.
Pages 778-780
[Thanks to John Moyer]
The circuit diagrams in Figure 32.11, Figure 32.12 and Figure 32.13 have the positive and negative terminals of the op amps reversed.
Page 811
[Thanks to Trent Lillehaugen]
csnubber is missing in Figure 33.2.
Page 866
[Thanks to Trent Lillehaugen]
In Figure 35.9, the box should be labelled “Closed-loop controller” (not “Open-loop controller”).
Page 867
[Thanks to Trent Lillehaugen]
The second sentence in the 4th paragraph is a mess.
It will make a little more sense as follows:
Specifically, we measure the error between the desired system output (that is, the desired speed of the vehicle in this case) and the current system output (the current vehicle speed in this case).
Pages 871-872
[Thanks to John Moyer]
John correctly spotted that the description of the technique used to calculate the sample rate (based on the system rise time) contains an arithmetic error.
In addition, the equation on p.871 provides a sample rate that is close to the minimum required to ensure stability for many systems.
To solve both problems, the text beginning “Having determined the rise time …” (at the bottom of p.871) through to the start of the “Hardware Resources” section (on p.873) will be more useful if replaced with the following:
Having determined the rise time (measured in seconds), we can approximate the required sample rate as follows:
Sample rate (Hz) = 40 / Rise time (seconds)
Thus, if the rise time measured in Figure 35-11 was 0.1 second, the required sample frequency would be around 400 Hz.
Please note that this value is approximate, and involves several assumptions about the nature of the system. See Franklin et al. (1994), for further details.
Pages 928-930
[Thanks to Wang GuoYun]
The function “[code lang=”c”]Check_Switch()[/code]” should include a call to the “[code lang=”c”]Timer_1_Manual_Reload()[/code]”
Adding this function call at the end of “[code lang=”c”]Check_Switch()[/code]” will address this problem.