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?)?