Forum: Mikrocontroller und Digitale Elektronik Externe .c bringt nur theater


von Sebi (Gast)


Lesenswert?

Hallo, ich hab mir einen kleinen Autonomen Roboter gebaut, aber immer 
wenn ich versuche die Steuerung der Motoren in ein externe .c und .h 
zupacken läuft danach nichts mehr.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include "HC_SR_04.h"
5
#include "USART.h"
6
7
/****************************************************************************************************************************/
8
/***************************************************** Globale Variablen ****************************************************/
9
/****************************************************************************************************************************/
10
uint16_t abstand = 0,rechts =0,links =0;
11
/****************************************************************************************************************************/
12
/***************************************************** Initialisierungen ****************************************************/
13
/****************************************************************************************************************************/
14
15
void timer1_motorpwm_init()                                  /*Inizialisierung von Timer1_Motor*/
16
{
17
  /* fpwm = F_CPU/(Prescaller*Obergrenze)*/
18
  TCCR1A |= (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
19
  /* Modus 14: Fast PWM mit beliebiger Schrittzahl (festgelegt durch ICR1) nicht Invertiert(COM1x1) */
20
  TCCR1B |= (1<<WGM13)|(1<<WGM12)| (1<<CS11); /* (WGM13 und WGM12 gehören zu Modi auswahl) CS = Prescaler 8 */
21
  
22
  DDRD |= (1<<MOTORA_1) | (1<<MOTORB_1) | (1<<SERVO_PWM);        /* Ausgänge PORT D standard maessig LOW */
23
  DDRC |= (1<<MOTORB_2) | (1<<MOTORA_2) | (1<<MOTORB_EN) | (1<<MOTORA_EN);
24
  
25
  PORTC |= (0<<MOTORB_2) | (0<<MOTORA_2) | (1<<MOTORB_EN) | (1<<MOTORA_EN);
26
  ICR1 = F_PWM;                                        /* Obergrenze / Periodendauer */
27
28
  OCR1A = 30;  /* LINKS */                                          /* Einschaltzeit MOTORA */
29
  OCR1B = 30;  /* RECHTS */                                          /* Einschaltzeit MOTORB */
30
}
31
32
void timer2_servo_init()
33
{
34
  TCCR2 |= (1<<WGM21) | (1<<WGM20) | (1<<COM21) | (1<<CS22)| (1<<CS21) | (1<<CS20);  /* Fast PWM nicht invertiert (ORC2) */
35
  /* Presacaller 1:1024 Periodendauer 16,4ms ~ 61 HZ*/
36
  DDRD |= (1<<SERVO_PWM);
37
  SERVO_MITTE;
38
}
39
40
void MOTOR_PWM (uint16_t A, uint16_t B)
41
{
42
  OCR1A = A;
43
  OCR1B = B;
44
}
45
int main(void)
46
{
47
  
48
  timer2_servo_init();
49
  hc_sr04_init();
50
  timer1_motorpwm_init();
51
  sei();
52
  while (1)
53
  {
54
    SERVO_MITTE;
55
    PORTC = (0<<MOTORB_2) | (0<<MOTORA_2) | (1<<MOTORB_EN) | (1<<MOTORA_EN);
56
    abstand = HC_SR_04();
57
    if (abstand >100)
58
    {
59
      MOTOR_PWM(50,50);
60
    }
61
    else if (abstand > 40 && abstand <= 100)
62
    {
63
      MOTOR_PWM(35,35);
64
    }
65
    else if (abstand <= 40 && abstand >5)
66
    {
67
      MOTOR_PWM(0,0);
68
      SERVO_LINKS;
69
      _delay_ms(250);
70
      links = HC_SR_04();
71
      SERVO_RECHTS;
72
      _delay_ms(250);
73
      rechts = HC_SR_04();
74
      PORTC = (1<<MOTORB_2) | (1<<MOTORA_2) | (1<<MOTORB_EN) | (1<<MOTORA_EN);
75
      MOTOR_PWM(10,10);
76
      _delay_ms(1000);
77
      PORTC = (0<<MOTORB_2) | (0<<MOTORA_2) | (1<<MOTORB_EN) | (1<<MOTORA_EN);
78
      if (links <= rechts)
79
      {
80
        SERVO_RECHTS;
81
        MOTOR_PWM(40,0);
82
        _delay_ms(500);
83
      }
84
      else
85
      {
86
        SERVO_LINKS;
87
        MOTOR_PWM(0,40);
88
        _delay_ms(500);
89
      }
90
    }
91
    else
92
    {
93
      MOTOR_PWM(0,0);
94
    }
95
  }
96
}

schreib ich den Code so funktoniert alles einwandfrei.

packe ich nun den Code in eine externe .c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "L293D.h"
4
5
6
7
void MOTOR_PWM (uint16_t A, uint16_t B)
8
{
9
  OCR1A = A;
10
  OCR1B = B;
11
}
und das hier in eine .h
1
#ifndef L293D_H_
2
#define L293D_H_
3
4
extern void MOTOR_PWM (uint16_t A, uint16_t B);
5
6
#endif /* L293D_H_ */

natürlich wird die L293D.h mit include eingebunden und der Code der in 
der L293D.c ist aus der Main entfernt.

Weiß jemand woran es liegen könnte?

von Erwin D. (Gast)


Lesenswert?

Sebi schrieb:
> Weiß jemand woran es liegen könnte?

Woran was liegen könnte?
Du hast nicht geschrieben, was passiert...

von Sebi (Gast)


Lesenswert?

Es passiert das die Beiden Motoren nur noch rückwärts oder gar nicht 
mehr laufen und der Servo in der Rechten Prosition stehen bleibt. ach 
aus und einschalten fährt der Servo wieder in die Mitte bebewegt sich 
nach rechts und bleibt dort.

von Georg G. (df2au)


Lesenswert?

Unerklärbare Effekte. Und der Compiler wirft dir keine Fehler oder 
Warnungen an den Kopf, wenn du den Kram übersetzt und linkst?

von dasrotemopped (Gast)


Lesenswert?

>extern void MOTOR_PWM (uint16_t A, uint16_t B);
Schlüsselwort EXTERN vor einer Funktionsdeklaration kommt mir seltsam 
vor.
Was soll damit erreicht werden ?

Gruß,

dasrotemopped.

von Sebi (Gast)


Lesenswert?

ne hab wieder ERRORS noch WARNINGS oder MESSAGES

was ich nur komisch finde ist der Code bleibt ja gleich, ich packe ja 
nur die Funktion der Steuerung in eine externe c zur übersicht, der Code 
wird ja nicht verändert.

von Sebi (Gast)


Lesenswert?

Hab mal Probehalber das extern rausgenommen, ändern tut sich aber nix.

von dasrotemopped (Gast)


Lesenswert?

die frage bleibt, Was sollte damit erreicht werden ?

von Sebi (Gast)


Lesenswert?

extern ist für den Compiler nur ein Hinweis das die Funktion anderweitig 
noch benutzt wird.

von Georg G. (df2au)


Lesenswert?

Dann poste doch mal die erzeugten HEX-Files aus beiden Versionen. Dann 
kann man vergleichen.

von Dietrich L. (dietrichl)


Lesenswert?

Sebi schrieb:
> was ich nur komisch finde ist der Code bleibt ja gleich, ich packe ja
> nur die Funktion der Steuerung in eine externe c zur übersicht, der Code
> wird ja nicht verändert.

Hast Du auch sorgfältig und mehrfach kontrolliert, ob beim Zerteilen und 
Kopieren nicht doch irgend etwas schief gegangen ist?

von Dietrich L. (dietrichl)


Lesenswert?

Georg G. schrieb:
> Dann poste doch mal die erzeugten HEX-Files aus beiden Versionen. Dann
> kann man vergleichen.

Oder das Listing mit Maschinencode.

von Sebi (Gast)


Angehängte Dateien:

Lesenswert?

Hier sind die beiden.

von dasrotemopped (Gast)


Lesenswert?

>extern ist für den Compiler nur ein Hinweis das die Funktion anderweitig
noch benutzt wird.
eher nicht. das ist laut meinem Kernighan/Ritchie für Variablen, nicht 
Funktionen.
Darum vermute ich, das dein Programm ein Problem mit der Sichtbarkeit 
von Variablen hat.

>*** Globale Variablen ***
>uint16_t abstand = 0,rechts =0,links =0;

Global verstehst du warscheinlich auch anders als C.

void MOTOR_PWM (uint16_t A, uint16_t B)
{
  OCR1A = A;
  OCR1B = B;
}

A ist 16 bit, muss auf einem 8bitter OCR1A nicht einzeln in OCR1AL und 
OCRA1H beschrieben werden ?
Ist schon was länger her, als ich AVRs benutzt habe.

von Sebi (Gast)


Angehängte Dateien:

Lesenswert?

Hier hab ich auch mal das ganze als c Code.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

dasrotemopped schrieb:
>>extern void MOTOR_PWM (uint16_t A, uint16_t B);
> Schlüsselwort EXTERN vor einer Funktionsdeklaration kommt mir
> seltsam vor.
EXTERN ist auch kein SChlüsselwork; extern aber wohl.

> Was soll damit erreicht werden?

MOTOR_PWM hat external linkage.  Siehe etwa C99 §6.2.2 Linkage of 
Identifiers, Clause 5.

von Sebi (Gast)


Lesenswert?

Also wenn ich A und B als je als uin8_t angebe ändert sich nix.

mache ich es als AH und AL und füge die anschließend zusammen passiert 
auch nix anders.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

dasrotemopped schrieb:
> A ist 16 bit, muss auf einem 8bitter OCR1A nicht einzeln in OCR1AL und
> OCRA1H beschrieben werden ?

Nein.  Das ist ein Grund, C zu verwenden und nicht Assembler :-)

