1 | /*****************************************************
|
2 | Project : SPEEDOMETER
|
3 | Version : 1.0
|
4 | Comments: Peter Reinisch
|
5 |
|
6 |
|
7 | Chip type : ATmega8515
|
8 | Program type : Application
|
9 | Clock frequency : 8.000000 MHz 64MS
|
10 | Memory model : Small
|
11 | External SRAM size : 0
|
12 | Data Stack size : 128
|
13 |
|
14 | Compiled with CodeVisionAVR C cross-compiler.
|
15 | *****************************************************/
|
16 | #include <mega8515.h>
|
17 |
|
18 | // Alphanumeric LCD Module functions
|
19 | #include <alcd.h>
|
20 |
|
21 | // Standard library functions (itoa, ftoa etc.)
|
22 | #include <stdlib.h>
|
23 |
|
24 | // Delay functions
|
25 | #include <delay.h>
|
26 |
|
27 | // Nicknames for port pins
|
28 | #define PLUS_KEY PINC.0
|
29 | #define MINUS_KEY PINC.1
|
30 | #define ENTER_KEY PINC.2
|
31 | #define DIA_KEY PINC.3
|
32 | #define SPEED_PORT PORTC.7
|
33 |
|
34 | // Nicknames for delays, Etc.
|
35 | #define DEBOUNCE_DELAY 80
|
36 | #define REFRESH_DELAY 200
|
37 | #define SPEED_MULTIPLIER 292
|
38 | #define PULSE_TURN 12
|
39 |
|
40 | // Global variables
|
41 | unsigned char circ=0; // Calculated circumference
|
42 | unsigned int dcm=0; // Distance covered in cm (modul 100m)
|
43 | unsigned long speed=0; // Calculated speed
|
44 | unsigned int trip=0; // Trip distance (0.1 Km)
|
45 | unsigned long distance=0; // Total distance (0.1 Km)
|
46 | unsigned char overflow=0; // Timer1 overflow; for long delays
|
47 | unsigned long count=0; // Current Timer1 count
|
48 | unsigned long lastcount=0; // Last Timer1 count
|
49 |
|
50 | // Some messages
|
51 | flash char msg_saving[]="Saving Data...";
|
52 | flash char msg_circ[]="Circumference:";
|
53 | flash char msg_dia[]="Enter Circum";
|
54 | flash char msg_cm[]=" cm";
|
55 |
|
56 | // Temporary variables
|
57 | char tempstr[10];
|
58 |
|
59 | // EEPROM saved variables
|
60 | // Note that these variables are not written periodically.
|
61 | // The diameter is written only when the diameter is changed from the menu.
|
62 | // The odometer reading is saved only when the main power to the system is cut-off.
|
63 | eeprom unsigned long int save_odometer=0;
|
64 | eeprom unsigned long int save_trip=0;
|
65 | eeprom unsigned char save_circ=0;
|
66 | eeprom unsigned long int save_dcm=0;
|
67 |
|
68 | // Timer 0 overflow interrupt service routine
|
69 | // Current speed of the vehicle if no input pulse
|
70 | // arrives within the expected period.
|
71 | interrupt [TIM0_OVF] void timer0_ovf_isr(void)
|
72 | {
|
73 | count=overflow*65536+TCNT1;
|
74 | if(count>lastcount)
|
75 | {
|
76 | speed=(unsigned int) ((circ/PULSE_TURN)*SPEED_MULTIPLIER)/count;
|
77 | }
|
78 | }
|
79 |
|
80 | // Timer 1 overflow interrupt service routine
|
81 | interrupt [TIM1_OVF] void timer1_ovf_isr(void)
|
82 | {
|
83 | overflow++;
|
84 | }
|
85 |
|
86 | // External Interrupt 0 service routine
|
87 | // A pulse is recieved & this function gets called..
|
88 | interrupt [EXT_INT0] void ext_int0_isr(void)
|
89 | {
|
90 | // Increment dcm modul 10000 (0.1 Km)
|
91 | dcm=dcm+(circ/PULSE_TURN);
|
92 | if(dcm>10000)
|
93 | {
|
94 | dcm=dcm-10000;
|
95 | // For every 10000 cm, trip and distance are incremented by 1 (0.1 Km)
|
96 | trip++;
|
97 | distance++;
|
98 | }
|
99 | count=overflow*65536+TCNT1;
|
100 | lastcount=count; // Save the current count (for automatic damping of speed by Timer0)
|
101 |
|
102 | // Reset the timer
|
103 | TCNT1=0;
|
104 | overflow=0;
|
105 |
|
106 | speed=(unsigned int)((circ/PULSE_TURN)*SPEED_MULTIPLIER)/count;
|
107 | }
|
108 |
|
109 | // External Interrupt 1 service routine
|
110 | // This interrupt is triggered automatically only
|
111 | // when the main power to the circuit is removed (turning off the vehicle).
|
112 | interrupt [EXT_INT1] void ext_int1_isr(void)
|
113 | {
|
114 | // Save odometer reading in EEPROM
|
115 | save_odometer=distance;
|
116 | save_trip=trip;
|
117 | save_dcm=dcm;
|
118 | lcd_clear();
|
119 | lcd_putsf(msg_saving); // "Saving Data..."
|
120 | delay_ms(1000);
|
121 | }
|
122 |
|
123 | void main(void)
|
124 | {
|
125 |
|
126 | // Input/Output Ports initialization
|
127 | // Port A initialization
|
128 | PORTA=0x00;
|
129 | DDRA=0x00;
|
130 |
|
131 | // Port B initialization
|
132 | PORTB=0x00;
|
133 | DDRB=0x00;
|
134 |
|
135 | // Port C initialization
|
136 | PORTC=0x00;
|
137 | DDRC=0x80;
|
138 |
|
139 | // Port D initialization
|
140 | PORTD=0x00;
|
141 | DDRD=0x00;
|
142 |
|
143 | // Port E initialization
|
144 | PORTE=0x00;
|
145 | DDRE=0x00;
|
146 |
|
147 | // Timer/Counter 0 initialization
|
148 | // Clock source: System Clock
|
149 | // Clock value: 7.813 kHz
|
150 | // Mode: Normal top=FFh
|
151 | // OC0 output: Disconnected
|
152 | TCCR0=0x05;
|
153 | TCNT0=0x00;
|
154 | OCR0=0x00;
|
155 |
|
156 | // Timer/Counter 1 initialization
|
157 | // Clock source: System Clock
|
158 | // Clock value: 7.813 kHz
|
159 | // Mode: Normal top=FFFFh
|
160 | // OC1A output: Discon.
|
161 | // OC1B output: Discon.
|
162 | // Noise Canceler: Off
|
163 | // Input Capture on Falling Edge
|
164 | // Timer 1 Overflow Interrupt: On
|
165 | // Input Capture Interrupt: Off
|
166 | // Compare A Match Interrupt: Off
|
167 | // Compare B Match Interrupt: Off
|
168 | TCCR1A=0x00;
|
169 | TCCR1B=0x05;
|
170 | TCNT1H=0x00;
|
171 | TCNT1L=0x00;
|
172 | ICR1H=0x00;
|
173 | ICR1L=0x00;
|
174 | OCR1AH=0x00;
|
175 | OCR1AL=0x00;
|
176 | OCR1BH=0x00;
|
177 | OCR1BL=0x00;
|
178 |
|
179 | // External Interrupt(s) initialization
|
180 | // INT0: On ; Input Pulses
|
181 | // INT0 Mode: Falling Edge
|
182 | // INT1: On ; Save the current odometer reading
|
183 | // INT1 Mode: Falling Edge
|
184 | // INT2: Off ; Not used
|
185 | GICR|=0xC0;
|
186 | MCUCR=0x0A;
|
187 | EMCUCR=0x00;
|
188 | GIFR=0xC0;
|
189 |
|
190 | // Timer(s)/Counter(s) Interrupt(s) initialization
|
191 | TIMSK=0x82;
|
192 |
|
193 | // Analog Comparator initialization
|
194 | // Analog Comparator: Off
|
195 | // Analog Comparator Input Capture by Timer/Counter 1: Off
|
196 | ACSR=0x80;
|
197 |
|
198 | // LCD module initialization
|
199 | // Connections are specified in the
|
200 | // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
|
201 | // RS - PORTA Bit 0
|
202 | // RD - PORTA Bit 2
|
203 | // EN - PORTA Bit 1
|
204 | // D4 - PORTA Bit 4
|
205 | // D5 - PORTA Bit 5
|
206 | // D6 - PORTA Bit 6
|
207 | // D7 - PORTA Bit 7
|
208 | // Characters/line: 16/2
|
209 | lcd_init(16);
|
210 |
|
211 | //Read saved odometer reading
|
212 | distance=save_odometer;
|
213 | trip=save_trip;
|
214 | dcm=save_dcm;
|
215 |
|
216 | //Read saved diameter
|
217 | circ=save_circ;
|
218 | lcd_putsf(msg_circ); // "Circumference:"
|
219 | itoa(circ, tempstr);
|
220 | lcd_gotoxy(3,1);
|
221 | lcd_puts(tempstr);
|
222 | lcd_putsf(msg_cm); // " cm"
|
223 | delay_ms(1000);
|
224 |
|
225 | // Global enable interrupts
|
226 | #asm("sei")
|
227 |
|
228 | while(1)
|
229 | {
|
230 | lcd_clear();
|
231 | if(speed<1)
|
232 | speed=0;
|
233 |
|
234 | // Convert speed to string
|
235 | ftoa(speed, 0, tempstr);
|
236 | // Display it on the screen
|
237 | lcd_gotoxy(0,0);
|
238 | lcd_puts(tempstr);
|
239 | lcd_putsf("Km/h");
|
240 |
|
241 |
|
242 | // Convert trip distance (in Km) to string
|
243 | ftoa((float)trip/10, 1, tempstr);
|
244 | // Display it on the screen
|
245 | lcd_gotoxy(0,1);
|
246 | lcd_puts(tempstr);
|
247 | //lcd_putsf("Km");
|
248 |
|
249 | // Convert total distance (in Km) to string
|
250 | ftoa((float)distance/10, 1, tempstr);
|
251 | // Display it on the screen
|
252 | lcd_gotoxy(8,1);
|
253 | lcd_puts(tempstr);
|
254 | delay_ms(REFRESH_DELAY);
|
255 |
|
256 | // If the Trip Rest switch is pressed for more then 500ms, clear the trip meter
|
257 | if(ENTER_KEY==0)
|
258 | {
|
259 | delay_ms(500);
|
260 | if(ENTER_KEY==0)
|
261 | {
|
262 | trip=0;
|
263 | }
|
264 | }
|
265 |
|
266 | // If the Change Diamter key is pressed for more than a second,
|
267 | if(DIA_KEY==0)
|
268 | {
|
269 | delay_ms(1000);
|
270 | if(DIA_KEY==0)
|
271 | {
|
272 | while (1)
|
273 | {
|
274 | lcd_clear();
|
275 | lcd_putsf(msg_dia);
|
276 | itoa(circ,tempstr);
|
277 | lcd_gotoxy(3,1);
|
278 | lcd_puts(tempstr);
|
279 | lcd_putsf(msg_cm);
|
280 |
|
281 | if(PLUS_KEY==0 && circ<250)
|
282 | {
|
283 | delay_ms(DEBOUNCE_DELAY);
|
284 | if(PLUS_KEY==0)
|
285 | circ=circ+1;
|
286 | } else
|
287 | if(MINUS_KEY==0 && circ>1)
|
288 | {
|
289 | delay_ms(DEBOUNCE_DELAY);
|
290 | if(MINUS_KEY==0)
|
291 | circ=circ-1;
|
292 | } else
|
293 | if(ENTER_KEY==0)
|
294 | {
|
295 | delay_ms(DEBOUNCE_DELAY);
|
296 | if(ENTER_KEY==0)
|
297 | {
|
298 | lcd_clear();
|
299 | lcd_putsf(msg_circ); // "Circumference:"
|
300 | itoa(circ, tempstr);
|
301 | lcd_gotoxy(3,1);
|
302 | lcd_puts(tempstr);
|
303 | lcd_putsf(msg_cm); // " cm"
|
304 | // Save in EEPROM
|
305 | save_circ=circ;
|
306 | delay_ms(1000);
|
307 | break;
|
308 | }
|
309 | }
|
310 | else
|
311 | delay_ms(DEBOUNCE_DELAY);
|
312 | };
|
313 | }
|
314 | }
|
315 |
|
316 | };
|
317 |
|
318 | }
|