Forum: Compiler & IDEs Timing-Problem beim ATMega32


von Thomas (Gast)


Lesenswert?

Hallo,

ich habe ein kleines Problem mit meinem AtMega32...
Ich habe bereits ein lauffähiges BASCOM-Programm zusammengedängelt.
Das finde ich allesdings äusserst unschön.
Nun ist es so, dass ich selbiges gerne in ein C-Programm konvertieren 
möchte, also zumindest von der Idee her.

BASCOM-Programm:
1
$regfile = "m32def.dat"                                     'definieren des verwendeten Chips
2
3
$crystal = 16000000                                         'definieren des verwendeten externen Quarz (8MHz)
4
5
Config Portd = Output
6
Dim S As String * 24
7
8
9
10
11
12
Main:
13
Do
14
15
16
17
Portd.1 = 1
18
Waitus 833
19
20
Portd.1 = 1
21
Waitus 833
22
Portd.1 = 0
23
Waitus 833
24
Portd.1 = 0
25
Waitus 833
26
Portd.1 = 1
27
Waitus 833
28
Portd.1 = 0
29
Waitus 833
30
Portd.1 = 0
31
Waitus 833
32
Portd.1 = 0
33
Waitus 833
34
35
Portd.1 = 0
36
Waitus 833
37
38
Portd.1 = 0
39
Waitus 833
40
Portd.1 = 0
41
Waitus 833
42
43
44
45
46
47
Portd.1 = 1
48
Waitus 833
49
50
Portd.1 = 1
51
Waitus 833
52
Portd.1 = 1
53
Waitus 833
54
Portd.1 = 0
55
Waitus 833
56
Portd.1 = 1
57
Waitus 833
58
Portd.1 = 0
59
Waitus 833
60
Portd.1 = 1
61
Waitus 833
62
Portd.1 = 0
63
Waitus 833
64
65
Portd.1 = 0
66
Waitus 833
67
68
Portd.1 = 0
69
Waitus 833
70
Portd.1 = 0
71
Waitus 833
72
Waitms 250
73
74
75
76
77
Portd.1 = 1
78
Waitus 833
79
80
Portd.1 = 0
81
Waitus 833
82
Portd.1 = 1
83
Waitus 833
84
Portd.1 = 0
85
Waitus 833
86
Portd.1 = 1
87
Waitus 833
88
Portd.1 = 1
89
Waitus 833
90
Portd.1 = 1
91
Waitus 833
92
Portd.1 = 0
93
Waitus 833
94
95
Portd.1 = 0
96
Waitus 833
97
98
Portd.1 = 0
99
Waitus 833
100
Portd.1 = 0
101
Waitus 833
102
Waitms 250
103
104
105
106
107
Portd.1 = 1
108
Waitus 833
109
110
Portd.1 = 0
111
Waitus 833
112
Portd.1 = 0
113
Waitus 833
114
Portd.1 = 1
115
Waitus 833
116
Portd.1 = 1
117
Waitus 833
118
Portd.1 = 0
119
Waitus 833
120
Portd.1 = 1
121
Waitus 833
122
Portd.1 = 0
123
Waitus 833
124
125
Portd.1 = 1
126
Waitus 833
127
128
Portd.1 = 0
129
Waitus 833
130
Portd.1 = 0
131
Waitus 833
132
Waitms 250
133
134
135
136
137
Portd.1 = 1
138
Waitus 833
139
140
Portd.1 = 1
141
Waitus 833
142
Portd.1 = 1
143
Waitus 833
144
Portd.1 = 0
145
Waitus 833
146
Portd.1 = 1
147
Waitus 833
148
Portd.1 = 0
149
Waitus 833
150
Portd.1 = 1
151
Waitus 833
152
Portd.1 = 0
153
Waitus 833
154
155
Portd.1 = 0
156
Waitus 833
157
158
Portd.1 = 0
159
Waitus 833
160
Portd.1 = 0
161
Waitus 833
162
Waitms 250
163
164
165
166
167
Portd.1 = 1
168
Waitus 833
169
Portd.1 = 1
170
Waitus 833
171
Portd.1 = 1
172
Waitus 833
173
Portd.1 = 1
174
Waitus 833
175
Portd.1 = 1
176
Waitus 833
177
Portd.1 = 1
178
Waitus 833
179
Portd.1 = 0
180
Waitus 833
181
Portd.1 = 1
182
Waitus 833
183
Portd.1 = 0
184
Waitus 833
185
Portd.1 = 0
186
Waitus 833
187
Portd.1 = 0
188
Waitus 833
189
Waitms 250
190
Portd.1 = 1
191
Waitus 833
192
Portd.1 = 1
193
Waitus 833
194
Portd.1 = 1
195
Waitus 833
196
Portd.1 = 1
197
Waitus 833
198
Portd.1 = 1
199
Waitus 833
200
Portd.1 = 1
201
Waitus 833
202
Portd.1 = 0
203
Waitus 833
204
Portd.1 = 1
205
Waitus 833
206
Portd.1 = 0
207
Waitus 833
208
Portd.1 = 0
209
Waitus 833
210
Portd.1 = 0
211
Waitus 833
212
Waitms 250
213
Portd.1 = 1
214
Waitus 833
215
Portd.1 = 1
216
Waitus 833
217
Portd.1 = 1
218
Waitus 833
219
Portd.1 = 1
220
Waitus 833
221
Portd.1 = 1
222
Waitus 833
223
Portd.1 = 1
224
Waitus 833
225
Portd.1 = 0
226
Waitus 833
227
Portd.1 = 1
228
Waitus 833
229
Portd.1 = 0
230
Waitus 833
231
Portd.1 = 0
232
Waitus 833
233
Portd.1 = 0
234
Waitus 833
235
Waitms 250
236
Portd.1 = 1
237
Waitus 833
238
Portd.1 = 1
239
Waitus 833
240
Portd.1 = 1
241
Waitus 833
242
Portd.1 = 1
243
Waitus 833
244
Portd.1 = 1
245
Waitus 833
246
Portd.1 = 1
247
Waitus 833
248
Portd.1 = 0
249
Waitus 833
250
Portd.1 = 1
251
Waitus 833
252
Portd.1 = 0
253
Waitus 833
254
Portd.1 = 0
255
Waitus 833
256
Portd.1 = 0
257
Waitus 833
258
Waitms 250
259
Portd.1 = 1
260
Waitus 833
261
Portd.1 = 1
262
Waitus 833
263
Portd.1 = 1
264
Waitus 833
265
Portd.1 = 1
266
Waitus 833
267
Portd.1 = 1
268
Waitus 833
269
Portd.1 = 1
270
Waitus 833
271
Portd.1 = 0
272
Waitus 833
273
Portd.1 = 1
274
Waitus 833
275
Portd.1 = 0
276
Waitus 833
277
Portd.1 = 0
278
Waitus 833
279
Portd.1 = 0
280
Waitus 833
281
Waitms 250
282
Portd.1 = 1
283
Waitus 833
284
Portd.1 = 1
285
Waitus 833
286
Portd.1 = 1
287
Waitus 833
288
Portd.1 = 1
289
Waitus 833
290
Portd.1 = 1
291
Waitus 833
292
Portd.1 = 1
293
Waitus 833
294
Portd.1 = 0
295
Waitus 833
296
Portd.1 = 1
297
Waitus 833
298
Portd.1 = 0
299
Waitus 833
300
Portd.1 = 0
301
Waitus 833
302
Portd.1 = 0
303
Waitus 833
304
Waitms 250
305
Portd.1 = 1
306
Waitus 833
307
Portd.1 = 1
308
Waitus 833
309
Portd.1 = 1
310
Waitus 833
311
Portd.1 = 1
312
Waitus 833
313
Portd.1 = 1
314
Waitus 833
315
Portd.1 = 1
316
Waitus 833
317
Portd.1 = 0
318
Waitus 833
319
Portd.1 = 1
320
Waitus 833
321
Portd.1 = 0
322
Waitus 833
323
Portd.1 = 0
324
Waitus 833
325
Portd.1 = 0
326
Waitus 833
327
Waitms 250
328
Portd.1 = 1
329
Waitus 833
330
Portd.1 = 1
331
Waitus 833
332
Portd.1 = 1
333
Waitus 833
334
Portd.1 = 1
335
Waitus 833
336
Portd.1 = 1
337
Waitus 833
338
Portd.1 = 1
339
Waitus 833
340
Portd.1 = 0
341
Waitus 833
342
Portd.1 = 1
343
Waitus 833
344
Portd.1 = 0
345
Waitus 833
346
Portd.1 = 0
347
Waitus 833
348
Portd.1 = 0
349
Waitus 833
350
Waitms 250
351
Portd.1 = 1
352
Waitus 833
353
Portd.1 = 1
354
Waitus 833
355
Portd.1 = 1
356
Waitus 833
357
Portd.1 = 1
358
Waitus 833
359
Portd.1 = 1
360
Waitus 833
361
Portd.1 = 1
362
Waitus 833
363
Portd.1 = 0
364
Waitus 833
365
Portd.1 = 1
366
Waitus 833
367
Portd.1 = 0
368
Waitus 833
369
Portd.1 = 0
370
Waitus 833
371
Portd.1 = 0
372
Waitus 833
373
Waitms 250
374
Portd.1 = 1
375
Waitus 833
376
Portd.1 = 1
377
Waitus 833
378
Portd.1 = 1
379
Waitus 833
380
Portd.1 = 1
381
Waitus 833
382
Portd.1 = 1
383
Waitus 833
384
Portd.1 = 1
385
Waitus 833
386
Portd.1 = 0
387
Waitus 833
388
Portd.1 = 1
389
Waitus 833
390
Portd.1 = 0
391
Waitus 833
392
Portd.1 = 0
393
Waitus 833
394
Portd.1 = 0
395
Waitus 833
396
Waitms 250
397
Portd.1 = 1
398
Waitus 833
399
Portd.1 = 1
400
Waitus 833
401
Portd.1 = 1
402
Waitus 833
403
Portd.1 = 1
404
Waitus 833
405
Portd.1 = 1
406
Waitus 833
407
Portd.1 = 1
408
Waitus 833
409
Portd.1 = 0
410
Waitus 833
411
Portd.1 = 1
412
Waitus 833
413
Portd.1 = 0
414
Waitus 833
415
Portd.1 = 0
416
Waitus 833
417
Portd.1 = 0
418
Waitus 833
419
Waitms 250
420
Portd.1 = 1
421
Waitus 833
422
Portd.1 = 1
423
Waitus 833
424
Portd.1 = 1
425
Waitus 833
426
Portd.1 = 1
427
Waitus 833
428
Portd.1 = 1
429
Waitus 833
430
Portd.1 = 1
431
Waitus 833
432
Portd.1 = 0
433
Waitus 833
434
Portd.1 = 1
435
Waitus 833
436
Portd.1 = 0
437
Waitus 833
438
Portd.1 = 0
439
Waitus 833
440
Portd.1 = 0
441
Waitus 833
442
Waitms 250
443
444
445
446
Portd.1 = 1
447
Waitus 833
448
449
Portd.1 = 0
450
Waitus 833
451
Portd.1 = 1
452
Waitus 833
453
Portd.1 = 0
454
Waitus 833
455
Portd.1 = 0
456
Waitus 833
457
Portd.1 = 1
458
Waitus 833
459
Portd.1 = 1
460
Waitus 833
461
Portd.1 = 1
462
Waitus 833
463
464
Portd.1 = 0
465
Waitus 833
466
467
Portd.1 = 0
468
Waitus 833
469
Portd.1 = 0
470
Waitus 833
471
Waitms 250
472
473
474
Portd.1 = 1
475
Waitus 833
476
477
Portd.1 = 1
478
Waitus 833
479
Portd.1 = 0
480
Waitus 833
481
Portd.1 = 1
482
Waitus 833
483
Portd.1 = 1
484
Waitus 833
485
Portd.1 = 0
486
Waitus 833
487
Portd.1 = 1
488
Waitus 833
489
Portd.1 = 1
490
Waitus 833
491
492
Portd.1 = 1
493
Waitus 833
494
495
Portd.1 = 0
496
Waitus 833
497
Portd.1 = 0
498
Waitus 833
499
Waitms 10000
500
Loop
501
502
Return

