STM32F303 USART in Kombination mit Timer+ADC+DMA der 2te

OP #4739866
Lesenswert?

Hallo,

es geht darum, dass die serielle Kommunikation per UART die ADCs und den 
DMA stört.

Ein Java Programm auf dem PC soll verschiedene Variablen des 
Mikrocontrollers abfragen können. Der uC sendet nur dann etwas, wenn er 
gefragt wird.

Aufbau einer solchen Abfrage:
|STX|Var_Number_Byte_1|Var_Number_Byte_0|'?'|ETX|

(Weil ich mehr als 256 Variablen monitoren können möchte, indexiere ich 
die Variable über 2 Bytes)

Eine Abfrage kann beispielsweise so aussehen:
   2 0                  1     '?'  3


2 -> STX
0 -> MSByte der Variablen Nummer
1 -> LSByte der Variablen Nummer
'?' -> "Computer möchte lesen"
3 -> ETX

hier möchte der Computer den Wert der Variable 01 lesen.
Es kann sich dabei um unterschiedliche Datentypen handeln: Int, UInt, 
Float.
Alle Variablen sind 32bit groß, deshalb werden sie als ein 4 Byte großes 
Packet gesendet und mit einem ETX abgeschlossen.
Das Array "variables" enthält die Adressen der Variablen, die abgefragt 
werden können. Es kann Adressen eines Ints, UInts und Floats enthalten.

Quellcode der seriellen Kommunikation:
1
#define rx_buffer_size 20
2

3
void init_serial(void)
4
{
5
  // config GPIOs
6
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
7

8
    GPIO_InitTypeDef GPIO_InitStructure;
9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
11
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
12
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
13
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
14
    GPIO_Init(GPIOB, &GPIO_InitStructure);
15

16
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_7);
17
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_7);
18

19

20
    // config NVIC
21
    NVIC_InitTypeDef NVIC_InitStructure; //create NVIC structure
22
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
23
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
24
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
25
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
26
  NVIC_Init(&NVIC_InitStructure);
27

28

29
  // config USART1
30
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
31

32
  USART_InitTypeDef USART_Initialisation;
33
  USART_Initialisation.USART_BaudRate = 9600;
34
  USART_Initialisation.USART_WordLength = USART_WordLength_8b;
35
  USART_Initialisation.USART_StopBits = USART_StopBits_1;
36
  USART_Initialisation.USART_Parity = USART_Parity_No;
37
  USART_Initialisation.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
38
  USART_Initialisation.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
39
  /* USART configuration */
40
  USART_Init(USART1, &USART_Initialisation);
41

42
  /* Enable the USART1 Receive interrupt */
43
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
44

45
  /* Enable USART */
46
  USART_Cmd(USART1, ENABLE);
47

48
}
49

50
int variables[20];
51

52
int var_number = 0;
53
int working_variable = 0;
54

55
volatile char rx_buffer[rx_buffer_size];
56

57
volatile int rx_buffer_index = 0;
58
volatile int data_ready = 0;
59

60
char tx_data_byte_0;
61
char tx_data_byte_1;
62
char tx_data_byte_2;
63
char tx_data_byte_3;
64

65
void USART1_IRQHandler(void)
66
{
67
  if (USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
68
    {
69
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);
70

71

72
        switch (USART1->RDR) {
73
      case 2: // STX received
74
        rx_buffer_index = 0;
75
        break;
76
      case 3: // ETX received
77
        data_ready = 1;
78
        break;
79
      default: // usual data
80
        rx_buffer[rx_buffer_index] = USART1->RDR;
81
        rx_buffer_index++;
82
        if(rx_buffer_index >= rx_buffer_size) // prevent rx_buffer overflow
83
        {
84
          rx_buffer_index--;
85
        }
86
        break;
87
    }
88

89
    }
90
}
91

92

93

94

