Skip to content

Commit 4a080dc

Browse files
committed
Enhance I2C initialization with detailed configuration constants and improve internal state checks for better error handling
1 parent c0a1107 commit 4a080dc

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

include/i2c.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,22 @@
44
#include "common.h"
55
#include <stdint.h>
66

7-
/* Initialize I2C Controller
8-
I2C Frequency = (100 kHz) / (2 ^ clkdiv)
9-
Max frequency clkdiv = b000, 100kHz
10-
Min frequency clkdiv = b111, 781.25 Hz
11-
*/
7+
/*
8+
* Configuration Constants
9+
* These define the behavior and timing characteristics of the I2C interface
10+
*/
11+
#define I2C_POLL_TIMEOUT 2000 // Maximum cycles to wait during I2C operations
12+
#define I2C_STRETCH_DELAY 100 // Microseconds to delay during clock stretching
13+
#define I2C_CLOCK_FREQ 100000 // Default I2C clock frequency (100 kHz)
14+
15+
/*
16+
* Initialize I2C controller with specified clock settings
17+
* clkdiv: Clock divider (0-7) determines I2C frequency:
18+
* 0 = 100kHz (standard mode)
19+
* 1 = 50kHz
20+
* 2 = 25kHz
21+
* etc.
22+
*/
1223
w_status_t i2c_init(uint8_t clkdiv);
1324

1425
w_status_t i2c_write_data(uint8_t address, const uint8_t *data, uint8_t len);

pic18f26k83/i2c.c

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,58 @@
22

33
#include "i2c.h"
44

5-
#ifndef I2C_POLL_TIMEOUT
6-
#define I2C_POLL_TIMEOUT 2000
7-
#endif
5+
/* Private function declarations */
6+
static void clear_i2c_buffers(void);
7+
static w_status_t check_i2c_state(void);
8+
static w_status_t wait_for_idle(void);
9+
static w_status_t i2c_write(uint8_t address, const uint8_t *data, uint8_t len);
10+
static w_status_t i2c_read(uint8_t address, uint8_t *data, uint8_t len);
11+
12+
/*
13+
* Clear I2C buffers and ensure they're in a known state
14+
*/
15+
static void clear_i2c_buffers(void) {
16+
// Clear the buffer flag and flush any pending data
17+
I2C1STAT1bits.CLRBF = 1;
18+
while (I2C1STAT1bits.RXBF) {
19+
(void)I2C1RXB; // Read and discard any data
20+
}
21+
}
22+
23+
/*
24+
* Check the current state of the I2C module
25+
* Verifies module is enabled and no errors are present
26+
*/
27+
static w_status_t check_i2c_state(void) {
28+
if (!I2C1CON0bits.EN) {
29+
return W_IO_ERROR; // Module not enabled
30+
}
31+
32+
// Check for any error conditions
33+
if (I2C1ERRbits.BCLIF || // Bus collision
34+
I2C1ERRbits.BTOIF || // Bus timeout
35+
I2C1ERRbits.NACKIF) { // Not acknowledged
36+
37+
I2C1ERR = 0; // Clear error flags
38+
return W_IO_ERROR;
39+
}
40+
41+
return W_SUCCESS;
42+
}
43+
44+
/*
45+
* Wait for the I2C bus to become idle
46+
* Monitors the Bus Free bit with timeout protection
47+
*/
48+
static w_status_t wait_for_idle(void) {
49+
unsigned int timeout = 0;
50+
while (!I2C1STAT0bits.BFRE) {
51+
if (timeout++ >= I2C_POLL_TIMEOUT) {
52+
return W_IO_TIMEOUT;
53+
}
54+
}
55+
return W_SUCCESS;
56+
}
857

958
w_status_t i2c_init(uint8_t clkdiv) {
1059
// CSTR Enable clocking; S Cleared by hardware after Start; MODE 7-bit address; EN enabled; RSEN

0 commit comments

Comments
 (0)