Mein C-Programm sieht nun wie folgt aus:
1
#define F_CPU 16000000UL  // 16MHZ
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
void DELAYUS(int a)
6
{
7
        _delay_us(500);
8
        asm("nop");
9
        _delay_us(a-500);
10
}
11
12
void delay(int a)
13
{
14
        _delay_ms(a);
15
}
16
17
void txd(int a)
18
{
19
if (a==1)
20
                PORTD=0;
21
        else
22
                PORTD=2;
23
}
24
25
void test(void)
26
{
27
int d=800;
28
txd(1);
29
delay(1000);
30
//Startbit
31
txd(0);
32
DELAYUS(d);
33
//7-Bit Zeichen Übertragen
34
txd(0);
35
DELAYUS(d);
36
txd(1);
37
DELAYUS(d);
38
txd(1);
39
DELAYUS(d);
40
txd(0);
41
DELAYUS(d);
42
txd(1);
43
DELAYUS(d);
44
txd(1);
45
DELAYUS(d);
46
txd(1);
47
DELAYUS(d);
48
//Parity-Bit
49
txd(1);
50
DELAYUS(d);
51
//2 Stop-Bits
52
txd(1);
53
DELAYUS(d);
54
txd(1);
55
DELAYUS(d);
56
delay(15);
57
58
//=================2
59
60
//Startbit
61
txd(0);
62
DELAYUS(d);
63
//7-Bit Zeichen Übertragen
64
txd(0);
65
DELAYUS(d);
66
txd(0);
67
DELAYUS(d);
68
txd(1);
69
DELAYUS(d);
70
txd(0);
71
DELAYUS(d);
72
txd(1);
73
DELAYUS(d);
74
txd(0);
75
DELAYUS(d);
76
txd(1);
77
DELAYUS(d);
78
//Parity-Bit
79
txd(1);
80
DELAYUS(d);
81
//2 Stop-Bits
82
txd(1);
83
DELAYUS(d);
84
txd(1);
85
DELAYUS(d);
86
delay(15);
87
88
//==============================3
89
90
//Startbit
91
txd(0);
92
DELAYUS(d);
93
//7-Bit Zeichen Übertragen
94
txd(1);
95
DELAYUS(d);
96
txd(0);
97
DELAYUS(d);
98
txd(1);
99
DELAYUS(d);
100
txd(0);
101
DELAYUS(d);
102
txd(0);
103
DELAYUS(d);
104
txd(0);
105
DELAYUS(d);
106
txd(1);
107
DELAYUS(d);
108
//Parity-Bit
109
txd(1);
110
DELAYUS(d);
111
//2 Stop-Bits
112
txd(1);
113
DELAYUS(d);
114
txd(1);
115
DELAYUS(d);
116
delay(15);
117
118
//======================4
119
120
//Startbit
121
txd(0);
122
DELAYUS(d);
123
//7-Bit Zeichen Übertragen
124
txd(1);
125
DELAYUS(d);
126
txd(1);
127
DELAYUS(d);
128
txd(0);
129
DELAYUS(d);
130
txd(0);
131
DELAYUS(d);
132
txd(1);
133
DELAYUS(d);
134
txd(0);
135
DELAYUS(d);
136
txd(1);
137
DELAYUS(d);
138
//Parity-Bit
139
txd(0);
140
DELAYUS(d);
141
//2 Stop-Bits
142
txd(1);
143
DELAYUS(d);
144
txd(1);
145
DELAYUS(d);
146
delay(15);
147
148
//===============5
149
150
//Startbit
151
txd(0);
152
DELAYUS(d);
153
//7-Bit Zeichen Übertragen
154
txd(0);
155
DELAYUS(d);
156
txd(0);
157
DELAYUS(d);
158
txd(1);
159
DELAYUS(d);
160
txd(0);
161
DELAYUS(d);
162
txd(1);
163
DELAYUS(d);
164
txd(0);
165
DELAYUS(d);
166
txd(1);
167
DELAYUS(d);
168
//Parity-Bit
169
txd(1);
170
DELAYUS(d);
171
//2 Stop-Bits
172
txd(1);
173
DELAYUS(d);
174
txd(1);
175
DELAYUS(d);
176
delay(15);
177
178
//================6
179
180
for (int i=0;i<=12;i++)
181
{
182
//Startbit
183
txd(0);
184
DELAYUS(d);
185
//7-Bit Zeichen Übertragen
186
txd(0);
187
DELAYUS(d);
188
txd(0);
189
DELAYUS(d);
190
txd(0);
191
DELAYUS(d);
192
txd(0);
193
DELAYUS(d);
194
txd(0);
195
DELAYUS(d);
196
txd(1);
197
DELAYUS(d);
198
txd(0);
199
DELAYUS(d);
200
//Parity-Bit
201
txd(1);
202
DELAYUS(d);
203
//2 Stop-Bits
204
txd(1);
205
DELAYUS(d);
206
txd(1);
207
DELAYUS(d);
208
delay(15);
209
}
210
211
//Startbit
212
txd(0);
213
DELAYUS(d);
214
//7-Bit Zeichen Übertragen
215
txd(1);
216
DELAYUS(d);
217
txd(0);
218
DELAYUS(d);
219
txd(1);
220
DELAYUS(d);
221
txd(1);
222
DELAYUS(d);
223
txd(0);
224
DELAYUS(d);
225
txd(0);
226
DELAYUS(d);
227
txd(0);
228
DELAYUS(d);
229
//Parity-Bit
230
txd(1);
231
DELAYUS(d);
232
//2 Stop-Bits
233
txd(1);
234
DELAYUS(d);
235
txd(1);
236
DELAYUS(d);
237
delay(15);
238
239
//Startbit
240
txd(0);
241
DELAYUS(d);
242
//7-Bit Zeichen Übertragen
243
txd(0);
244
DELAYUS(d);
245
txd(1);
246
DELAYUS(d);
247
txd(0);
248
DELAYUS(d);
249
txd(0);
250
DELAYUS(d);
251
txd(1);
252
DELAYUS(d);
253
txd(0);
254
DELAYUS(d);
255
txd(0);
256
DELAYUS(d);
257
//Parity-Bit
258
txd(0);
259
DELAYUS(d);
260
//2 Stop-Bits
261
txd(1);
262
DELAYUS(d);
263
txd(1);
264
DELAYUS(d);
265
delay(15);
266
}
267
268
int main (void) {
269
   DDRD  = 0xff;
270
   PORTD = 0x00;
271
272
   while(1) {
273
//      DELAYUS(800);
274
//      txd(1);
275
//      DELAYUS(800);
276
//      txd(0);
277
        test();
278
        delay(5000);
279
   }
280
   return 0;
281
}
282
roo