95
void serial_monitor(void)
96
{
97
  if(data_ready == 0) // wenn keine neuen Daten vorhanden oder der Datensatz noch nicht zu Ende übertragen wurde
98
  {
99
    return;
100
  }
101

102

103
  // ermittle, welche Variable gerade angesprochen wird
104
  var_number = (rx_buffer[0] << 8) + rx_buffer[1];
105

106
  working_variable = variables[var_number];
107

108
  if(rx_buffer[2] == 63) // 63 == '?' -> PC will lesen
109
  {
110
    tx_data_byte_3 = ((char *)(working_variable))[0];
111
    tx_data_byte_2 = ((char *)(working_variable))[1];
112
    tx_data_byte_1 = ((char *)(working_variable))[2];
113
    tx_data_byte_0 = ((char *)(working_variable))[3];
114

115

116
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
117
    USART_SendData(USART1, tx_data_byte_3);
118
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
119
    USART_SendData(USART1, tx_data_byte_2);
120
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
121
    USART_SendData(USART1, tx_data_byte_1);
122
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
123
    USART_SendData(USART1, tx_data_byte_0);
124
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
125
    USART_SendData(USART1, 3); // send ETX
126
  }
127

128
  data_ready = 0;
129
}
130

131

132

133
void init_variables(void)
134
{
135
  variables[0] = (int) &tmp_uint;
136
  variables[1] = (int) &tmp_int;
137
  variables[2] = (int) &tmp_float;
138
}

(Die Funktion 'serial_monitor()' wird immer wieder in der main while(1) 
Schleife aufgerufen)

Alles funktioniert soweit. Zusätzlich soll ein Timer für PWM laufen, 
welcher mit seinem TRGO2 zwei ADCs im Dualmode triggert. Die ADCs 
sampeln mehrere Channel, die Sampelwerte werden per DMA abgeholt. 
Nachdem alle Channel gesampelt wurden, soll der DMA1_Channel1_IRQHandler 
aufgerufen werden.

Quellcode der Konfiguration:
1
/**************************************************************************************/
2
void TIM1_Configuration(void)
3
{
4
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
5
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
6
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
7

8
  // Pin configuration
9
  GPIO_InitTypeDef GPIO_InitStructure;
10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
14
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
15
  GPIO_Init(GPIOA, &GPIO_InitStructure);
16

17
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
18
  GPIO_Init(GPIOB, &GPIO_InitStructure);
19

20

21
  // Table 14. STM32F303 alternate function mapping
22
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_6);
23
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_6);
24
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_6);
25
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_6);
26
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_6);
27
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_6);
28

29

30
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
31
  TIM_OCInitTypeDef TIM_OCInitStructure;
32

33

34
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
35
  TIM_TimeBaseStructure.TIM_Period = 1600; // Auto reload value
36
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
37
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
38
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
39
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
40

41
  TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
42

43

44
  TIM_OCStructInit(&TIM_OCInitStructure);
45
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
46
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
47
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
48
  TIM_OCInitStructure.TIM_Pulse = 0;
49
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
50
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
51
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
52
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
53

54

55

56

57
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
58
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
59
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);
60
  TIM_OC5Init(TIM1, &TIM_OCInitStructure);
61
  TIM1->CCR5 = TIM1->ARR-1;
62

63

64
  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
65

66
  /* Automatic Output enable, Break, dead time and lock configuration*/
67
  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Disable;
68
  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable;
69
  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
70
  TIM_BDTRInitStructure.TIM_DeadTime = 7; // (TIM_DeadTime/SystemCoreCLock) = us
71
  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
72
  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
73
  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
74

75
  TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
76

77

78
  TIM_ARRPreloadConfig(TIM1, ENABLE);
79

80
  TIM1->CR1 |= TIM_CR1_ARPE;  // Enable auto reload
81

82

83
  TIM_Cmd(TIM1, ENABLE);
84
  /* TIM1 Main Output Enable */
85
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
86

