Externe .c bringt nur theater

Gast #4799006
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?
Gast
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.
Gast
>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.
Gast
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.
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?
Gast
>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.
Gast
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.
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 ;-)
Gast
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.
Gast
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 ...
Gast
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.
Gast
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.
Gast
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.
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.
Gast
------ 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 
==========
Persönliche Seite
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.
Gast
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
}
Gast
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
Gast
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.
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.