Zum testen habe ich nun in beiden Sprachen eine simple Schleife 
geschrieben die nichts weiter tut als den einen pin im 833µs-Takt ein 
und aus zu schalten.
Auf meinem Oszilloskop sehen die Intervalle in denen die beiden 
Programme schalten allerdings noch entwas unterschiedlich aus.
Mein Problem ist nicht durch die Nutzung eines UARTs zu lösen, da die 
Protokoll-Norm erheblich von der RS232-Norm abweicht.

Hat jemand eine Idee?

Grüße und Danke
Thomas

von Icke (Gast)


Lesenswert?

Benutze einen Timer und Bitschiebereien.
So wird das nichts.

von Thomas (Gast)


Lesenswert?

Warum funktioniert es denn dann mit absoluter Zuverlässigkeit mit 
BASCOM?
Und warum ist der Impuls und dessen breite so stabil, dass ich im 
Oszilloskop keine Veränderungen sehe?

von Oliver (Gast)


Lesenswert?

Da Programm ist ja wohl ein verspäteter Aprilscherz. Selbst in Bascom 
gibt es Schleifen und Unterprogramme.

Was macht dein C-Programm, wenn du statt
> _delay_us(a-500);

 _delay_us(300);

schreibst? Der Sinn der variablen Verzögerung ist eh nicht klar.