87
  TIM_SelectOutputTrigger2(TIM1, TIM_TRGO2Source_OC5Ref);
88
}
89
/**************************************************************************************/
90
void NVIC_Configuration(void)
91
{
92
    NVIC_InitTypeDef NVIC_InitStructure;
93

94
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
95
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
96
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
97

98
  /* Enable DMA1 channel1 IRQ Channel */
99
  NVIC_InitStructure.NVIC_IRQChannel = /*11;//*/DMA1_Channel1_IRQn;
100
  NVIC_Init(&NVIC_InitStructure);
101

102

103
}
104
/**************************************************************************************/
105
void ADC_GPIO_Configuration(void)
106
{
107
    GPIO_InitTypeDef GPIO_InitStructure;
108

109
  /* Enable GPIOA and GPIOB Periph clock */
110
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
111

112
  /* ADC Channels configuration */
113
  /* Configure  as analog input */
114
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
115
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
116
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
117
  GPIO_Init(GPIOA, &GPIO_InitStructure);
118

119
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
120
  GPIO_Init(GPIOB, &GPIO_InitStructure);
121
}
122
/**************************************************************************************/
123
void ADC12_DMA_Configuration(void)
124
{
125
    DMA_InitTypeDef DMA_InitStructure;
126

127
  /* Enable DMA1 clock */
128
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
129

130
  /* DMA configuration */
131
  /* DMA1 Channel1 Init Test */
132
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC12_CDR_ADDRESS;
133
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC12DualConvertedValue[0];
134
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
135
  DMA_InitStructure.DMA_BufferSize = SAMPLES;
136
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
137
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
138
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
139
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
140
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
141
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
142
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
143

144
  DMA_Init(DMA1_Channel1, &DMA_InitStructure); // ADC1
145
}
146
/**************************************************************************************/
147
void ADC_Configuration(void)
148
{
149
    ADC_InitTypeDef        ADC_InitStructure;
150
    ADC_CommonInitTypeDef  ADC_CommonInitStructure;
151
  volatile int i;
152
//    uint16_t CalibrationValue[4];
153

154
  /* Configure the ADC clocks */
155
  RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1);
156

157
  /* Enable ADC1/2/3/4 clocks */
158
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
159

160
  /* ADC GPIO configuration */
161
  ADC_GPIO_Configuration();
162

163
  /* ADC DMA Channel configuration */
164
  ADC12_DMA_Configuration();
165

166
  /* ADC Calibration procedure */
167
  ADC_VoltageRegulatorCmd(ADC1, ENABLE);
168
  ADC_VoltageRegulatorCmd(ADC2, ENABLE);
169

170

171
  /* Insert delay */
172
  for(i=0; i<10000; i++);
173

174
  ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
175
  ADC_StartCalibration(ADC1);
176

177
  ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single);
178
  ADC_StartCalibration(ADC2);
179

180

181

182
  while(ADC_GetCalibrationStatus(ADC1) != RESET );
183
  CalibrationValue[0] = ADC_GetCalibrationValue(ADC1);
184

185
  while(ADC_GetCalibrationStatus(ADC2) != RESET );
186
  CalibrationValue[1] = ADC_GetCalibrationValue(ADC2);
187

188
  /* ADC Dual mode configuration */
189
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_RegSimul;
190
  ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
191
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; // 12-bit
192
  ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
193
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = 10;
194

195
  ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
196

197
  /* */
198
  ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable; // Triggered
199
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
200
  ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge;
201
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
202
  ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
203
  ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
204
  ADC_InitStructure.ADC_NbrOfRegChannel = 3;
205

206
  ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_10; // Entspricht dem TRGO2 des TIM1
207

208
  ADC_Init(ADC1, &ADC_InitStructure);
209
  ADC_Init(ADC2, &ADC_InitStructure);
210

211

212

213
  /*
214
  ____|Seq1|Seq2|Seq3|
215
  ADC1|PB0 |PA0 |PA1 |
216
  ADC2|PA7 |-   | -  |
217
  */