von dasrotemopped (Gast)


Lesenswert?

jetzt bin ich gespannt, woran es liegt !

von Georg G. (df2au)


Lesenswert?

Nun noch die Files HC_SR_04.h + c und USART.h + c, dann kann man es mal 
übersetzen und vergleichen.

von Georg G. (df2au)


Lesenswert?

dasrotemopped schrieb:
> A ist 16 bit, muss auf einem 8bitter OCR1A nicht einzeln in OCR1AL und
> OCRA1H beschrieben werden ?

Da passt der Compiler auf dich auf und macht es in der richtigen 
Reihenfolge.

von Sebi (Gast)


Angehängte Dateien:

Lesenswert?

Hier sind die 4.

von Jay K. (deeplyembedded)


Lesenswert?

dasrotemopped schrieb:
>>extern ist für den Compiler nur ein Hinweis das die Funktion anderweitig
> noch benutzt wird.
> eher nicht. das ist laut meinem Kernighan/Ritchie für Variablen, nicht
> Funktionen.
> Darum vermute ich, das dein Programm ein Problem mit der Sichtbarkeit
> von Variablen hat.
>
>>*** Globale Variablen ***
>>uint16_t abstand = 0,rechts =0,links =0;
>
> Global verstehst du warscheinlich auch anders als C.
>
> void MOTOR_PWM (uint16_t A, uint16_t B)
> {
>   OCR1A = A;
>   OCR1B = B;
> }
>
> A ist 16 bit, muss auf einem 8bitter OCR1A nicht einzeln in OCR1AL und
> OCRA1H beschrieben werden ?
> Ist schon was länger her, als ich AVRs benutzt habe.