Oliver

von Johannes M. (johnny-m)


Lesenswert?

Forenregeln lesen! Langer Code gehört in den Anhang! Das ist eine 
Zumutung!

Abgesehen davon: Dokumentation lesen! Variable delays gehen so nicht. 
Und ein C-Buch lesen, in dem was von Schleifen und strukturierter 
Programmierung steht!

von MWS (Gast)


Lesenswert?

Thomas,

mit allem Respekt, aber Dein Code ist brechreizerregend.

Wobei Du interessanterweise denselben Erguss bereits im Bascom-Forum 
losgeworden bist, nur hieß es dort noch:
"Code einer Loop nicht deterministisch"

Lustigerweise hast Du dort in Deinem ersten Versuch das Pin statt den 
Port getoggelt, also den Pullup, und Dich über das Ergebnis gewundert.

Du würdest Dir selber einen Gefallen tun, indem Du:
a) den Gebrauch von intelligent wirkendenden Fremdwörtern wie 
"deterministisch" in Zusammenhang mit diesem Code-gewordenen Albtraum 
unterlässt
b) erst mal programmieren lernst

von Thomas (Gast)


Lesenswert?

Hallo Zusammen,

ich kann nicht nachvollziehen, warum ihr meint die Qulität meines Codes 
beurtielen zu können wenn ihr garnicht wisst worum es bei meinem Versuch 
geht.
Mit genuss hätte ich mir das Posting sparen können wenn ich gewusst 
hätte, dass es hier sowieso nur darum geht anderen Menschen für Ihren 
Code eins aufs Maul zu hauen, wenn man selbst meint, dass man der Gott 
unter der Sonne ist.