218

219
  /* ADC1 regular configuration */
220
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_7Cycles5); // PB0
221
  /* ADC2 regular configuration */
222
  ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_7Cycles5); // PA7
223

224

225
  /* ADC1 regular configuration */
226
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_7Cycles5); // PA0
227

228

229
  /* ADC1 regular configuration */
230
  ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_7Cycles5); // PA1
231

232

233
  /* Configures the ADC DMA */
234
  ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);
235

236
  /* Enable the ADC DMA */
237
  ADC_DMACmd(ADC1, ENABLE);
238

239
  /* Enable ADC[1..2] */
240
  ADC_Cmd(ADC1, ENABLE);
241
  ADC_Cmd(ADC2, ENABLE);
242

243

244
  /* wait for ADC1 ADRDY */
245
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
246

247
  /* wait for ADC2 ADRDY */
248
  while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY));
249

250

251
  /* Enable the DMA channel */
252
  DMA_Cmd(DMA1_Channel1, ENABLE);
253

254
  /* Enable DMA1 Channel1 Transfer Complete interrupt */
255
  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
256

257

258
  /* Start ADC1 Software Conversion */
259
  ADC_StartConversion(ADC1);
260

261
}
262
/**************************************************************************************/
263
void DMA1_Channel1_IRQHandler(void)
264
{
265
  /* Test on DMA1 Channel1 Transfer Complete interrupt */
266
  if (DMA_GetITStatus(DMA1_IT_TC1))
267
  {
268

269
    /* Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits */
270
    DMA_ClearITPendingBit(DMA1_IT_GL1);
271

272
    adc_interrupt();
273

274
  }
275
}
276

277
void Periph_Configuration(void)
278
{
279
  SystemInit();
280
  TIM1_Configuration();
281

282
  ADC_Configuration();
283

284
  /* Enable DMA1 Channel1 Transfer Complete interrupt */
285
  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
286

287
  NVIC_Configuration();
288

289
}
290
/**************************************************************************************/
1
int main(void)
2
{
3
        init_variables();
4
  init_serial();
5
  Periph_Configuration();
6

7
  while(1)
8
  {
9
    serial_monitor();
10
  }
11
}


Funktioniert alles soweit auch: Es werden Daten seriell an den PC 
übertragen, PWM Signale werden generiert, ADCs sampeln die Channel, 
Sampelwerte werden per DMA abgeholt und es wird
in den DMA1_Channel1_IRQHandler gewechselt. Dort wird vorerst nur eine 
Float Variable um 0.1 erhöht.
Nach einer gewissen, unbestimmbaren Zeit (1-60s) hören die ADCs 
plötzlich auf zu sampeln und es wird nicht in den 
DMA1_Channel1_IRQHandler gesprungen.
Die serielle Kommunikation läuft problemlos weiter. Es werden weiterhin 
richtige Werte an den PC übertragen.
Ohne serieller Kommunikation tritt das Problem nicht auf.

Wie könnte das zusammenhängen?

Gruß
#4739986
Lesenswert?

Andreas T. schrieb:
> Dort wird vorerst nur eine
> Float Variable um 0.1 erhöht.

Das geht aber nur eine bestimmte Zeit gut, denn Float hat nur 5-6 
signifikante Stellen. Irgendwann sind Deine 0.1 zu klein um noch die 
Mantisse bei der großen Zahl beeinflussen zu können. Dann hat die 
Addition der kleinen Zahl keinen Effekt mehr.

Nimm lieber einen unsigned int als Zähler.
Gast #4740069
Lesenswert?

Andreas T. schrieb:
> Dort wird vorerst nur eine
> Float Variable um 0.1 erhöht.

Schlechte Idee. 0.1 dezimal hat keine exakte Entsprechung im float, 
ähnlich wie man 1/3 nicht mit einer endlichen Dezimal-Kommadarstellung 
haben kann.

