Hallo zusammen, ich würde gerne eine Zeitmessung mit meinen XMEGA32E5 realisieren, um eine Distanzmessung auszuwerten. Die Distanzmessung soll mit einem Ultraschall Modul realisiert werden. Ich arbeite bei dem XMEGA mit 32MHz und möchte Zeiten von 10µs bis 200ms messen http://www.mikrocontroller.net/attachment/218122/HC-SR04_ultraschallmodul_beschreibung_3.pdf Leider ist mir nicht ganz klar wie ich diese Messung am genausten realisiere. 1.Möglichkeit: Steigende Flanke bzw logisches high mit Interrupt detektieren und Timer starten Fallende Flanke bzw logisches low mit Interrupt detektieren und Timerwert auslesen 2.Möglichkeit: Nutzen der Capture channes des XMEGA's hierzu wird in Datenblatt unter anderen eine Pulsweitenmessung erwähnt, die ich jedoch noch nicht ganz verstanden habe. Hat noch jemand eine andere Idee bzw. schon mal etwas ähnliches realisiert? (Ich weiß das diese Module für den Arduino gedacht sind, möchte aber keinen Arduino nutzen)
2. Möglichkeit. Das kann der XMEGA besonders komfortabel. Hier mal ein Beispielsetup. Parallel dazu muss der betreffende Interrupt behandelt werden, um die Messwerte abzuholen. Jede steigende Flanke startet die Messung, die fallende stoppt und trägt das Messergebnis in das Capture-Register ein.
1 | ;-------------------------- |
2 | ;TimerC5 |
3 | ;Debug pulse capturing |
4 | ldi Temp, 0xFF |
5 | ldi TempH, 0xFF |
6 | sts TCC5_PER, Temp |
7 | sts TCC5_PER+1, TempH |
8 | |
9 | ldi Temp, TC45_CCBMODE_CAPT_gc | TC45_CCAMODE_CAPT_gc ;capture B and capture A enabled |
10 | sts TCC5_CTRLE, Temp |
11 | ldi Temp, TC45_EVACT_PWF_gc | TC45_EVSEL_CH0_gc ;Pulse-width / Frequency Capture, Event Channel 0 |
12 | sts TCC5_CTRLD, Temp |
13 | |
14 | ldi Temp, 0b00000110 ;Prescaler 256 |
15 | sts TCC5_CTRLA, Temp |
16 | ldi Temp, TC45_CCBINTLVL_LO_gc ;Low Level compare interrupt enabled |
17 | sts TCC5_INTCTRLB, Temp |
18 | |
19 | |
20 | ;setup EventSystem |
21 | ldi Temp, 0b01010110 ;PortA6 as EventCh0 input |
22 | sts EVSYS_CH0MUX, Temp |
Ich hab mal versucht die Sache in C zu übersetzen
1 | void initTimer5AsCapture(); |
2 | {
|
3 | TCC5.PER = 0xFFFF; |
4 | |
5 | TCC5.CTRLE = TC45_CCBMODE_CAPT_gc |
6 | | TC45_CCAMODE_CAPT_gc; |
7 | |
8 | TCC5.CTRLD = TC45_EVACT_PWF_gc |
9 | | TC45_EVSEL_CH0_gc; |
10 | |
11 | TCC5.CTRLA = TC45_CLKSEL_DIV256_gc; |
12 | |
13 | TCC5.INTCTRLB = TC45_CCBINTLVL_LO_gc; |
14 | |
15 | EVSYS.CH0MUX = EVSYS_CHMUX_PORTA_PIN6_gc; |
16 | }
|
oder für Timer 4 etwas abgewandelt:
1 | void initTimer4AsCapture(); |
2 | {
|
3 | TCC5.PER = 0xFFFF; |
4 | |
5 | TCC4.CTRLA = TC4_SYNCHEN_bm |
6 | | TC4_EVSTART_bm |
7 | | TC45_CLKSEL_DIV1_gc; |
8 | |
9 | TCC4.CTRLD = TC45_EVACT_PWF_gc |
10 | | TC45_EVSEL_CH0_gc; |
11 | |
12 | TCC4.CTRLE = TC45_CCAMODE_CAPT_gc; |
13 | |
14 | TCC4.INTCTRLB = TC45_CCAINTLVL_LO_gc; |
15 | |
16 | EVSYS.CH0MUX = EVSYS_CHMUX_PORTA_PIN0_gc; |
17 | }
|
Im Interrupt muss ich dann nur noch das richtige Register auslesen und in dem steht dann der Wert für die Zeit?
Der Code oben hat noch ein oder zwei kleine Probleme. Falls jemand ein ähnliches Problem hat könnte ihm mein fertiger Code vielleicht helfen. (Das Programm ist für das XMEGA-E5 Xplained Board geschrieben)
1 | #define F_CPU 32000000
|
2 | #include <avr/io.h> |
3 | #include "clksys_driver.h" |
4 | #include <asf.h> |
5 | |
6 | #include <stdlib.h> |
7 | |
8 | void clock32M(void); |
9 | void initTimer4AsCapture(void); |
10 | void initTimer5AsCapture(void); |
11 | |
12 | |
13 | |
14 | volatile uint16_t timer4_value = 0; |
15 | volatile uint8_t timer4_Flag = 0; |
16 | volatile uint16_t timer5_value = 0; |
17 | volatile uint8_t timer5_Flag = 0; |
18 | |
19 | |
20 | /*! Channel B Compare or Capture Interrupt
|
21 | *
|
22 | * This function handles the Channel B Compare or Capture Interrupt
|
23 | *
|
24 | */
|
25 | ISR (TCC4_CCB_vect) |
26 | {
|
27 | timer4_Flag = 1; |
28 | timer4_value = TCC4.CCB; |
29 | }
|
30 | |
31 | |
32 | /*! Channel B Compare or Capture Interrupt
|
33 | *
|
34 | * This function handles the Channel B Compare or Capture Interrupt
|
35 | *
|
36 | */
|
37 | ISR (TCC5_CCB_vect) |
38 | {
|
39 | timer5_Flag = 1; |
40 | timer5_value = TCC5.CCB; |
41 | }
|
42 | |
43 | void initTimer4AsCapture() |
44 | {
|
45 | TCC4.PER = 0xFFFF; |
46 | |
47 | TCC4.CTRLA = TC4_SYNCHEN_bm |
48 | | TC4_EVSTART_bm |
49 | | TC45_CLKSEL_DIV64_gc; |
50 | |
51 | TCC4.CTRLD = TC45_EVACT_PWF_gc |
52 | | TC45_EVSEL_CH0_gc; |
53 | |
54 | TCC4.CTRLE = TC45_CCAMODE_CAPT_gc |
55 | | TC45_CCBMODE_CAPT_gc; |
56 | |
57 | TCC4.INTCTRLB = TC45_CCBINTLVL_MED_gc; |
58 | |
59 | PMIC.CTRL |= PMIC_MEDLVLEN_bm; |
60 | |
61 | EVSYS.CH0MUX = EVSYS_CHMUX_PORTA_PIN0_gc; |
62 | }
|
63 | |
64 | |
65 | void initTimer5AsCapture() |
66 | {
|
67 | TCC5.PER = 0xFFFF; |
68 | |
69 | TCC5.CTRLE = TC45_CCBMODE_CAPT_gc |
70 | | TC45_CCAMODE_CAPT_gc; |
71 | |
72 | TCC5.CTRLD = TC45_EVACT_PWF_gc |
73 | | TC45_EVSEL_CH0_gc; |
74 | |
75 | TCC5.CTRLA = TC5_SYNCHEN_bm |
76 | | TC5_EVSTART_bm |
77 | | TC45_CLKSEL_DIV256_gc; |
78 | |
79 | TCC5.INTCTRLB = TC45_CCBINTLVL_LO_gc; |
80 | |
81 | PMIC.CTRL |= PMIC_LOLVLEN_bm; |
82 | |
83 | EVSYS.CH0MUX = EVSYS_CHMUX_PORTA_PIN0_gc; |
84 | }
|
85 | |
86 | |
87 | /*! Clock initial
|
88 | *
|
89 | * This function initial the 32MHz Clock for the µC
|
90 | *
|
91 | */
|
92 | void clock32M(void) |
93 | {
|
94 | /* Enable internal 32 MHz ring oscillator and wait until it's
|
95 | * stable. Set the 32 MHz ring oscillator as the main clock source.
|
96 | * Then disable the other oscillators.
|
97 | */
|
98 | CLKSYS_Enable( OSC_RC32MEN_bm ); |
99 | do {} while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 ); |
100 | CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc ); |
101 | CLKSYS_Disable( OSC_RC2MEN_bm | OSC_RC32KEN_bm ); |
102 | }
|
103 | |
104 | int main(void) |
105 | {
|
106 | long double distance4 = 0; |
107 | long double distance5 = 0; |
108 | uint32_t d4 = 0; |
109 | uint32_t d5 = 0; |
110 | uint8_t count = 0; |
111 | char buf4[5]; |
112 | char buf5[5]; |
113 | |
114 | cli(); |
115 | |
116 | clock32M(); |
117 | initTimer4AsCapture(); |
118 | initTimer5AsCapture(); |
119 | |
120 | sei(); |
121 | |
122 | PORTA.DIRSET = PIN1_bm; // Ausgang |
123 | PORTA.DIRCLR = PIN0_bm; // Eingang |
124 | |
125 | PORTA.OUTSET = PIN1_bm; |
126 | |
127 | board_init(); |
128 | gfx_mono_init(); |
129 | |
130 | _delay_ms(500); |
131 | |
132 | while (true) |
133 | {
|
134 | |
135 | PORTA.OUTCLR = PIN1_bm; |
136 | _delay_us(20); |
137 | PORTA.OUTSET = PIN1_bm; |
138 | |
139 | while(!timer4_Flag || !timer5_Flag){} |
140 | timer4_Flag = 0; |
141 | timer5_Flag = 0; |
142 | |
143 | distance4 = ((64*(long double)timer4_value)/64000)*343; |
144 | distance5 = ((256*(long double)timer5_value)/64000)*343; |
145 | |
146 | count ++; |
147 | |
148 | d4 += distance4; |
149 | d5 += distance5; |
150 | |
151 | if (count > 2) |
152 | {
|
153 | count = 0; |
154 | |
155 | d4 = d4/3; |
156 | d5 = d5/3; |
157 | |
158 | itoa(d4,buf4,10); |
159 | itoa(d5,buf5,10); |
160 | |
161 | gfx_mono_draw_string(" mm", 0, 0, &sysfont); |
162 | gfx_mono_draw_string(" mm", 0, 10, &sysfont); |
163 | gfx_mono_draw_string(buf4, 0, 0, &sysfont); |
164 | gfx_mono_draw_string(buf5, 0, 10, &sysfont); |
165 | }
|
166 | |
167 | _delay_ms(200); |
168 | }
|
169 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.