Forum: Mikrocontroller und Digitale Elektronik Fehlermeldung: STM32F107VC / uVision Keil


von Ma B. (drumstick)


Lesenswert?

Guten Tag!

Ich arbeite mit dem STM32F107VC, uVision von Keil!

Ich möchte die AD-Wandlung per externer Interrupt einlesen! Nun 
erscheint folgende Fehlermeldung:

Frontego_ARM_2011_MAB.axf:

Error: L6218E: Undefined symbol ADC (referred from main.o).
1
void ADC_IRQHandler(void)
2
{
3
4
    if(EXTI ->  PR & (1 << 18))  // External Interrupt at PortC Pin 4 (ADC)
5
    {
6
    
7
        EXTI    ->  PR |= (1 << 18);        // Reset the Interrupt Flagbit
8
        
9
        if (ADC1->SR & (1 << 1))            // If conversion has finished
10
        {
11
                AD_Val  =   ADC1->DR & 0x0FFF;   // Read AD converted value
12
                ADC1    ->  CR2 |= 1 << 22;     // Start new conversion 
13
        }
14
                
15
        ADWert  =   AD_Val  <<  4;       // AD-Wert auf 8 Bit wandeln
16
        GPIOE   ->  BSRR    =   ADWert;    // AD-Wert an Port E ausgeben
17
        GPIOE   ->  BSRR    |=  0xFF000000;    // Port E Neutralisieren
18
                       
19
        TIM1    ->  CCR1    =   ADC1 ->  DR;  // Compare Register 3; Vergleichsregister mit dem AD-Wert laden    
20
21
    }
22
23
}

Die Vektoren der Interrupts sind doch in den Startup-files definiert? 
Was bedeutet dann diese Meldung??

von Oliver J. (skriptkiddy)


Lesenswert?

versuch mal
1
void ADC_IRQHandler(void) __irq{
2
3
....
4
5
}

von Ma B. (drumstick)


Lesenswert?

Hallo!

danke für die Antwort, hat aber nichts gebracht!

Gruss

M.B.

von Matthias K. (matthiask)


Lesenswert?

Anhand des Programmschnippsels nicht zu beantworten! Wahrscheinlich 
fehlt irgendwo ein include...

von ... (Gast)


Lesenswert?

Matthias K. schrieb:
> Wahrscheinlich fehlt irgendwo ein include...

Eher fehlt irgendwo eine "1". In der Fehlermeldung ist von "ADC" die 
Rede, im Codeschnipsel steht "ADC1".

von Ma B. (drumstick)


Lesenswert?

Hallo!

Danke für die Antworten! Es fehlte ein Include. Was aber seltsam ist, 
die Externe Interrupt EXTI0, EXTI1 usw. funktionieren, ausser der ADC 
Interrupt. Und ich weiss nicht wieso. Den ADC Interrupt habe ich auf 
enable gesetzt!??
1
#define     ADCCONTROLLREG1         0x000001A0                                                                                            /**/
2
#define     ADCCONTROLLREG2         0x001E0003                                                                                            /**/
3
#define     SAMPTIMEREG1            0x00005000                                                                                            /**/
4
#define     SAMPTIMEREG2            0x00000000                                                                                            /**/
5
#define     REGUSEQUREG1            0x00000000                                                                                            /**/
6
#define     REGUSEQUREG2            0x00000000                                                                                            /**/
7
#define     REGUSEQUREG3            0x0000000E 
8
9
#define     INTERMASKREG            0x0004E007                                                                                            /**/
10
#define     FALLTRIGSELECREG        0x0004E007                                                                                            /**/
11
#define     EXINTCONFIGREG1         0x00000333                                                                                            /**/
12
#define     EXINTCONFIGREG4         0x00003330                                                                                            /**/
13
#define     EXINTCONFIGREG2         0x00000002                                                                                            /**/
14
#define     EVENTCONTREG            0X0000004F                                                                                            /**/
15
#define     INTERRUPTSELECT         0X000001C0                                                                                            /**/
16
#define     INTERRUPTSELECT1        0X00000100
17
18
19
20
21
// ADC
22
    ADC1    ->  SQR1        =   REGUSEQUREG1;               // Regular channel 1 conversion
23
    ADC1    ->  SQR2        =   REGUSEQUREG2;               // Clear register
24
    ADC1    ->  SQR3        =   REGUSEQUREG3;               // SQ1 = channel 14
25
    ADC1    ->  SMPR1       =   SAMPTIMEREG1;               // Channel 14 sample time is 55.5 cyc
26
    ADC1    ->  SMPR2       =   SAMPTIMEREG2;               // Clear register
27
    ADC1    ->  CR1         =   ADCCONTROLLREG1;            // Scan mode on
28
    ADC1    ->  CR2         =   ADCCONTROLLREG2;            // Enable external trigger, EXTSEL = SWSTART, Continuous conversion, ADC enable
29
         