Es handelt sich bei meinem Code nur um einen Versuch ob es möglich ist 
diese Bits in den entsprechnenden Intervallen zu übertragen. Dank der 
Hilfe im Basic-Forum habe ich das Basic-Programm auch bereits zum Laufen 
bekommen. Ich kann nun das Gerät am anderen Ende des Drahtes mit den 
gewünschten statischen Testdaten versorgen.

In der regel ist es aber doch nunmal so, dass man einen solchen Versuch 
der generellen Machbarkeit nicht mit zu vielen Strukturen durchführt um 
so viele Fehlerquellen wie möglich auszuschliessen.
Der nächste Schritt wäre dann sowieso eine Dynamik in die Übertragenen 
Daten zu bekommen.

Hat nun noch jemand einen Konstruktiven Vorschlag für mein Problem oder 
seid Ihr alle nur gut um über anderen Code Meckern???

Achso und Deterministisch hat auf mein Problem voll zugetroffen, denn es 
hat sich nicht nach jedem Schleifendurchlauf gleich verhalten!!!
Vielleich sollte da noch mal jemand über andere Arten der Beleidigung 
und Abwartschung derer Leute nachdenken!!!

Vielen Dank schonmal....

von Oliver (Gast)


Lesenswert?

Och, jetzt isser beleidigt.

Drehn wir den Spieß doch mal rum. Da stellt jemand einen hunderte Zeilen 
langen, völlig unleserlichen und absolut blödsinnig formulierten und 
formatierten Code in ein Forum, wovon 99,9% der Zeilen erkennbar nichts 
mit dem Problem zu tun haben, macht nicht einmal den Versuch, für das 
Problem kurzes, möglichst prägnantes Beispiel zu erstellen, geschweige 
denn, die Forenregeln oder den allgemeine Umgang im Forum zu beachten, 
und erwartet, das andere ihre freie Zeit dafür opfern, sich in den 
ganzen Müll hinzudenken. Eine bessere Steilvorlage für blöde Antworten 
und hämische Kommentare gibt es doch gar nicht.

>ich kann nicht nachvollziehen, warum ihr meint die Qulität meines Codes
>beurtielen zu können wenn ihr garnicht wisst worum es bei meinem Versuch
>geht.

Nimm das einfach mal als gegeben an. Schließlich gehst du ja auch davon 
aus, daß dir hier jemand helfen kann.

Aber zurück zum Problem:
>Zum testen habe ich nun in beiden Sprachen eine simple Schleife
>geschrieben die nichts weiter tut als den einen pin im 833µs-Takt ein
>und aus zu schalten.

Das mag sein, aber dein gezeigtes Programm macht etwas anderes. Die 
auskommentierten Zeilen im Hauptprogramm würden das tun. Zeig doch mal 
genau das Testprogramm, auf dem deine Oszi-Messungen beruhen. Abgesehen 
davon ergibt
1
int d=800;
wohl keine 833µs;

Oliver
Oliver

von Karl H. (kbuchegg)


Lesenswert?

> In der regel ist es aber doch nunmal so, dass man einen solchen
> Versuch der generellen Machbarkeit nicht mit zu vielen Strukturen
> durchführt um so viele Fehlerquellen wie möglich auszuschliessen.

Schon richtig.
Aber man läuft dann auch Gefahr, dass der Versuch mit dem Endergebnis 
absolut nichts zu tun hat und daher keineswegs in irgendeiner Form 
aussagekräftig ist, ob das gesteckte Ziel erreichbar ist oder nicht.

