Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 5320
Скачиваний: 0
9. High-Level Language 245
Examples
Example 9.1
Write a C function to return the square root of a positive 16-bit integer. The algorithm of Fig. 6.9 on page 162 is to be used to implement the conversion.
Solution
Modifying the task list of Example 6.5 to suit the structure of the C while loop gives:
1.Zero the loop count
2.Set variable i (the magic number) to 1
3.WHILE i is less than or equal to the number
(a)Take i from Number
(b)Add 2 to i
(c)Increment the loop√ count
4. Return loop count as Number
The function heading gives it its name sqr_root and defines the parameters to be passed to the function and the outcome. The form unsigned int sqr_root(unsigned long number) declares that it will return an unsigned int value and one unsigned long int object will be passed to it, which will be known as number within the function. On this basis the coding of Program 9.2 directly implements the task list. As the square root of a 16-bit object will fit into an 8-bit byte, the loop count is declared unsigned int. The magic number i will however be twice (plus one) that of count and is therefore defined as a unsigned long object. At the same time as these internal function variables are defined they are given their initial values.
The while loop is repeated until the value of the reducing number drops below the increasing value of i, at which point any further subtraction will drop the outcome below zero. The value of the loop count is the square root and is returned to the caller at the end of the function.
Program 9.2 Coding the square root function.
unsigned int sqr_root(unsigned long number)
{
unsigned int count = 0; unsigned long i = 1; while(number>=i)
{
number = number - i; i = i + 2;
count++;
}
return count;
}
9. High-Level Language 247
As we are told that only the 14 lower bits of emf have any meaning, line 4 ANDs the 16-bit object with 3FFFh (0x3FFF) to clear the upper two bits. The 0x prefix is C’s way of denoting hexadecimal.
Finally an unsigned long version of the float object temperature is made and returned in line 8.
The resulting executable code running on a mid-range PIC core takes 667 program words; or around 23 of the Program store of a PIC16F84 device. Because of the size penalty of using floating-point objects, fixedpoint arithmetic is used wherever possible in embedded microcontroller implementations.
Example 9.4
On page 213 we implemented a root mean square program to implement
the mathematical relationship NUM_12 + NUM_22. Write a C function to implement this relationship, where the two 8-bit objects num_1, num_2 are passed to the function which returns the 8-bit value rms.
Solution
The solution shown in Program 9.4 uses the internal unsigned long 16-bit variable sum to hold the addition of the two squared 8-bit variables. The squaring operation is simply implemented using the C multiplication operator * rather than coding a squaring function of the manner of Program 8.3 on page 215. The function developed in Program 9.2 is used to
Program 9.4 Generating the root-mean square value of two variables.
unsigned int variance(unsigned int num_1, unsigned int num_2)
{
unsigned long sum; unsigned int rms;
sum = (unsigned long)num_1*num_1 + (unsigned long)num_2*num_2; rms = sqr(sum);
return rms;
}
unsigned int sqr(unsigned long number)
{
unsigned int count = 0; unsigned long i = 1; while(number>=i)
{
number = number - i; i = i + 2;
count++;
}
return count;
}
248 The Quintessential PIC Microcontroller
generate the square root of the 16-bit sum object and is called from the function variance() line 6 with the return value being assigned to the variable sum as part of the call. In compiling the source code using the CCS C compiler, 100 machine-level instructions are needed to implement this problem. This compares to 62 instruction for the assembly-code version of Chapter 8. This gives an e ciency ratio of 62%.
Self-assessment questions
9.1The coding of Program 9.2 can be simplified if it is observed that the variable i is always twice count plus one, so count is not needed. Instead, on return the 16-bit value i can be logic shifted once right (see page 11) and the 8-bit cast version of the remainder is the equivalent of the absent count. In shifting right the datum is divided by two and by throwing away the one that pops out, e ectively subtracts by one (i is always odd and so its least significant bit is always 1). Try coding this alternative arrangement. The C operator to shift right by n places is >> n. If the datum is unsigned then the shift is a logic shift right. See Example 9.3 to see how to cast a datum to another type.
9.2A PIC-based digital thermometer is to display temperatures between 0◦C and 100◦C. To be able to market the device to USA the thermometer is to have the option to display the temperature in Fahrenheit. Write a function for a PIC-based thermometer that is to convert Celsius integers to the equivalent Fahrenheit integer. The input is to be an unsigned int byte representing Celsius and the return Fahrenheit is also to be an unsigned int datum. The relationship is:
fahrenheit = (celsius × 9)/5 + 32
and the arithmetic should be done in 16-bit precision to avoid overrange.
9.3 A cold-weather indicator in an automobile dashboard display comprises three LEDs, which are connected to the lower three bits of Port A. Bit 2 of this location is connected to the red LED, which is to light if the Fahrenheit temperature is less than 30. Bit 1 is the yellow LED for temperatures below 40◦F, and bit 0 is the green LED. Write a function, whose input is ◦F, that activates the appropriate LED.
Access to the LEDs through Port A at File 05h in C can be accomplished by placing the following line of code at the head of the program: You may assume that a logic 0 at the appropriate Port A pin
9. High-Level Language 249
lights the LED. You may also presume that the three appropriate Port A bits have been set to output mode.
#define LED *(unsigned int *)0x05
whereupon the variable LED can be altered like any other variable. You will also need to use the if-else conditional construction:
if(something is true) {do this;}
else if(whatever is true) {do that;}
else
{do the other;}
9.4 Arrays of objects can be defined in C using the notation fred[n] where fred is the name of the array and n is the nth element. For example an array of ten values making up the decimal 7-segment patterns described in Fig. 6.6 on page 148 can be defined and initialized as:
unsigned int 7_seg[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
These ten values for 7_seg[0] through 7_seg[9] will be placed in ten sequential file registers. As most PICs have a severally limited number of GPRs and this example is a array of constants it makes more sense to place these ten constant bytes in Program ROM. Using the key word const in front of the array definition tells the compiler to initialize Program store locations instead.
unsigned int const 7_seg[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
As data in the Program store is not directly accessible in the lowand mid-range PIC Harvard architecture the compiler will actually place a series of retlw <byte> instructions in ROM as described in Table 6.4 on page 149.
Based on the above array definition, code a C functionto return the 7-segment code equivalent of an unsigned int n passed to the function.
9.5 As part of a digital game a PIC is to drive an active-low 7-LED display to implement an electronic die. Our problem, outlined in Fig. 9.4, is to convert a ’throw’ number n between 1 and 6 to the 7-bit display.
250 The Quintessential PIC Microcontroller
Code a C function converting n, which is passed to the function, and returning the appropriate code pattern.
Throw pattern[n] a |
b |
|||||
n |
gfedcba |
f |
g c |
|||
e |
d |
|||||
1 |
0111111 |
3Fh |
||||
Throw |
Function |
Die pattern |
2 |
1110110 |
76h |
|
3 |
0110110 |
36h |
||||
n |
die() |
pattern[n] |
||||
4 |
1100100 |
64h |
||||
5 |
0100100 |
24h |
||||
6 |
1000000 |
40h |
||||
Fig. 9.4 The active-low die patterns.
9.6Driving the die requires seven parallel port lines and the electronic game requires to drive two die displays. By inspection of the patterns of Fig. 9.4 how could you reduce the requirement to four bits only?
9.7As part of the same electronic game a function is to be written to return the next pseudo random number in the 127 sequence defined by the generator configuration of Fig. 3.12 on page 70. The current number is to be passed to the function and the next number in the sequence returned. It may be assumed that this passed datum is never zero.
How could you modify the function to send the sequence of all 127 pseudo random numbers out of Port B beginning with the passed number?
9.8To integrate the outcome to the pseudo random function with the die display we need to map the set of 127 numbers to the range one to six. Devise a modified function to implement the mapping. Hint: What simple mathematical operation would map any number to the range zero to five?