Forum: Mikrocontroller und Digitale Elektronik STM32F4 ADC und USART Interrupt


von Ahmet G. (korkmaz)


Lesenswert?

Hallo,

ich beschäftige mich zur Zeit mit dem STM32F407VG und betreibe einen 
ADC, der Werte Analog einließt und diese dann über UART verschickt.

Funktionieren tut das ganze eigentlich ganz gut, jedoch ist ja bekannt 
das das Senden zeitlich über UART um ein vielfaches größer ist als das 
Konvertieren eines Analogwertes.

Nun habe ich das Ganze etwas umgebaut und für den ADC und USART eine 
Interruptroutine verwendet. Ich möchte so vorgehen das der ADC einen 
Wert Puffert, dieser dann über USART versendet wird , in der 
Zwischenzeit des sendens schreibt der ADC den Wert in einen zweiten 
Puffer. Ist der erste Puffer versendet, versendet USART den zweiten und 
der ADC liest in der zwischenzeit einen Wert in Puffer eins wieder ein.

Programmiert habe ich das ganze so:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_gpio.h"
3
#include "stm32f4xx_rcc.h"
4
#include "stm32f4xx_adc.h"
5
#include "stm32f4xx_usart.h"
6
#include "misc.h"
7
8
9
void interruptConfig();
10
void adcConfig();
11
void usartConfig();
12
void ledConfig();
13
14
15
typedef struct{
16
  uint16_t buffer;
17
  int lock;
18
}bufferStruct;
19
20
bufferStruct bufferOne;
21
bufferStruct bufferTwo;
22
23
24
int main(void)
25
{
26
  ledConfig();
27
  usartConfig();
28
  adcConfig();
29
30
  ADC_SoftwareStartConv(ADC3);
31
32
33
  ADC_ITConfig(ADC3, ADC_IT_EOC, ENABLE);
34
  USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
35
36
37
    while(1)
38
    {
39
    }
40
}
41
42
void ADC_IRQHandler()
43
{
44
  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
45
46
  if(bufferOne.lock== 0)
47
  {
48
    bufferOne.buffer =ADC_GetConversionValue(ADC3);
49
    bufferOne.lock = 1;
50
  }
51
  else if(bufferTwo.lock == 0)
52
  {
53
    bufferTwo.buffer = ADC_GetConversionValue(ADC3);
54
    bufferTwo.lock = 1;
55
  }
56
  ADC_ClearFlag(ADC3, ADC_FLAG_EOC);
57
}
58
59
60
void USART3_IRQHandler()
61
{
62
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
63
64
  if(bufferOne.lock== 1)
65
  {
66
    USART_SendData(USART3, (uint8_t) bufferOne.buffer );
67
    bufferOne.lock = 0;
68
  }
69
  else if(bufferTwo.lock == 1)
70
  {
71
    USART_SendData(USART3, (uint8_t) bufferTwo.buffer );
72
    bufferTwo.lock = 0;
73
  }
74
  USART_ClearFlag(USART3, USART_IT_TXE);
75
}
76
77
78
79
80
void ledConfig()
81
{
82
  GPIO_InitTypeDef led_gpio;
83
84
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
85
86
  led_gpio.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
87
  led_gpio.GPIO_Mode = GPIO_Mode_OUT;
88
  led_gpio.GPIO_OType = GPIO_OType_PP;
89
  led_gpio.GPIO_Speed = GPIO_Speed_50MHz;
90
  led_gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
91
  GPIO_Init(GPIOD, &led_gpio);
92
}
93
94
void adcConfig()
95
{
96
  ADC_InitTypeDef       ADC_InitStructure;
97
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
98
    GPIO_InitTypeDef      GPIO_InitStructure;
99
  NVIC_InitTypeDef    NVIC_adc;
100
101
102
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOC, ENABLE);
103
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
104
105
106
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
107
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
108
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
109
  GPIO_Init(GPIOC, &GPIO_InitStructure);
