XMEGA and HD44780 LCD
Character LCD are one of the easiest and cheapest way of adding output to a microcontroller system. The world of character LCDs has mainly standarized on HD44780 controller chip, which was designed to be interfaced with the rest of the system by a parallel bus but today simple bit-banging does the job.
One of the obstacles to using HD44780 with XMEGA are different supply voltages. Displays usually require 5V, while XMEGA is 3.3V-only. The HD44780 controller will happily run from 3.3V but the display matrix itself requires higher voltage to move crystals around. 5V displays will not have enough contrast at lower voltage to show anything. There are some HD44780 displays that run at 3.3V but they are not available in all shapes, sizes and colors.
There are ways to run the display at 3.3V and generate bias voltage separately but they require extra components. For one of my designs I opted for separate supply voltages for the LCD and rest of the system.
The display is centrally located in the schematic. All data lines go directly to the XMEGA. There are two separate voltage regulators (IC2, IC6) and two jumpers (solder bridges) to select a voltage for the display. To use 5V - IC6 has to be placed, J1 not soldered and J2 soldered in 2-3 position. To use 3.3V only - IC6 is not placed, J1 is soldered and J2 is soldered in 1-2 position. I had to use the first option. 3.3V signals from the MCU are correctly received by display's 5V logic. LCD's RW line is permanently grounded so the display can never output 5V to data lines. Without being able to read the busy flag from the display software has to use very relaxed timings so that the display always has enough time to process the commands.
Software
I have based my driver on this library. The main modifications are of course - different pin control macros for XMEGA, extra characters and mostly important - it is not busy waiting!. Well... it is very little busy waiting :)
This driver has a transmit buffer that can be loaded any time from main application context (main loop) without any delays. The transmit buffer is then being transmitted from a timer interrupt so even though the display is a "slow" device - it does not block the whole program. The only ugly part is a small 50µs delay in interrupt handler between outputting two nibbles but that could be easily improved by implementing a simple finite (2) state machine.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Driver - API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
Driver - internals
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
|
I release the code into public domain.