STM32F4 ADC und USART Interrupt

#3155486
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ß.
#3156371
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren