Externe .c bringt nur theater

Gast #4799006
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?
Gast #4799018
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.
Gast #4799039
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.
Gast #4799089
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.
#4799132
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 ;-)
Gast #4799137
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.
Gast #4799143
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 ...
Gast #4799149
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.
Gast #4799168
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.
Gast #4799173
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.
Gast #4799180
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 
==========
Persönliche Seite #4799206
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.
Gast #4799229
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
}
Gast #4799305
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.
Gast #4799310
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.

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