Forum: Compiler & IDEs i2c fleury lib Probleme


von benjamin (Gast)


Lesenswert?

Hallo zusammen,

ich bin gerade dabei ein digitalen Funktionsgenerator zu bauen. Die 
einzelnen Funktionsgruppen wurden schon ausgiebig getestet und 
funktionieren. Da ich früher mit BASCOM programmiert habe, habe ich mir 
nun endlich vorgenommen auf C umzusteigen.
Ich will nun über den I2C Bus mit  zwei PCF8574 eine PLL steuern. 
Vorneweg: Mit BASCOM funktioniert es. Man kann also ein HW Fehler 
ausschließen.
Benutzen tu ich die Lib von Fleury für den I2C.
Jedoch bleibe ich immer bei i2c_start() eine "1" zurück, also dass es 
nicht geklappt hat, den SLAVE anzusprechen.
1
#include <avr/io.h>
2
#include <pll.h>
3
#include <i2c.h>
4
#include <uart.h>
5
#include <stdlib.h>
6
7
#define PCF8574_1  0x40
8
#define PCF8574_2  0x42
9
10
void init_pll(void)
11
{  
12
  // MUX Pins an PortD auf Ausgänge schalten
13
  DDRD |= (1 << DDD4) | (1 << DDD5) | (1 << DDD6) | (1 << DDD7);
14
15
  // i2c Bus initialisieren
16
  i2c_init();
17
18
  // Pll auf niedrigste Frequenz setzen
19
  set_pll_frequency(1);  
20
}
21
22
void i2c_send_byte(unsigned char addr, unsigned char byte)
23
{
24
  unsigned char ret;
25
26
  ret = i2c_start(addr+I2C_WRITE);       
27
28
  if (ret) 
29
  {
30
      // Baustein nicht erreichbar
31
      i2c_stop();
32
  }else 
33
  {
34
      i2c_write(byte);                       
35
      i2c_stop();
36
  }
37
}
38
39
40
void set_pll_frequency(unsigned short multiplier)
41
{
42
  unsigned short divider = 1024;
43
  unsigned char mux = 10;
44
  unsigned char byte1 = 0;
45
  unsigned char byte2 = 0;
46
  unsigned short n;
47
  unsigned char tmp;
48
49
  while (divider * multiplier > 2000)
50
  {
51
    divider >>= 1;
52
    mux--;
53
  } 
54
55
  // divider * multiplier -> Zerlegen in die zwei PCF8574 Bytes für PLL und über i2c wegschicken
56
  n = divider * multiplier;
57
58
  if (n % 2 != 0)
59
  {
60
    byte1 = n % 2;
61
  }
62
63
  n = n / 2;
64
65
  if (n / 1000 > 0)
66
  {
67
    tmp = n / 1000;
68
    byte1 += (tmp << 1);
69
    n -= tmp * 1000;
70
  }
71
  
72
  if (n / 100 > 0)
73
  {
74
    tmp = n / 100;
75
    byte2 += (tmp << 4);
76
    n -= tmp * 100;
77
  }
78
  
79
  if (n / 10 > 0)
80
  {
81
    tmp = n / 10;
82
    byte2 += tmp;
83
    n -= tmp * 10;
84
  }
85
  
86
  if (n / 1 > 0)
87
  {
88
    tmp = n / 1;
89
    byte1 += (tmp << 4);
90
    n -= tmp * 1;
91
  }
92
93
  /*char num[9];
94
  
95
  itoa(byte1, num, 10);
96
  uart_puts(num);
97
98
  itoa(byte2, num, 10);
99
  uart_puts(num);*/
100
  
101
  i2c_send_byte(PCF8574_1, byte1);
102
  i2c_send_byte(PCF8574_2, byte2);    
103
104
  // mux -> MUX Ports setzen
105
  if (mux & 0x01)
106
  {
107
    PORTD |= (1 << PD4);
108
  }
109
  if (mux & 0x02)
110
  {
111
    PORTD |= (1 << PD5);
112
  }
113
  if (mux & 0x04)
114
  {
115
    PORTD |= (1 << PD6);
116
  }
117
  if (mux & 0x08)
118
  {
119
    PORTD |= (1 << PD7);
120
  }
121
}
1
/*************************************************************************
2
* Title:    I2C master library using hardware TWI interface
3
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
4
* File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6
* Target:   any AVR device with hardware TWI 
7
* Usage:    API compatible with I2C Software Library i2cmaster.h
8
**************************************************************************/
9
#include <inttypes.h>
10
#include <compat/twi.h>
11
#include <uart.h>
12
13
#include <i2c.h>
14
15
16
/* define CPU frequency in Mhz here if not defined in Makefile */
17
#ifndef F_CPU
18
#define F_CPU 16000000UL
19
#endif
20
21
/* I2C clock in Hz */
22
#define SCL_CLOCK  100000L
23
24
25
/*************************************************************************
26
 Initialization of the I2C bus interface. Need to be called only once
27
*************************************************************************/
28
void i2c_init(void)
29
{
30
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
31
  
32
  TWSR = 0;                         /* no prescaler */
33
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
34
  //TWSR = 1;
35
  //TWBR = 192;
36
37
}/* i2c_init */
38
39
40
/*************************************************************************  
41
  Issues a start condition and sends address and transfer direction.
42
  return 0 = device accessible, 1= failed to access device
43
*************************************************************************/
44
unsigned char i2c_start(unsigned char address)
45
{
46
    uint8_t   twst;
47
48
  // send START condition
49
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
50
51
  // wait until transmission completed
52
  while(!(TWCR & (1<<TWINT)));
53
  
54
  // check value of TWI Status Register. Mask prescaler bits.
55
  twst = TW_STATUS & 0xF8;
56
  if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
57
58
             !HIERHER KOMM ICH NICHT!
59
60
  // send device address
61
  TWDR = address;
62
  TWCR = (1<<TWINT) | (1<<TWEN);
63
64
  // wail until transmission completed and ACK/NACK has been received
65
  while(!(TWCR & (1<<TWINT)));
66
  
67
  // check value of TWI Status Register. Mask prescaler bits.
68
  twst = TW_STATUS & 0xF8;
69
  if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
70
  
71
  return 0;
72
73
}/* i2c_start */
74
75
76
/*************************************************************************
77
 Issues a start condition and sends address and transfer direction.
78
 If device is busy, use ack polling to wait until device is ready
79
 
80
 Input:   address and transfer direction of I2C device
81
*************************************************************************/
82
void i2c_start_wait(unsigned char address)
83
{
84
    uint8_t   twst;
85
86
87
    while ( 1 )
88
    {
89
      // send START condition
90
      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
91
    
92
      // wait until transmission completed
93
      while(!(TWCR & (1<<TWINT)));
94
    
95
      // check value of TWI Status Register. Mask prescaler bits.
96
      twst = TW_STATUS & 0xF8;
97
      if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
98
    
99
      // send device address
100
      TWDR = address;
101
      TWCR = (1<<TWINT) | (1<<TWEN);
102
    
103
      // wail until transmission completed
104
      while(!(TWCR & (1<<TWINT)));
105
    
106
      // check value of TWI Status Register. Mask prescaler bits.
107
      twst = TW_STATUS & 0xF8;
108
      if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
109
      {          
110
          /* device busy, send stop condition to terminate write operation */
111
          TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
112
          
113
          // wait until stop condition is executed and bus released
114
          while(TWCR & (1<<TWSTO));
115
          
116
          continue;
117
      }
118
      //if( twst != TW_MT_SLA_ACK) return 1;
119
      break;
120
     }
121
122
}/* i2c_start_wait */
123
124
125
/*************************************************************************
126
 Issues a repeated start condition and sends address and transfer direction 
127
128
 Input:   address and transfer direction of I2C device
129
 
130
 Return:  0 device accessible
131
          1 failed to access device
132
*************************************************************************/
133
unsigned char i2c_rep_start(unsigned char address)
134
{
135
    return i2c_start( address );
136
137
}/* i2c_rep_start */
138
139
140
/*************************************************************************
141
 Terminates the data transfer and releases the I2C bus
142
*************************************************************************/
143
void i2c_stop(void)
144
{
145
    /* send stop condition */
146
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
147
  
148
  // wait until stop condition is executed and bus released
149
  while(TWCR & (1<<TWSTO));
150
151
}/* i2c_stop */
152
153
154
/*************************************************************************
155
  Send one byte to I2C device
156
  
157
  Input:    byte to be transfered
158
  Return:   0 write successful 
159
            1 write failed
160
*************************************************************************/
161
unsigned char i2c_write( unsigned char data )
162
{  
163
    uint8_t   twst;
164
    
165
  // send data to the previously addressed device
166
  TWDR = data;
167
  TWCR = (1<<TWINT) | (1<<TWEN);
168
169
  // wait until transmission completed
170
  while(!(TWCR & (1<<TWINT)));
171
172
  // check value of TWI Status Register. Mask prescaler bits
173
  twst = TW_STATUS & 0xF8;
174
  if( twst != TW_MT_DATA_ACK) return 1;
175
  return 0;
176
177
}/* i2c_write */
178
179
180
/*************************************************************************
181
 Read one byte from the I2C device, request more data from device 
182
 
183
 Return:  byte read from I2C device
184
*************************************************************************/
185
unsigned char i2c_readAck(void)
186
{
187
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
188
  while(!(TWCR & (1<<TWINT)));    
189
190
    return TWDR;
191
192
}/* i2c_readAck */
193
194
195
/*************************************************************************
196
 Read one byte from the I2C device, read is followed by a stop condition 
197
 
198
 Return:  byte read from I2C device
199
*************************************************************************/
200
unsigned char i2c_readNak(void)
201
{
202
  TWCR = (1<<TWINT) | (1<<TWEN);
203
  while(!(TWCR & (1<<TWINT)));
204
  
205
    return TWDR;
206
207
}/* i2c_readNak */

Brauch ihr noch etwas zur hoffentlich erfolgreichen Fehleranalyse? Ich 
bin echt am verzweifeln mittlerweile.

Voller Hoffnung,
Benjamin

von Oliver (Gast)


Lesenswert?

>Brauch ihr noch etwas zur hoffentlich erfolgreichen Fehleranalyse?

Wie wärs mit der Funktion main(). Ohne die geht eigentlich gar nichts.

Oliver

von benjamin (Gast)


Lesenswert?

main.c sieht ganz unspektakulär aus:
1
#include <pll.h>
2
#include <uart.h>
3
#include <avr/interrupt.h>
4
5
#ifndef F_CPU
6
#define F_CPU 16000000UL
7
#endif
8
9
#define UART_BAUD_RATE      19200
10
11
void init(void)
12
{
13
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
14
  sei();
15
16
  init_pll();
17
}
18
19
int main(void)
20
{  
21
22
  init();
23
  
24
    while (1)
25
  {
26
27
  }
28
29
  return 0;
30
}

Habt ihr vielleicht eine Idee, an was es liegen könnte?

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.