Beim AVR mußt Du für Eingänge und Ausgänge verschiedene Register nehmen
(PINx, PORTx).
Open Drain Ausgänge realisiert man mit dem DDRx-Register
Um Bitvariablen zu definieren, muß man unter GCC Bitfelder benutzen,
dann gehts ganz einfach wie unter Keil C51:
1 | #include <avr\io.h>
|
2 | #include <inttypes.h>
|
3 | #include <stdio.h>
|
4 |
|
5 |
|
6 | struct bits {
|
7 | uint8_t b0:1;
|
8 | uint8_t b1:1;
|
9 | uint8_t b2:1;
|
10 | uint8_t b3:1;
|
11 | uint8_t b4:1;
|
12 | uint8_t b5:1;
|
13 | uint8_t b6:1;
|
14 | uint8_t b7:1;
|
15 | } __attribute__((__packed__));
|
16 |
|
17 |
|
18 | #define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
|
19 |
|
20 |
|
21 | #define scl SBIT(PORTC, 5)
|
22 | #define sda SBIT(DDRC, 4)
|
23 | #define sdain SBIT(PINC, 4)
|
24 | #define sdalevel SBIT(PORTC, 4)
|
25 |
|
26 | #define uchar unsigned char
|
27 |
|
28 |
|
29 | void I2C_write(uchar d)
|
30 | {
|
31 | uchar i;
|
32 | sdalevel = 0;
|
33 | scl = 0;
|
34 | for (i = 1; i <= 8; i++)
|
35 | {
|
36 | sda = !(d >> 7);
|
37 | scl = 1;
|
38 | d = d << 1; /* increase scl high time */
|
39 | scl = 0;
|
40 | }
|
41 | sda = 0; /* Release the sda line */
|
42 | scl = 0;
|
43 | scl = 1;
|
44 | if(sdain) printf("Ack bit missing %02X",(unsigned int)d);
|
45 | scl = 0;
|
46 | }
|
Peter
P.S.:
1 | d = d << 1; /* increase scl high time */
|
Dürfte beim AVR nicht reichen.
Außerdem verschiebt der AVR-GCC solche Intruktionen, da sie seiner
Meinung nach keinen Einfluß auf die Ausführung haben.
IO-Zugriffe stellen leider keine Barrieren für Reordering dar.