Als Zähler nimmt man Integer. Die nächstbessere Lösung ist es, 
Intervalle wie 1/2, 1/4, 1/8 usw. zu nehmen, weil die eine exakte 
Darstellung haben.

Mußt Du wirklich Intervalle von 0.1 haben, dann nimmt man einen Integer 
und konvertiert ihn vor der Intervallauswertung nach float, dann 
dividiert man das durch 10.0f.
Gast #4740141
Lesenswert?

Oje oje, was für einen riesigen Batzen Quellcode hast du da gepostet. 
Wer soll statt deiner sich da durchquälen?

Nun, wenn ich beim Überfliegen deiner Quelle sowas sehe:

Andreas T. schrieb:
> void USART1_IRQHandler(void)
> {
>   if (USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
>     {
>         USART_ClearITPendingBit(USART1,USART_IT_RXNE);
>
>         switch (USART1->RDR) {

..dann wird mir schlecht.

Warum um alles in der Welt schaffen es die heutigen Programmierer nicht, 
die Dinge und deren Ebenen sauber auseinander zu halten? In jeder 
Firmware gibt es ne Hierarchie:
1. Hardware
2. LoLevelTreiber
3. ggf.höhere Treiber (Protokolle)
4. Algorithmen, also das, was die Firmware eigentlich tun soll

Schreibe dir einen Treiber für deinen USART, der eben diesen USART 
sauber abstrahiert und den Datenstrom in beiden Richtungen puffert und 
organisiert. UND NICHT MEHR!

Was hat dich geritten, daß du in deinen Treiber eine Auswertung der 
Daten schreibst? (switch (USART.RDR)...) Sowas gehört dort 
allerkeinstenfalls hin.

Zweitens: dein Usart_Clear_PendingBit ist mir suspekt. Lies das 
Refmanual. Soweit mir erinnerlich, ist sowas ein Bug. Das RX-Bit wird 
von der Hardware automatisch gelöscht, sobald RDR gelesen wurde. Das 
bedeutet übrigens auch, daß du RDR nur ein einziges Mal pro empfangenem 
Byte lesen darfst. Also, die Regel ist:
1. Status lesen und auswerten, geht m.W. beliebig oft
2. RDR auslesen (geht nur 1x) und Byte wegspeichern.
(Falls das Lesen von RDR bei dir ausnahmsweise mehrfach geht, dann ist 
das entweder ein Zufall oder der Compiler hat den zweiten Zugriff 
wegoptimiert oder das Startbit des nächste Bytes am Pin ist noch nicht 
detektiert.

Ich geb dir mal ein funktionierendes Beispiel (hab das hier schon 
mehrfach gepostet). Läuft gut, wertet allerdings Fehlersituationen nicht 
aus.
1
__irq void USART1_IRQHandler (void)
2
{ char c;
3
  int  i, j;
4

5
  if (USART1_ISR & ((1<<5)|(1<<3))) // RX: Zeichen empfangen oder Overrun
6
  { // hier ggf. Overrun, Parity, Frame u.a. Errors auswerten
7
    
8
    // Zeichen abholen
9
    c = USART1_RDR;
10
    i = U1Buf.InWP;
11
    j = (i+1) & (IBLEN-1);
12
    if (j!=U1Buf.InRP)
13
    { U1Buf.InBuf[i] = c;
14
      U1Buf.InWP = j;
15
    }
16
  }
17

18
  if  (USART1_ISR & (1<<7))              // TX: Sendepuffer leer geworden
19
  { i = U1Buf.OutRP;
20
    if (i!=U1Buf.OutWP)                  // ob es was zu senden gibt
21
    { USART1_TDR  = U1Buf.OutBuf[i];
22
      U1Buf.OutRP = (i+1) & (OBLEN-1);
23
    }
24
    else
25
    { USART1_CR1 &= ~(3<<6);             // nö, TXEIE und TCIE ausschalten
26
    }
27
  }
28
}

W.S.

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