Wenn du schon was versuchst, ohne allzuviel Aufwand zu haben, dann mach 
dir doch um Himmels Willen wenigstens eine Funktion, ohne gleich auf 
Copy&Paste auszuweichen. Copy&Paste ist eigentlich fast immer das 
Schlimmste was du tun kannst. Es sieht nur auf den ersten Blick so aus, 
als ob damit das Programmieren schnell von der Hand geht.
1
void TransmitData( uint8_t Bit1, uint8_t Bit2, uint8_t Bit3, uint8_t Bit4,
2
                   uint8_t Bit5, uint8_t Bit6, uint8_t Bit7, uint8_t Parity )
3
{
4
  int d=800;
5
6
  //Startbit
7
  txd(0);
8
  DELAYUS(d);
9
10
  //7-Bit Zeichen Übertragen
11
  txd( Bit1 );
12
  DELAYUS(d);
13
  txd( Bit2 );
14
  DELAYUS(d);
15
  txd( Bit3 );
16
  DELAYUS(d);
17
  txd( Bit4 );
18
  DELAYUS(d);
19
  txd( Bit5 );
20
  DELAYUS(d);
21
  txd( Bit6 );
22
  DELAYUS(d);
23
  txd( Bit7 );
24
  DELAYUS(d);
25
26
  //Parity-Bit
27
  txd( Parity );
28
  DELAYUS(d);
29
30
  //2 Stop-Bits
31
  txd(1);
32
  DELAYUS(d);
33
  txd(1);
34
  DELAYUS(d);
35
  delay(15);
36
}

Alleine durch diese Funktion fällt von deinem Code schon mal geschätze 
70% weg ....
1
void test(void)
2
{
3
  TransmitData( 0, 1, 1, 0, 1, 1, 1,  1 );
4
  TransmitData( 0, 0, 1, 0, 1, 0, 1,  1 );
5
  TransmitData( 1, 0, 1, 0, 0, 0, 1,  1 );
6
  TransmitData( 1, 1, 0, 0, 1, 0, 1,  0 );
7
  TransmitData( 0, 0, 1, 0, 1, 0, 1,  1 );
8
9
  for (int i=0;i<=12;i++)
10
  {
11
    TransmitData( 0, 0, 0, 0, 0, 1, 0,   1);
12
  }
13
14
  TransmitData( 1, 0, 1, 1, 0, 0, 0,   1 );
15
  TransmitData( 0, 1, 0, 0, 1, 0, 0,   0 );
16
}

... und der Rest ist so gestaltet, dass du zumindest in der Anzahl der 
übertragenen Bits keinen Fehler mehr haben kannst.

Testcode soll durchaus ein Minimum an Funktionalität haben, aber er soll 
auch halbwegs realistisch sein.

Dein eigentliches Problem wurde ja schon angesprochen
1
void DELAYUS(int a)
2
{
3
        _delay_us(500);
4
        asm("nop");
5
        _delay_us(a-500);
6
}

... beim Aufruf der _delay_xx Funktionen immer drauf achten, dass die 
Argumente konstant sind. a-500 ist nicht konstant.

von Oliver (Gast)


Lesenswert?

>... beim Aufruf der _delay_xx Funktionen immer drauf achten, dass die
>Argumente konstant sind. a-500 ist nicht konstant.

Das stimmt zwar, erklärt nicht aber, warum das delay nicht trotzdem 
konstant ist.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Oliver wrote:

> Das stimmt zwar, erklärt nicht aber, warum das delay nicht trotzdem
> konstant ist.

Da hast du recht.
Auf der anderen Seite ist

> Auf meinem Oszilloskop sehen die Intervalle in denen die beiden
> Programme schalten allerdings noch entwas unterschiedlich aus.
...
> Und warum ist der Impuls und dessen breite so stabil, dass ich im
> Oszilloskop keine Veränderungen sehe?

auch keine wirklich gute Fehlerbeschreibung.
Ich kann davon eigentlich nicht wirklich ableiten, dass seine Delay 
Zeiten einen Jitter haben, nur dass die Zeiten nicht ganz das sind, was 
er sich erwartet.

von Thomas (Gast)


Lesenswert?

Hi,

ich habe in meinem nun funktionieren Basic-Code ja ein Delayus von 833µs 
drin. Dieser Code funktioniert ja auch.
Also habe ich mir ein Basic-Programm gebaut welches nichts anderes macht 
als Flanken zu erzeugen:
1
$regfile = "m32def.dat"
2
$crystal = 16000000
3
Config Portd = Output
4
5
Main:
6
  Do
7
    Portd.1 = 1
8
    Waitus 833
9
    Portd.1 = 0
10
    Waitus 833
11
  Loop
12
Return

Dabei habe ich auf dem Oszi nun die tatsächliche Flanken-Länge messen 
können. Diese stimmt auch ziemlich genau mit der Ziel-Wartezeit von 
833µs überein.

Dann bin ich als nächtes her gegangen und habe ein entsprechendes 
C-Programm geschrieben was eigentlich das selbe tuen sollte. Dabei bin 
ich allerdings bei der Dokumentation darauf gestossen, dass _delay_us 
maximal 768µs Delay zulässt. Daher meine Konstruktion mit den 2 
getrennten Anweisungen.

