-
Notifications
You must be signed in to change notification settings - Fork 0
/
AT24C32.c
175 lines (157 loc) · 4.57 KB
/
AT24C32.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <util/delay.h>
#include "AT24C32.h"
#include "usart.h"
#include "i2c.h"
void AT24C32_send_16_bit_address(uint16_t address) {
i2c_send((uint8_t) (address >> 8)); /* most significant byte */
i2c_send((uint8_t) address); /* least significant byte */
}
void AT24C32_clear_all(void) {
uint8_t i;
uint16_t page_address = 0;
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
while (page_address < AT24C32_BYTES_MAX) {
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(page_address);
for (i = 0; i < AT24C32_BYTES_PER_PAGE; i++) {
i2c_send(255);
}
i2c_stop();
_delay_ms(20); // write cycle time
page_address += AT24C32_BYTES_PER_PAGE;
}
i2c_stop();
}
void AT24C32_byte_write(uint16_t address, uint8_t byte) {
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_send(byte);
i2c_stop();
_delay_ms(20); // write cycle time
}
void AT24C32_word_write(uint16_t address, uint16_t word) {
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_send((uint8_t) (word >> 8));
i2c_send((uint8_t) word);
i2c_stop();
_delay_ms(20); // write cycle time
}
/* void AT24C32_page_write(uint16_t address, const uint8_t my_page[]) {
if ((address % AT24C32_BYTES_PER_PAGE) == 0) {
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
for (i = 0; i < AT24C32_BYTES_PER_PAGE; i++) {
i2c_send(my_page[i]);
}
i2c_stop();
}
else {
print_string("Invalid page address! Must be a multiple of 32.\r\n");
}
} */
void AT24C32_ascii_sequential_write(uint16_t address, const char my_string[]) {
uint32_t i = 0;
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
while (my_string[i]) {
if ((i > 0) & ((i % AT24C32_BYTES_PER_PAGE) == 0)) {
address += AT24C32_BYTES_PER_PAGE;
i2c_stop();
_delay_ms(20); // write cycle time
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_send(my_string[i]);
i++;
}
else {
i2c_send(my_string[i]);
i++;
}
}
i2c_stop();
_delay_ms(20); // write cycle time
}
uint8_t AT24C32_current_address_read(void) {
uint8_t byte;
i2c_start();
i2c_send(AT24C32_ADDRESS_R);
byte = i2c_read_no_ack();
i2c_stop();
return (byte);
}
uint8_t AT24C32_random_read(uint16_t address) {
uint8_t byte;
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_start();
i2c_send(AT24C32_ADDRESS_R);
byte = i2c_read_no_ack();
i2c_stop();
return (byte);
}
/*
C programming does not allow to return an entire array as an argument to a function.
However, you can return a pointer to an array by specifying the array's name without an index.
Second point to remember is that C does not advocate to return the address of a local variable
to outside of the function, so you would have to define the local variable as static variable.
Here I cannot use static because storage size of 'byte' isn't constant. But it compiles with
an warning. However, if I call this function, the warning disappears.
uint8_t * AT24C32_sequential_read(uint16_t address, uint16_t how_many_bytes) {
uint16_t i;
uint8_t byte[how_many_bytes];
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_start();
i2c_send(AT24C32_ADDRESS_R);
for (i = 0; i < how_many_bytes; i++) {
if (i == (how_many_bytes - 1)){
byte[i] = i2c_read_no_ack();
}
else {
byte[i] = i2c_read_ack();
}
}
i2c_stop();
return (byte);
}
Now inside main.c,
uint16_t address = 0;
uint16_t how_many_bytes = 569;
uint16_t i;
uint8_t *p;
p = AT24C32_sequential_read(address, how_many_bytes);
for ( i = 0; i < how_many_bytes; i++ ) {
transmit_byte(*(p + i));
}
This function can do only so much because m168 has only got 2KBytes of internal SRAM and
I can at best read 900-1000 bytes/character off of the i2c memory, depending on what else is running,
before the MCU runs off its RAM memory.
However, an easy solution can be made: dont output anything, just print from within...
*/
void AT24C32_sequential_read(uint16_t address, uint16_t how_many_bytes) {
uint16_t i;
i2c_start();
i2c_send(AT24C32_ADDRESS_W);
AT24C32_send_16_bit_address(address);
i2c_start();
i2c_send(AT24C32_ADDRESS_R);
for (i = 0; i < how_many_bytes; i++) {
if (i == (how_many_bytes - 1)){
transmit_byte(i2c_read_no_ack());
}
else {
transmit_byte(i2c_read_ack());
}
}
i2c_stop();
}