30
    ADC1    ->  CR2         |=   1 <<  3  ;                 // Initialize calibration registers
31
    while (ADC1->CR2        &   (1 << 3)) ;                 // Wait for initialization to finish
32
    ADC1     ->  CR2        |=   1 << 2   ;                 // Start calibration
33
    while (ADC1->CR2        &   (1 << 2)) ;                 // Wait for calibration to finish
34
    ADC1    ->  CR2         |=   1 << 22  ;                 // Start first conversion
35
36
37
EXTI    ->  IMR       = INTERMASKREG;                   // Interrupt 13 and 15 are masked 
38
    EXTI    ->  FTSR      = FALLTRIGSELECREG;               // Falling trigger events
39
    AFIO    ->  EXTICR[0] = EXINTCONFIGREG1;                // PortD Pin 14, Pin 13 and Pin 15 are the EXT_Interrupt source
40
    AFIO    ->  EXTICR[1] = EXINTCONFIGREG2;   
41
    AFIO    ->  EXTICR[3] = EXINTCONFIGREG4;                // PortD Pin 14, Pin 13 and Pin 15 are the EXT_Interrupt source
42
    NVIC    ->  ISER[0]   = INTERRUPTSELECT;                // External Interrupt EXTI15_10 are selected
43
    NVIC    ->  ISER[1]   = INTERRUPTSELECT1;                // External Interrupt EXTI15_10 are selected
44
      
45
46
47
48
49
void ADC_IRQHandler(void)
50
{
51
52
    if(EXTI ->  PR & (1 << 18))                              // External Interrupt at PortC Pin 4 (ADC)
53
    {
54
    
55
        EXTI    ->  PR |= (1 << 18);                         // Reset the Interrupt Flagbit
56
        
57
        if (ADC1->SR & (1 << 1))                            // If conversion has finished
58
        {
59
                AD_Val  =   ADC1->DR & 0x0FFF;              // Read AD converted value
60
                ADC1    ->  CR2 |= 1 << 22;                 // Start new conversion 
61
        }
62
                
63
        ADWert  =   AD_Val  <<  4;                          // AD-Wert auf 8 Bit wandeln
64
        GPIOE   ->  BSRR    =   ADWert;                     // AD-Wert an Port E ausgeben
65
        GPIOE   ->  BSRR    |=  0xFF000000;                 // Port E Neutralisieren
66
                       
67
        TIM1    ->  CCR1    =   ADC1 ->  DR;                // Compare Register 3; Vergleichsregister mit dem AD-Wert laden    
68
69
    }
70
}         
71
72
73
74
75
int main (void)         
76
{
77
    
78
    // Subroutienen
79
80
    init();     // Initialisierung: Keine Uebergabewerte
81
    
82
    
83
    // Endlosschlaufe
84
85
    while(1)
86
    {       
87
    }
88
}


Die erste Wandlung wird in der Init gestartet, dies sollte kein Problem 
sein. Die Vektoradresse stimmt auch!? Es müsste doch gehen?!

Vielen Dank und freundliche Grüsse!!


M.B.

von Sven Wagner (Gast)


Lesenswert?

Ist den der ADC schon mit Strom versorgt?
V_DDA (und V_SSA) angeschlossen? ADCCLK auf einen gescheiten Wert 
gestellt?

Grüße
Sven

von Ma B. (drumstick)


Lesenswert?

Hallo!

Ja, die AD Wandlung funktionierte einwandfrei. Bis jetzt hatte ich die 
Wandlung in einer Funktion ausgeführt, die vom Hauptprogramm aufgerufen 
wurde. Jetzt möchte ich aber, dass die kontinuierliche Wandlung einen 
ADC Interrupt auslöst und den Ausgangsport mit dem neuen Wert 
aktuallisiert!

Der Pointer ruft die Interruptroutiene des ADC nie auf, die anderen, 
Externen Interrupts werden ausgeführt!

Zudem muss ich sagen, dass ich ein Demoboard verwende, da ist Speisung 
und Anschlüsse vorhanden und verbunden.


danke und Gruss!

M.B.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Skript Kiddy schrieb:
> versuch mal
>
>
1
> void ADC_IRQHandler(void) __irq{
2
> 
3
> ....
4
> 
5
> }
6
>

beim Cortex-M ist das Schlüsselwort __irq nicht mehr notwendig, da der 
das von Hause aus macht.

von Kurt (Gast)


Lesenswert?

Hast du den ADC-INT eingeschaltet?

von Ma B. (drumstick)


Lesenswert?

ja, Bit 5 von CR1 auf 1 setzen:

Bit 5 EOCIE: Interrupt enable for EOC

This bit is set and cleared by software to enable/disable the End of 
Conversion interrupt.

0: EOC interrupt disabled
1: EOC interrupt enabled. An interrupt is generated when the EOC bit is 
set.


danke und Gruss!

M.B.

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
Noch kein Account? Hier anmelden.