Forum: Mikrocontroller und Digitale Elektronik M328: einzelne Bytes über I2C an Slave senden


von Ben (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich möchte von einem M328 als Master über I2C hin und wieder Bytes an 
einen Slave mit der Adresse 0xA0 senden. Es sollen einfach nur einzelne 
Bytes vom Master an den Slave gesendet werden.

Als Hilfe habe ich mir das Buch "AVR" von Florian Schäffer besorgt.
Dazu gehört ein Programm, das ein Eeprom beschreiben und auslesen kann. 
Das Programm ist für meine Zwecke natürlich oversized.
Es befindet sich für Anschauungszwecke aber im Anhang.

Das Programm, das ich daraus zusammengestellt habe, sieht so aus:
1
/* I²C (TWI) Bus
2
 *
3
 * Sendet Werte (Bytes) an einen Slave
4
 *
5
 */
6
7
#include <avr/io.h>
8
#include <util/delay.h>
9
10
#define BASEADR    0xA0          // Adresse des Slaves
11
#define TW_READ    1    // LSB bei Busadresse zur Kennzeichnung eines Lesezugriffes
12
#define TW_WRITE  0    // LSB bei Busadresse zur Kennzeichnung eines Schreibzugriffes 
13
14
void delay_ms(uint16_t);
15
void i2c_start(void);
16
void i2c_stop(void);
17
void i2c_send(uint8_t) ;
18
int main(void);
19
20
// wartet ms Millisekunden
21
void delay_ms(uint16_t ms)
22
{
23
  for(uint16_t t=0; t<=ms; t++)
24
    _delay_ms(1); 
25
}
26
27
/**
28
  @brief  Startanweisung senden
29
  @param  none
30
  @return  none
31
*/
32
33
void i2c_start(void) 
34
{
35
  TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);   // send start condition
36
  while ((TWCR & _BV(TWINT)) == 0) ;     // wait for transmission
37
}
38
39
/**
40
  @brief  Stopanweisung senden
41
  @param  none
42
  @return  none
43
*/
44
45
void i2c_stop(void) 
46
{
47
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);    // send stop condition
48
}
49
50
/**
51
  @brief  Datenbyte senden
52
  @param  Byte
53
  @return  none
54
*/
55
void i2c_send(uint8_t DataByte) // FRAGE: wird hier der Inhalt der Variable wert in die Variable DataByte "umgefüllt" ???
56
{
57
  TWDR = DataByte;
58
  TWCR = _BV(TWINT) | _BV(TWEN);       // clear interrupt to start transmission
59
  while ((TWCR & _BV(TWINT)) == 0) ;     // wait for transmission
60
}
61
62
/**
63
  @brief  Datenbyte empfangen
64
  @param  ACK senden (1) oder nicht (0)
65
  @return  none
66
*/
67
68
69
70
int main(void)
71
{
72
  uint8_t wert=0;
73
  
74
  TWBR = (F_CPU / 100000UL - 16) / 2;    // TWI Baudrate 100KHz
75
76
  
77
  while (1) //
78
  {
79
80
    i2c_start();
81
    i2c_send(BASEADR | TW_WRITE); 
82
83
84
    i2c_send(wert);
85
    i2c_stop();
86
    _delay_ms(100);      // kurz warten
87
    
88
    wert++; // Variable wert um 1 erhöhen
89
90
  }
91
92
  return 0;
93
}

Kommt das so in etwa hin?
Gesendet werden sollen in diesem Programm die Zahlen von 0 bis 255 und 
dann nach dem Überschlag wieder die Zahlen von 0 bis 255 und immer so 
weiter.

Noch eine Frage zur Hardware: müssen an die beiden Pins SDA und SCL vom 
Master noch Widerstände nach 5V geschaltet werden oder werden hier die 
internen Pullups dafür verwendet (oder müsste man das noch von Hand 
einstellen?)?

von Achim H. (pluto25)


Lesenswert?

Ben schrieb:
> werden hier die internen Pullups dafür verwendet
Die reichen nicht, da sind schon externe nötig ca 4k7.
Obwohl das Datenblatt meint:
"The internal pull-ups can in some systems eliminate the need for 
external ones."
wars bei mir sehr unzuverlässig ohne die 4k7

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.