Forum: Mikrocontroller und Digitale Elektronik undefined reference to function bei Atmel I2C-Funktion; warum?


von Matthias (Gast)


Lesenswert?

Hallo,

ich möchte im Atmel-Studio den I2C eines Atmega16 einsetzen.
Dazu gibt es vom Atmel folgende Funktionen:
https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591794

Der Header sieht die folgenden funktionalitäte vor:
1
void TWI_Master_Initialise( void );
2
unsigned char TWI_Transceiver_Busy( void );
3
unsigned char TWI_Get_State_Info( void );
4
void TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char );
5
void TWI_Start_Transceiver( void );
6
unsigned char TWI_Get_Data_From_Transceiver( unsigned char *, unsigned char );


Nun scheitert es am Einsatz,

die Dateien sind im Projekt und werden auch z.b. beim include des 
Header-Files und beim schreiben der Funktionen selbst vom AtmelStudio 
vervollständigt

der header wurde included:
#include "TWI_Master.h"

Aufgerufen wird z.b. so:
TWI_Master_Initialise();

nun gibt es diese Meldung:
Error  1  undefined reference to `TWI_Master_Initialise()'

Ich habe auch eigene Funktionen z.b. zum UART geschrieben welche 
ebenfalls durch eine Header-File einbezogen werden und deren Aufruf auch 
funktuioniert:
Include:
#include "RS232.h"

In der Main:
SendUART("Q");

Im Header-File "RS232.h":
void SendUART(char* zeig);

Da funktioniert aber eben alles.

hat jemand vielleicht eine Idee, was für eine Art von Problem es bei 
Nutzung der "Fertigen" funktionen geben könnte? Für mich sehen beide 
Includes sowie Aufrufe identisch aus...

Viele Grüße, Matthias

von Beo Bachta (Gast)


Lesenswert?

Matthias schrieb:
> der header wurde included:
> #include "TWI_Master.h"

Du wirst wohl auch die Datei >TWI_Master.c< in dein Projekt
aufnehemn müssen, die Header-Datei alleine reicht nicht.

von Matthias (Gast)


Lesenswert?

Beo Bachta schrieb:
> Du wirst wohl auch die Datei >TWI_Master.c< in dein Projekt
> aufnehemn müssen, die Header-Datei alleine reicht nicht.

Ja, sie ist auch drinn...

Hier mal der Komplette Code:
1
#ifndef F_CPU
2
#define F_CPU 1000000UL
3
#endif
4
5
6
#include <util/delay.h>
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include "RS232.h"
10
#include "TWI_Master.h"
11
12
void InituC()
13
{
14
  DDRD = 0xf2;   //Ausgang für 5A-LoW-Treiber, Ausgang für RS232-TX
15
  DDRC = 0x00;   //I2C, Periph/uc = input
16
  DDRB = 0x00;   //kein SPI oder externe eingänge
17
  DDRA = 0x00;   //Keine Analog-Eingang nutzung
18
  sei();         //Global IRQ-Enable
19
}
20
21
int main(void)
22
{
23
  TWI_Master_Initialise();
24
  InituC();
25
  InitUART();
26
  unsigned char write_addr0[2] ={0xd0,0x00};
27
    while(1)
28
    {
29
    _delay_ms(1000);
30
    TWI_Start_Transceiver_With_Data(write_addr0 , 2);
31
    _delay_ms(1000);
32
                SendUART("b");
33
    }
34
}

Und in der TWI-Master.h:
1
void TWI_Master_Initialise( void );
2
unsigned char TWI_Transceiver_Busy( void );
3
unsigned char TWI_Get_State_Info( void );
4
void TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char );
5
void TWI_Start_Transceiver( void );
6
unsigned char TWI_Get_Data_From_Transceiver( unsigned char *, unsigned char );

Diese Funktionen sind für den Linker nicht auffindbar.

Andererseits in der RS232.h:
1
void InitUART();
2
void SendUART(char* zeig);
3
void ReceiveUART();
Die gehen alle und ich sehe keinen Unterschied oder etwas was bei den 
I2C-Funktionen fehlen sollte.

von Oliver S. (oliverso)


Lesenswert?

Matthias schrieb:
> Ja, sie ist auch drinn...

Dann halt nicht richtig...

Oliver

von Beo Bachta (Gast)


Lesenswert?

Matthias schrieb:
> Ja, sie ist auch drinn...

Das sieht man erst wirklich wenn du das komplette Projekt zeigst.

> Hier mal der Komplette Code:

Das ist nur die Datei main.c (vermutlich).

von Beo Bachta (Gast)


Lesenswert?

Matthias schrieb:
> und ich sehe keinen Unterschied oder etwas was bei den
> I2C-Funktionen fehlen sollte.

Eben gerade der ausführbare Code fehlt, und nicht nur die Prototypen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Matthias schrieb:
> Und in der TWI-Master.h:

 Das sind Deklarationen.
 Und wo befinden sich die tatsächlichen Routinen?

: Bearbeitet durch User
von Matthias (Gast)


Lesenswert?

Bisher gezeicht habe ich die Main.c

Die tatsächlichen Routinen sind in der TWI-Matser.c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "TWI_Master.h"
4
5
static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
6
static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
7
static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.
8
9
union TWI_statusReg TWI_statusReg = {0};            // TWI_statusReg is defined in TWI_Master.h
10
11
/****************************************************************************
12
Call this function to set up the TWI master to its initial standby state.
13
Remember to enable interrupts from the main application after initializing the TWI.
14
****************************************************************************/
15
void TWI_Master_Initialise(void)
16
{
17
  TWBR = TWI_TWBR;                                  // Set bit rate register (Baud rate). Defined in header file.Driver presumes prescaler to be 00.                                
18
  TWDR = 0xFF;                                      // Default content = SDA released.
19
  TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins.
20
         (0<<TWIE)|(0<<TWINT)|                      // Disable Interrupt.
21
         (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.
22
         (0<<TWWC);                                 //
23
}    
24
    
25
/****************************************************************************
26
Call this function to test if the TWI_ISR is busy transmitting.
27
****************************************************************************/
28
unsigned char TWI_Transceiver_Busy( void )
29
{
30
  return ( TWCR & (1<<TWIE) );                  // IF TWI Interrupt is enabled then the Transceiver is busy
31
}
32
33
/****************************************************************************
34
Call this function to fetch the state information of the previous operation. The function will hold execution (loop)
35
until the TWI_ISR has completed with the previous operation. If there was an error, then the function 
36
will return the TWI State code. 
37
****************************************************************************/
38
unsigned char TWI_Get_State_Info( void )
39
{
40
  while ( TWI_Transceiver_Busy() );             // Wait until TWI has completed the transmission.
41
  return ( TWI_state );                         // Return error state.
42
}
43
44
/****************************************************************************
45
Call this function to send a prepared message. The first byte must contain the slave address and the
46
read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read
47
from the slave. Also include how many bytes that should be sent/read including the address byte.
48
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
49
then initialize the next operation and return.
50
****************************************************************************/
51
void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize )
52
{
53
  unsigned char temp;
54
55
  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
56
57
  TWI_msgSize = msgSize;                        // Number of data to transmit.
58
  TWI_buf[0]  = msg[0];                         // Store slave address with R/W setting.
59
  if (!( msg[0] & (TRUE<<TWI_READ_BIT) ))       // If it is a write operation, then also copy data.
60
  {
61
    for ( temp = 1; temp < msgSize; temp++ )
62
      TWI_buf[ temp ] = msg[ temp ];
63
  }
64
  TWI_statusReg.all = 0;      
65
  TWI_state         = TWI_NO_STATE ;
66
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
67
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interrupt and clear the flag.
68
         (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
69
         (0<<TWWC);                             //
70
}
71
72
/****************************************************************************
73
Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.
74
The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
75
then initialize the next operation and return.
76
****************************************************************************/
77
void TWI_Start_Transceiver( void )
78
{
79
  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
80
  TWI_statusReg.all = 0;      
81
  TWI_state         = TWI_NO_STATE ;
82
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
83
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interrupt and clear the flag.
84
         (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
85
         (0<<TWWC);                             //
86
}
87
88
/****************************************************************************
89
Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call
90
TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the
91
data when they have arrived. Include a pointer to where to place the data and the number of bytes
92
requested (including the address field) in the function call. The function will hold execution (loop)
93
until the TWI_ISR has completed with the previous operation, before reading out the data and returning.
94
If there was an error in the previous transmission the function will return the TWI error code.
95
****************************************************************************/
96
unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )
97
{
98
  unsigned char i;
99
100
  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
101
102
  if( TWI_statusReg.lastTransOK )               // Last transmission competed successfully.              
103
  {                                             
104
    for ( i=0; i<msgSize; i++ )                 // Copy data from Transceiver buffer.
105
    {
106
      msg[ i ] = TWI_buf[ i ];
107
    }
108
  }
109
  return( TWI_statusReg.lastTransOK );                                   
110
}
111
112
// ********** Interrupt Handlers ********** //
113
/****************************************************************************
114
This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;
115
that is whenever a TWI event has occurred. This function should not be called directly from the main
116
application.
117
****************************************************************************/
118
ISR(TWI_vect)
119
{
120
  static unsigned char TWI_bufPtr;
121
  
122
  switch (TWSR)
123
  {
124
    case TWI_START:             // START has been transmitted  
125
    case TWI_REP_START:         // Repeated START has been transmitted
126
      TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
127
    case TWI_MTX_ADR_ACK:       // SLA+W has been transmitted and ACK received
128
    case TWI_MTX_DATA_ACK:      // Data byte has been transmitted and ACK received
129
      if (TWI_bufPtr < TWI_msgSize)
130
      {
131
        TWDR = TWI_buf[TWI_bufPtr++];
132
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
133
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to send byte
134
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
135
               (0<<TWWC);                                 //  
136
      }else                    // Send STOP after last byte
137
      {
138
        TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully. 
139
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
140
               (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
141
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
142
               (0<<TWWC);                                 //
143
      }
144
      break;
145
    case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK transmitted
146
      TWI_buf[TWI_bufPtr++] = TWDR;
147
    case TWI_MRX_ADR_ACK:       // SLA+R has been transmitted and ACK received
148
      if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
149
      {
150
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
151
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to read next byte
152
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
153
               (0<<TWWC);                                 //  
154
      }else                    // Send NACK after next reception
155
      {
156
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
157
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag to read next byte
158
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
159
               (0<<TWWC);                                 // 
160
      }    
161
      break; 
162
    case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK transmitted
163
      TWI_buf[TWI_bufPtr] = TWDR;
164
      TWI_statusReg.lastTransOK = TRUE;                 // Set status bits to completed successfully. 
165
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
166
             (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
167
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
168
             (0<<TWWC);                                 //
169
      break;      
170
    case TWI_ARB_LOST:          // Arbitration lost
171
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
172
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interrupt and clear the flag
173
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
174
             (0<<TWWC);                                 //
175
      break;
176
    case TWI_MTX_ADR_NACK:      // SLA+W has been transmitted and NACK received
177
    case TWI_MRX_ADR_NACK:      // SLA+R has been transmitted and NACK received    
178
    case TWI_MTX_DATA_NACK:     // Data byte has been transmitted and NACK received
179
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
180
    default:     
181
      TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.
182
                                                        // Reset TWI Interface
183
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
184
             (0<<TWIE)|(0<<TWINT)|                      // Disable Interrupt
185
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
186
             (0<<TWWC);                                 //
187
  }
188
}

von Beo Bachta (Gast)


Lesenswert?

Matthias schrieb:
> Die tatsächlichen Routinen sind in der TWI-Matser.c

Und diese muss in dein Projekt eingebunden sein, ich schrieb
es schon.

Beo Bachta schrieb:
> Du wirst wohl auch die Datei >TWI_Master.c< in dein Projekt
> aufnehemn müssen, die Header-Datei alleine reicht nicht.

Zwei Dinge müssen für die Datei erfüllt sein:

- Sie muss im Projektverzeichnis liegen
- Sie muss im Projekt-Baum eingetragen sein

Solange du dein Projekt nicht zeigst können wir es nicht überprüfen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Matthias schrieb:
> Die tatsächlichen Routinen sind in der TWI-Matser.c

Matthias schrieb:
> Beo Bachta schrieb:
>> Du wirst wohl auch die Datei >TWI_Master.c< in dein Projekt
>> aufnehemn müssen, die Header-Datei alleine reicht nicht.
>
> Ja, sie ist auch drinn...

 Glaube ich nicht...

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

Beo Bachta schrieb:
> Und diese muss in dein Projekt eingebunden sein, ich schrieb
> es schon.

Aber ist sie es nicht, wenn sie Rechts

Beo Bachta schrieb:
> Zwei Dinge müssen für die Datei erfüllt sein:
>
> - Sie muss im Projektverzeichnis liegen
> - Sie muss im Projekt-Baum eingetragen sein

Die sehe ich beide als erfüllt an, siehe Anhang.

von pegel (Gast)


Lesenswert?

Sieht richtig aus.
Gab es eine Fehlermeldung bzw. lässt die sich einzeln compilieren?

Rechte Maustaste oder Ctrl+F7 auf der Datei.

von Matthias (Gast)


Lesenswert?

pegel schrieb:
> Sieht richtig aus.
> Gab es eine Fehlermeldung bzw. lässt die sich einzeln compilieren?
>
> Rechte Maustaste oder Ctrl+F7 auf der Datei.

Einzeln lässt dich alles Compilieren, ohne einen Fehler oder Warnungen.

von pegel (Gast)


Lesenswert?

Hast Du schon probiert AS zu schliessen und wieder zu öffnen?
Vielleicht hat er die Datei einfach nicht richtig in das Projekt 
eingefügt.

So etwas soll früher vorgekommen sein.

von Beo Bachta (Gast)


Lesenswert?

Vermutlich ein Problem durch Vermischung von C++ Projekt
und C++ / C Dateien.

Kann man nur sehen/klären wenn das ganze Projekt vorhanden ist.

von pegel (Gast)


Lesenswert?

Beo Bachta schrieb:
> Vermutlich ein Problem durch Vermischung von C++ Projekt
> und C++ / C Dateien.

Möglich. Denn:
[/c]
#ifdef __cplusplus
extern "C" {
#endif
[/c]

gibt es nicht.

von pegel (Gast)


Lesenswert?

Sch... Falsche Formatierung.

Aber ihr wisst schon.

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

pegel schrieb:
> Hast Du schon probiert AS zu schliessen und wieder zu öffnen?
> Vielleicht hat er die Datei einfach nicht richtig in das Projekt
> eingefügt.
>
> So etwas soll früher vorgekommen sein.

Ja, leider ändert das nichts.

Beo Bachta schrieb:
> Kann man nur sehen/klären wenn das ganze Projekt vorhanden ist.

Also daran soll es nicht scheitern...

Hab es gelöst, indem ich den TWI aus dem Projekt entfernt habe, die 
datei zu .cpp umbenannt habe und sie wieder neu ins Projekt eingefügt 
habe.
--> 0-Errors / 0-Warnings

von pegel (Gast)


Lesenswert?

Matthias schrieb:
> Hab es gelöst, indem ich den TWI aus dem Projekt entfernt habe, die
> datei zu .cpp umbenannt habe und sie wieder neu ins Projekt eingefügt
> habe.

In AS7 geht es auch.
Habe im Solution Explorer die Datei einfach direkt umbenannt.

von Thomas Z. (usbman)


Lesenswert?

Matthias schrieb:
> Hab es gelöst, indem ich den TWI aus dem Projekt entfernt habe, die
> datei zu .cpp umbenannt habe und sie wieder neu ins Projekt eingefügt
> habe.

damit arbeitest du dich aber nur die falschen Header files rum.
Wie weiter oben ja schon angemerkt fehlen einfach im h file die 
entsprechenden c++ guards. Die sind immer dann notwendig werden wenn c 
Dateien in einem CPP Projekt verwendet werden.

Thomas

von pegel (Gast)


Lesenswert?

Thomas Z. schrieb:
> fehlen einfach im h file die entsprechenden c++ guards

Gerade probiert, Atmel Studio kommt damit klar.
Das ist die sauberste Lösung.

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.