extern gibt die Speicherklasse an und bei einer Funktionsdeklaration ist 
"extern" der Default, deshalb kann man ihn auch weglassen. Manche 
Programmierer schreiben den "extern" Klassifizierter explizit mit in die 
Funktionsdeklaration, um die Lesbarkeit zu verbessern.
Ein anderer Klassifizierer bei einer Funktionsdeklaratin wäre 
"static"..und jetzt kannst du mal raten, was der Unterschied zwischen 
extern und static ist ;-)

von Deuter des Willens K&Rs (Gast)


Lesenswert?

Johann L. schrieb:
> dasrotemopped schrieb:
>>>extern void MOTOR_PWM (uint16_t A, uint16_t B);
>> Schlüsselwort EXTERN vor einer Funktionsdeklaration kommt mir
>> seltsam vor.
> EXTERN ist auch kein SChlüsselwork; extern aber wohl.
>
>> Was soll damit erreicht werden?
>
> MOTOR_PWM hat external linkage.  Siehe etwa C99 §6.2.2 Linkage of
> Identifiers, Clause 5.

Nur mal so aus Interesse eines C-Standard-Juristen und weil Du hier 
einer der ausgefuchsteren C-Standard-Juristen bist.

Willst Du damit sagen, dass MOTOR_PWM ohnehin (also ohne das 
extern-Schlüsselwort) external linkage hat, also das Schlüsselwort 
überflüssig ist? So verstehe ich Absatz 5:

"5 If the declaration of an identifier for a function has no 
storage-class specifier, its linkage is determined exactly as if it were 
declared with the storage-class specifier extern. If the declaration 
of an identifier for an object has file scope and no storage-class 
specifier, its linkage is external."
(Hervorhebungen von mir).

Oder, willst Du lediglich erklären, was die Wirkung ist? Das ist 
zweifellos so richtig. Wobei man noch erwähnen könnte, dass das 
Schlüsselwort "extern" redundant ist.

Oder willst Du weder das eine noch das andere damit sagen?

Irgendwie irritiert mich das extern - habe ich in 30 Jahren weder 
verwendet noch vermisst (in Bezug auf Funktionen).
Es gibt entweder einen Prototyp; und der ist dann implizit extern, falls 
er nicht durch eine Definition in der selben Datei ersetzt wird. Oder er 
ist faktisch extern und der Linker meckert, falls er nicht doch noch 
irgendwo anders (in einem Objekt) die Definition entdeckt.

Aber mit dem Problem des TO scheint mir das alles nichts zu tun zu 
haben.

von Georg G. (df2au)


Lesenswert?

Welcher Prozessor ist das Ziel? Die, die in UART.C zulässig sind, werfen 
Fehler in MAIN.C.

von dasrotemopped (Gast)


Lesenswert?

nicht geraten, im C/C++ Referenz Buch nachgelesen (tatsächlich nicht 
gegooglet):
"Soll der Zugriff auf die Funktion nur aus Funktionen innerhalb des 
aktuellen Moduls heraus erfolgen dürfen, müssen Sie static angeben."

Raten ist nicht so meins ...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Deuter des Willens K&Rs schrieb:
> Willst Du damit sagen, dass MOTOR_PWM ohnehin (also ohne das
> extern-Schlüsselwort) external linkage hat, also das Schlüsselwort
> überflüssig ist?

Genau so ist es. Bei Funktionsdeklarationen ist "extern" implizit, es 
eigens hinzuschreiben überflüssig aber auch nicht störend.

