Forum: Mikrocontroller und Digitale Elektronik STM32F303 USART in Kombination mit Timer+ADC+DMA der 2te


von Andreas T. (skycurve)


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ß

von Jim M. (turboj)


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.

von Nop (Gast)


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.

von Andreas T. (skycurve)


Lesenswert?

Ich verwende diese Float Variable nicht als Zähler oder ähnliches. Ich 
kann hier genauso einen Integer nehmen und ihn um 1 erhöhen oder auch 
gar nichts machen -> das Problem tritt genau so auf.

Gruß

: Bearbeitet durch User
von W.S. (Gast)


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.

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.