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