von Deuter des Willens K&Rs (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Deuter des Willens K&Rs schrieb:
>> Willst Du damit sagen, dass MOTOR_PWM ohnehin (also ohne das
>> extern-Schlüsselwort) external linkage hat, also das Schlüsselwort
>> überflüssig ist?
>
> Genau so ist es. Bei Funktionsdeklarationen ist "extern" implizit, es
> eigens hinzuschreiben überflüssig aber auch nicht störend.

So sehe ich das auch (und schrieb das auch).
Meine Frage war, wie Johann das gemeint, was er mit seinem Beitrag 
beabsichtigt hat. Das selbe was ich denke, oder was anderes oder mehr?

Sagen wir mal, weil ich Johann zutraue, etwas auszusagen, was auch ich 
so sagen würde, aber das er damit etwas Anderes oder Zusätzliches sagen 
will, was ich nicht so sagen würde.

Kurz: Vielleicht kann ich da noch was lernen, was zwar nicht im 
Gegensatz zu meiner Ansicht steht, sie aber erweitert.

von Sebi (Gast)


Lesenswert?

Ist ein Atmega 16A.

ja die USART ist erstmal nur für eine kleine Auswahl an UC geschrieben, 
die ich selber nutze.

von Sebi (Gast)


Lesenswert?

Also die USART.h als auch die HC_SR_04.h laufen eigentlich ohne Probleme 
hab sie schon in meheren Projekten drin ohne das dort ein fehler erzeugt 
wird.

von Awesome (Gast)


Lesenswert?

Georg G. schrieb:
> werfen Fehler in MAIN.C.

Wie lauten diese Fehler?

von Sebi (Gast)


Lesenswert?

Hab mal weiter rum probiert, also SOLO läuft die MOTOR_PWM

von Sebi (Gast)


Lesenswert?

So Servo + MOTOR_PWM läuft auch O.o

von Deuter des Willens K&Rs (Gast)


Lesenswert?

Sebi schrieb:
> Hab mal weiter rum probiert, also SOLO läuft die MOTOR_PWM

In Summe denke ich, kann man plausibel vermuten, dass das Problem durch 
das bisher gezeigte von Deinem Code nicht verursacht wird. Zwar gibt es 
einige technisch etwas fragwürdige Details, aber sie sind nicht wirklich 
mit Deinem Problem in Verbindung zu bringen.

Ich schlage Dir vor, einmal das gesamte Projekt (je nach IDE also 
kompletten Projektpfad, makefiles etc. - Backupfiles der Editoren vorher 
löschen) als ZIP zu posten. Einmal in der Variante die geht und einmal 
in der Variante die nicht geht.

Dann kann das hier vielleicht jemand mal nachvollziehen - zumindest was 
das Compilieren und Linken angeht.

von Sebi (Gast)


Lesenswert?

Also jetzt versteh ich die Welt nicht. benutze ich alle 3 .h läuft es 
jetzt sobald ich jede if oder else auskommentiere.

setzte ich die void MOTOR_PWM einfach ins hauptprogramm läuft es auch 
mit if else.

von Sebastian S. (amateur)


Lesenswert?

Bau doch mal an verschiedenen Stellen Meldungen oder Fehler ein. Dann 
kannst Du feststellen ob der Compiler überall hinkommt.
Hast Du mal alle Zwischendateien gelöscht oder explizit einen rebuild 
all angestoßen?
Poste doch mal den Compileroutput.

von Sebi (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal die kompletten Datein

von Sebi (Gast)


Lesenswert?

------ Build started: Project: AUTONOM16AV1.22, Configuration: Debug AVR 
------
Build started.
Project "AUTONOM16AV1.22.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; 
('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "F:\Softwareentwicklung\Atmel Studio 
7\7.0\Vs\Compiler.targets" from project 
"G:\AtmelStudio\AUTONOM16AV1.22\AUTONOM16AV1.22\AUTONOM16AV1.22.cproj" 
(target "Build" depends on it):
  Task "RunCompilerTask"
    Shell Utils Path F:\Softwareentwicklung\Atmel Studio 
7\7.0\shellUtils
    F:\Softwareentwicklung\Atmel Studio 7\7.0\shellUtils\make.exe all 
--jobs 4 --output-sync
    make: Nothing to be done for 'all'.
  Done executing task "RunCompilerTask".
  Task "RunOutputFileVerifyTask"
        Program Memory Usage   :  1324 bytes   8,1 % Full
        Data Memory Usage     :  81 bytes   7,9 % Full
  Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "AUTONOM16AV1.22.cproj".
Target "PostBuildEvent" skipped, due to false condition; 
('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "F:\Softwareentwicklung\Atmel Studio 
7\7.0\Vs\Avr.common.targets" from project 
"G:\AtmelStudio\AUTONOM16AV1.22\AUTONOM16AV1.22\AUTONOM16AV1.22.cproj" 
(entry point):
Done building target "Build" in project "AUTONOM16AV1.22.cproj".
Done building project "AUTONOM16AV1.22.cproj".

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped 
==========

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Deuter des Willens K&Rs schrieb:
> Rufus Τ. F. schrieb:
>> Genau so ist es. Bei Funktionsdeklarationen ist "extern" implizit, es
>> eigens hinzuschreiben überflüssig aber auch nicht störend.
>
> So sehe ich das auch (und schrieb das auch).
> Meine Frage war, wie Johann das gemeint, was er mit seinem Beitrag
> beabsichtigt hat. Das selbe was ich denke, oder was anderes oder mehr?

Ich woollte lediglich klarstellen, dass das extern absolut ok ist und 
der TO nicht daran rundokern muss, nur weil dasrotemopped rumrät.

von Sebi (Gast)


Lesenswert?

Mal ne frage kann man den Timer 0 oder 2 bei einer F_CPU von 16 MHZ auf 
50 Hz runterfahren?
1
void timer2_servo_init()
2
{
3
  TCCR2 |= (1<<WGM21) | (1<<WGM20) | (1<<COM21) | (1<<CS22)| (1<<CS21) | (1<<CS20);  /* Fast PWM nicht invertiert (ORC2) */
4
  /* Presacaller 1:1024 Periodendauer 16,4ms ~ 61 HZ*/
5
  DDRD |= (1<<SERVO_PWM);
6
  SERVO_MITTE;
7
}

von Sebi (Gast)


Lesenswert?

Mal so eine frage am Rande könnte mal einer von euch auch mal das was 
nicht funktioniert in der Simulation fahren?

bei mir stehen da OCR2 , OCR1A, OCR1B dauerhaft auf 0

von Deuter des Willens K&Rs (Gast)


Lesenswert?

Johann L. schrieb:
> Deuter des Willens K&Rs schrieb:

>> Rufus Τ. F. schrieb:
[..,]

> Ich woollte lediglich klarstellen, dass das extern absolut ok ist und
> der TO nicht daran rundokern muss, nur weil dasrotemopped rumrät.

Aha. Dankeschön, Johann.

von A. S. (Gast)


Lesenswert?

Ich nehme an, Du hast auch schon probiert, die Funktion in der 
zusätzlichen Datei durch ein Zeichen umzubenennen und die 
Originalfunktion in main.c zusätzlich zu belassen. (so das wirklich nur 
der Ort der Funktion unterschiedlich ist.)

Wenn es dabei funktioniert, bleibt nur:

dasrotemopped schrieb:
> Darum vermute ich, das dein Programm ein Problem mit der Sichtbarkeit
> von Variablen hat.

und zwar, dass (aus welchen Gründen auch immer) OCR1A oder B (eine 
Header fehlt) an anderer Stelle gemappt wird. Korrektur: den kompletten 
Code bis zum letzten #include aus main.c auch in die neue C übernehmen, 
egal ob alles gebraucht wird. Falls nicht ok, auch das Makefile 
überprüfen.

von Deuter des Willens K&Rs (Gast)


Lesenswert?

Sebi schrieb:
> ------ Build started: Project: AUTONOM16AV1.22, Configuration: Debug AVR
> ------
> Build started.
[...]
> Build succeeded.
> ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped
> ==========

Es scheint so, als wenn Du kein Rebuild gestartet hast, sondern das 
Projekt schon "Up to date" war. Daher wird auch kein C-Compiler oder 
Linker aufgerufen. Und daher kann man auch keine Fehler oder Warnings 
sehen, noch die verwendeten Optionen.

Entweder Du lädst alle Source-Dateien und fügst überall eine Leerzeile 
oder so ein. (Irgendwas neutrales halt). Oder Du startest ausdrücklich 
ein "Rebuild". Was Dir leichter fällt.


Ich habe leider kein AVRStudio 7 und werde es mir, solange ich es 
vermeiden kann, auch nicht installieren. Daher kann ich Deine Projekte 
nicht kompilieren. Tut mir leid.
Aber vielleicht findet sich ja jemand.

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.