110
111
112
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
113
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
114
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
115
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
116
  ADC_CommonInit(&ADC_CommonInitStructure);
117
118
119
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
120
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
121
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
122
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
123
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
124
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
125
  ADC_InitStructure.ADC_NbrOfConversion = 1;
126
  ADC_Init(ADC3, &ADC_InitStructure);
127
128
129
  ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_3Cycles);
130
131
  ADC_Cmd(ADC3, ENABLE);
132
133
  NVIC_adc.NVIC_IRQChannel = ADC_IRQn;
134
  NVIC_adc.NVIC_IRQChannelCmd = ENABLE;
135
  NVIC_adc.NVIC_IRQChannelPreemptionPriority = 0x0F;
136
  NVIC_adc.NVIC_IRQChannelSubPriority = 0x01;
137
  NVIC_Init(&NVIC_adc);
138
139
}
140
141
void usartConfig()
142
{
143
    GPIO_InitTypeDef GPIO_InitStructure;
144
    USART_InitTypeDef USART_InitStructure;
145
    NVIC_InitTypeDef  NVIC_usart;
146
147
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
148
149
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
150
151
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
152
153
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
154
155
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
156
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
157
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
158
159
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
160
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
161
    GPIO_Init(GPIOC, &GPIO_InitStructure);
162
163
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
164
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
165
    GPIO_Init(GPIOC, &GPIO_InitStructure);
166
167
    USART_InitStructure.USART_BaudRate = 11500;
168
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
169
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
170
    USART_InitStructure.USART_Parity = USART_Parity_No;
171
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
172
    USART_InitStructure.USART_Mode = USART_Mode_Tx;
173
174
175
    USART_Init(USART3, &USART_InitStructure);
176
177
178
    USART_Cmd(USART3, ENABLE);
179
180
    NVIC_usart.NVIC_IRQChannel = USART3_IRQn;
181
    NVIC_usart.NVIC_IRQChannelCmd= ENABLE;
182
    NVIC_usart.NVIC_IRQChannelPreemptionPriority = 0x01;
183
    NVIC_usart.NVIC_IRQChannelSubPriority = 0x01;
184
    NVIC_Init(&NVIC_usart);
185
}

Nun habe ich das Problem, wenn ich den Interrupt für den ADC als erstes 
aktiviere komme ich nur noch in die Interrupt Routine des ADC´s aber nie 
in die des USART´s. Ich möchte im Prinzip immer prüfen, das wenn das TX 
Register leer ist das ein Interrupt ausgelöst wird und etwas versendet 
wird, ist wiederum eine Konvertierung des ADC´s fertig so gucke ich ob 
noch ein Puffer frei ist und speichere diesen zwischen.

Was mache ich Falsch?

Gruß.

von Uwe B. (derexponent)


Lesenswert?

Hi Ahmet Gee,

>Was mache ich Falsch?

der "USART_IT_TXE"-Interrupt bekommst du, wenn das senden eines Bytes 
per UART fertig ist...du sendest aber nie ein Byte
(das senden passiert ja auch im Interrupt)

versuche mal kurz vor der While(1) einen "Dummy-Wert"
zu senden um damit die ganze Kette anzutriggern

nachtrag...

das ganze wird trotzdem stehenbleiben

weil des senden eines wertes länger dauert
als das wandeln von zwei werten
und dann wird der ADC nicht mehr getriggert
(und in folge dann der UART nicht mehr)

mach das ganze entweder per DMA oder im Injected-Group-Mode
(oder wandle zyklisch und frag ab ob das senden fertig ist)

oder noch eine Möglichkeit :

1. Puffer = Dummy-Wert; // Dummy Wert
   UART = Puffer; // Puffer senden

2. Innerhalb vom UART-Interrupt :
   UART = Puffer;
   Trigger ADC;

3. Innerhalb vom ADC-Interrupt :
   Puffer = ADC;


Gruss Uwe

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.