Mein C-Programm sah nun so aus:
1
#define F_CPU 16000000UL  // 16MHZ
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
void DELAYUS(int a)
6
{
7
        _delay_us(500);
8
        _delay_us(a-500);
9
}
10
11
int main (void) {
12
   DDRD  = 0xff;
13
   PORTD = 0x00;
14
15
   while(1) {
16
      DELAYUS(800);
17
      txd(1);
18
      DELAYUS(800);
19
      txd(0);
20
   }
21
   return 0;
22
}

Dabei habe ich dann festgestellt, dass die Flankenlänge erheblich von 
der des Basic-Programms abweicht (~60-100µs)...

Nun war meine Frage warum.

Sorry, dass ich mein Fehler nicht ausführlich genug beschrieben habe. 
Vielleicht hätte der Teppich-Code von 1en und 0en nicht not getan.

Grüße
Thomas

von Oliver (Gast)


Lesenswert?

>Dabei habe ich dann festgestellt, dass die Flankenlänge erheblich von
>der des Basic-Programms abweicht (~60-100µs)...

Was denn nun genau? Sind die Pulse der C-Version alle gleich lang, aber 
eben zu lang, oder schwankt die Pulslänge von Puls zu Puls?

Oliver

von MWS (Gast)


Lesenswert?

Thomas,

hier ein Zitat von Dir aus Deinem Beitrag im Bascom Forum:

"Nach jedem 2. Durchlauf der Schleife bleibt der Ausgang auf 0 nach 
jedem anderen Durchlauf ist der Ausgang auf 1."

Wenn Du jetzt wüsstest was das Wort "deterministisch" eigentlich 
bedeutet, dann  hättest Du verstanden, daß sich Dein Programm, im 
Gegensatz zu Deiner Aussage, in höchsten Maße deterministisch verhielt.

Jetzt ist's ja nicht schlimm, etwas nicht zu wissen, geht mir jeden Tag 
so.

Nur wer Dinge wie :

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

vollständig ignoriert, dazu Code postet der dermaßen häßlich ist und 
auch noch mit Fremdwörtern rumwirft, von denen er keine Ahnung hat, darf 
sich über ein bisserl Spott nicht beschweren.

von Peter D. (peda)


Lesenswert?

Thomas wrote:
> Dann bin ich als nächtes her gegangen und habe ein entsprechendes
> C-Programm geschrieben was eigentlich das selbe tuen sollte. Dabei bin
> ich allerdings bei der Dokumentation darauf gestossen, dass _delay_us
> maximal 768µs Delay zulässt.

Das stimmt nicht, lies es bitte komplett:
1
   Perform a delay of \c __us microseconds, using _delay_loop_1().
2
3
   The macro F_CPU is supposed to be defined to a
4
   constant defining the CPU clock frequency (in Hertz).
5
6
   The maximal possible delay is 768 us / F_CPU in MHz.
7
8
   If the user requests a delay greater than the maximal possible one,
9
   _delay_us() will automatically call _delay_ms() instead.  The user
10
   will not be informed about this case.
Und:
1
   Perform a delay of \c __ms milliseconds, using _delay_loop_2().
2
3
   The macro F_CPU is supposed to be defined to a
4
   constant defining the CPU clock frequency (in Hertz).
5
6
   The maximal possible delay is 262.14 ms / F_CPU in MHz.
7
8
   When the user request delay which exceed the maximum possible one,
9
   _delay_ms() provides a decreased resolution functionality. In this
10
   mode _delay_ms() will work with a resolution of 1/10 ms, providing
11
   delays up to 6.5535 seconds (independent from CPU frequency).  The
12
   user will not be informed about decreased resolution.

Oder kurz gesagt, das Maximum ist 6,5535s.


Peter

von Thomas (Gast)


Lesenswert?

Hi,

das mit dem Deterministisch ist eine Frage des Bezuges. Wenn man es auf 
das gesamte Programm bezieht ist deine Ausführung korrekt. Wenn ich es 
aber auf einen Schleifenzyklus beziehe ist es das nicht... schwamm 
drüber...


Wenn ich das richtig gelesen habe kann delay-us maximal ein Delay von 
768 µs und ruft dann delay_ms für alle größeren werte auf, welche aber 
nur noch auf eine zehntel millisekunde genau ist...
1
The maximal possible delay is 768 us / F_CPU in MHz.

Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber 
gemessen an dem basic-test-programm zu kurz...

von Karl H. (kbuchegg)


Lesenswert?

Thomas wrote:

> Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber
> gemessen an dem basic-test-programm zu kurz...

Deine Idee mit den beiden _delay_us ist ja nicht so schlecht.
Nur: die _delay_xx Funktionen benötigen ein konstantes Argument!

Dies liegt daran, dass die Berechnung der internen Schleifenzahl über 
Floating Point Berechnung gemacht wird. Ist das Argument eine Konstante, 
dann kann der Optimizer (darum muss der auch eingeschaltet sein) die 
komplette Berechnung aus dem Code raushalten und zur Compiletime machen. 
Im generierten Code taucht die Berechnung nicht mehr auf -> kein 
Zeitverzug durch Floating Point Berechnungen. Ist das Argument hingegen 
nicht konstant oder ist der Optimizer nicht eingeschaltet, dann wird die 
Berechnung zur Laufzeit gemacht. Und diese Berechnung hat einen 
signifikanten Einfluss auf die tatsächliche Laufzeit -> die Zeiten 
stimmen nicht mehr.

