AVR Embedded Tutorial - Int to digits: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: AVR Embedded Tutorial - Int to digits
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Output digits (7 segment display) | |
| 2 | + | ||
| 3 | + | If you want to output an integer on a 7-segment display, the best way to do this is with the procedure described below. This looks more complex than with div and mode, but is much faster because the AVR cannot do hardware division. The AVR has to do division with great effort and this takes a lot of time. | |
| 4 | + | ||
| 5 | + | ## 4-digit output on a 7-segment display | |
| 6 | + | ||
| 7 | + | ### Declaration of the variables | |
| 8 | + | ||
| 9 | + | ``` pascal | |
| 10 | + | var | |
| 11 | + | Digit : array[0..3] of byte; // Values of the individual digits | |
| 12 | + | MyValue : Integer; // An integer to be output | |
| 13 | + | ``` | |
| 14 | + | ||
| 15 | + | ### On the PC | |
| 16 | + | ||
| 17 | + | The individual digits would be calculated on the PC in this way. With an ATtiny this cannot even be compiled because it cannot do division in hardware. You could do the division in software, but this would take a lot of time. | |
| 18 | + | ||
| 19 | + | ``` pascal | |
| 20 | + | Digit[0] := MyValue div 1000; | |
| 21 | + | Digit[1] := MyValue div 100 mod 10; | |
| 22 | + | Digit[2] := MyValue div 10 mod 10; | |
| 23 | + | Digit[3] := MyValue mod 10; | |
| 24 | + | ``` | |
| 25 | + | ||
| 26 | + | ### On the AVR | |
| 27 | + | ||
| 28 | + | But since the ATmega cannot divide and the ATtiny does not even know multiplication, you have to calculate this as follows: | |
| 29 | + | ||
| 30 | + | ``` pascal | |
| 31 | + | procedure IntToDigit(val : UInt16); | |
| 32 | + | var | |
| 33 | + | aChr : byte; | |
| 34 | + | empty : boolean; | |
| 35 | + | begin | |
| 36 | + | // Thousands | |
| 37 | + | aChr := 0; | |
| 38 | + | empty := True; | |
| 39 | + | ||
| 40 | + | while(val >= 1000) do | |
| 41 | + | begin | |
| 42 | + | Dec(val, 1000); | |
| 43 | + | Inc(aChr); | |
| 44 | + | empty := false; | |
| 45 | + | end; | |
| 46 | + | ||
| 47 | + | if empty then | |
| 48 | + | begin | |
| 49 | + | achr := 16; | |
| 50 | + | end; | |
| 51 | + | ||
| 52 | + | Digit[0] := aChr; | |
| 53 | + | ||
| 54 | + | // Hundreds | |
| 55 | + | aChr := 0; | |
| 56 | + | ||
| 57 | + | while(val > = 100) do | |
| 58 | + | begin | |
| 59 | + | Dec(val, 100); | |
| 60 | + | Inc(aChr); | |
| 61 | + | empty := false; | |
| 62 | + | end; | |
| 63 | + | ||
| 64 | + | if empty then | |
| 65 | + | begin | |
| 66 | + | achr := 16; | |
| 67 | + | end; | |
| 68 | + | ||
| 69 | + | Digit[1] := aChr; | |
| 70 | + | ||
| 71 | + | // Tens | |
| 72 | + | aChr : = 0; | |
| 73 | + | ||
| 74 | + | while(val > = 10) do | |
| 75 | + | begin | |
| 76 | + | Dec(val, 10); | |
| 77 | + | Inc(aChr); | |
| 78 | + | empty := false; | |
| 79 | + | end; | |
| 80 | + | ||
| 81 | + | if empty then | |
| 82 | + | begin | |
| 83 | + | aChr := 16; | |
| 84 | + | end; | |
| 85 | + | ||
| 86 | + | Digit[2] := aChr; | |
| 87 | + | ||
| 88 | + | // Ones | |
| 89 | + | aChr := 0; | |
| 90 | + | ||
| 91 | + | while(val >= 1) do | |
| 92 | + | begin | |
| 93 | + | Dec(val); | |
| 94 | + | Inc(aChr); | |
| 95 | + | end; | |
| 96 | + | ||
| 97 | + | Digit[3] := aChr; | |
| 98 | + | end; | |
| 99 | + | ``` | |
| 100 | + | ||
| 101 | + | ### Hexadecimal output | |
| 102 | + | ||
| 103 | + | If you want hexadecimal output, you can do it this way, since only **shift'' and**and''' operations are needed, which the AVR can do very quickly. | |
| 104 | + | ||
| 105 | + | ``` pascal | |
| 106 | + | Digit[0] := MyValue shr 12; | |
| 107 | + | Digit[1] := MyValue shr 8 and %1111; | |
| 108 | + | Digit[2] := MyValue shr 4 and %1111; | |
| 109 | + | Digit[3] := MyValue and %1111; | |
| 110 | + | ``` | |
| 111 | + | ||
| 112 | + | ### Call | |
| 113 | + | ||
| 114 | + | With the call to **IntToDigit** values are assigned to Digit\[\], which can then be output on a 7-segment display. | |
| 115 | + | ||
| 116 | + | ``` pascal | |
| 117 | + | MyValue := 1234; // Assign a value | |
| 118 | + | IntToDigit(MyValue); // The digits array gets values | |
| 119 | + | ``` | |
| 120 | + | ||
| 121 | + | ### Output | |
| 122 | + | ||
| 123 | + | The following is suitable for output to a 7-segment display, since you do not want to sacrifice 32 AVR pins, if any. | |
| 124 | + | ||
| 125 | + | - Via 4 shift registers | |
| 126 | + | - Multiplex, 12 pins are used for this, if you also connect the decimal point. | |
| 127 | + | - Shift register and multiplex. | |
| 128 | + | ||
| 129 | + | See also: | |
| 130 | + | ||
| 131 | + | - [[AVR Embedded Tutorial - Multiplex|Multiplex]] - Multiplex based on a 4-fold seven-segment display. | |
| 132 | + | - [[AVR Embedded Tutorial - Shiftregister|Shift registers]] - How do I control shift registers? | |
| 133 | + | ||
| 134 | + | # See also | |
| 135 | + | ||
| 136 | + | - [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview | |
| 137 | + | ||
| 138 | + | --- | |
| 139 | + | *From the Free Pascal wiki, page "AVR Embedded Tutorial - Int to digits", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 140 | + | Category: AVR | |
| 141 | + | Category: Arduino | |
| 142 | + | Category: Embedded | |
| 143 | + | Category: Tutorials |