#define DELAY  833

void Delay()
{
  _delay_us( 500 );
  _delay_us( DELAY - 500 );
}

Jetzt ist das Argument konstant und von 501 bis 786+500 änderbar.

Edit: Die Grenzzeit ist ja nicht 786 sondern 768 / F_CPU

von Oliver (Gast)


Lesenswert?

>Wenn ich das richtig gelesen habe kann delay-us maximal ein Delay von
>768 µs

Aber nur bei 1MHz Prozessortakt. Bei 16MHz sind es dann nur noch 786/16 
= 48µs. Ist aber m.E. egal.

>Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber
>gemessen an dem basic-test-programm zu kurz...

_delay_us(500) wird zu delay_ms(0.5), das sollte stimmen.
_delay_us(a-500) mit a=800 wird zu delay_ms(0.3), auch das sollte 
stimmen.

Allerdings verstehe ich die Frage nicht ganz, denn delay_us(800) ist 
nunmal kürzer als WAITUS 833, um "grob geschätzte" 33 us. Der Compiler 
erkennt leider trotz eingeschalteter Optimierung nicht, daß der 
Parameter von _delay_us(a-500) konstant ist, so wird der erst zur 
Laufzeit berechnet - als float, das dauert. Zusätzlich gehen gehen dann 
davon noch die Zyklen zum Aufruf des Unterprogramms ab, und jedes zweite 
mal die der while-Schleife, so daß am Ende weit weniger als 33 us 
Differenz rauskommen sollten, aber niemals 60-100us.

Very seltsam. Geht dein Scope richtig?

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Wenn du es wirklich variabel halten musst, dann kann man auch sowas 
machen. Gegebenenfalls muss man ein klein wenig Zeit für die Rechnerei 
in der Funktion berücksichtigen.
1
void Delay( int a )   // Angabe in µs
2
{
3
  uint8_t i;
4
  uint8_t count = a / 16;
5
  uint8_t rest = a % 16;
6
7
  for( i = 0; i < count; ++i )
8
    _delay_us( 16 );
9
10
  delay_us( rest );
11
}
12
13
int main()
14
{
15
  Delay( 800 ); // warte 800 us
16
}

Aber wichtig ist: Beim Aufruf von _delay_us muss eine Konstante sein 
und der Optimizer muss eingeschaltet sein.

von MWS (Gast)


Lesenswert?

Ok, also je nach Sichtweise deterministisch oder nicht :D

Aber mal ganz praktisch:
Verwende einen 16Bit Timer, z.B. Timer1, den kannst Du auf 
unterschiedliche Delays einstellen. Nimm entweder CTC oder lade den 
Timer vor mit einem Wert entsprechend des Delays. Bei 16MHz und einem 
Prescaler von 8 läuft der Timer nach maximal 32,768mS über. Für 800µS 
und bei CTC muss das OCR mit einem Wert von 1600 geladen werden, bei 
Verwendung als Overflow müsste er mit 63936 vorgeladen werden. Dann 
schreibst Du in die CTC/OVF ISR den Code rein, der die Portzustände 
(z.B. Bascom) per Read aus Data Anweisungen holt. Wenn Du 
verschwenderisch mit Speicher umgehen willst, dann ist jedes Byte ein 
Zustand. Wenn speichersparend vorzugehen ist, dann ist jedes Byte acht 
Zustände, die Du an den Portpin rausschiebst. Wenn Du eine zweite Data 
Tabelle anlegst, kannst Du darin sogar unterschiedliche Delays ablegen. 
Das Ganze ist nicht viel Code, und damit lässt sich dann viel einfacher 
arbeiten, experimentieren und auch ändern. Verändere mal auf die 
Schnelle den obigen Schlangencode, bzw. versuch die Übersicht zu 
behalten, und Du verstehst was ich meine.

von Oliver (Gast)


Lesenswert?

Ich hab es jetzt mal in der Simulation laufen lassen.

WinAVR2009xxx, mit Optimierung -OS

High 871  us
Low 872 us

wie erwartet.  Nix mit zu kurz.

Check mal dein Scope...

Oliver

von Thomas (Gast)


Lesenswert?

Hallo,

vielen Dank noch einmal an alle Beteiligten und noch mal ein 
Entschuldigung von meiner Seite für die Misachtung der Forums-Regeln.

Auch ein dickes Dankeschön an Karl Heinz.

Ich habe den Code nun etwas übersichtlicher gestaltet -> siehe Post von 
Karlheinz.

Und siehe da, kaum macht man es richtig funktionierts.

Der Fehlerteufel muss im Detail gesteckt haben.
Auch die Impulslaenge stimmte auf einmal als ich meine eigenen 
warte-Methoden entsorgt hatte. Alles ist nun im Lot.

Nun geht es an das erzeugen von Initelligenz :)

Grüße
Thomas

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.