Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c3db53c

Browse files
made i2c functions much more simple, modular, and faster. Now will test them inside the rtos tasks.
1 parent d769f53 commit c3db53c

File tree

4 files changed

+63
-66
lines changed

4 files changed

+63
-66
lines changed

‎include/i2c.h‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,14 @@ Date: 12/30/2024
2626
#define TSL2591_DATA_REGISTER (0xB4U)
2727
#define TSL2591_INIT_MESSAGE ((0xA0 << 8)|(0x03))
2828

29-
//timing for 16MHz I2CCLK and 100KHz transmission frequency
30-
//#define I2C2_TIMING_VALS ((0x3<<28)|(0x4<<20)|(0x2<<16)|(0xF<<8)|(0x13))
29+
#define I2C2_NBYTES (4U)
3130

3231
//timing for 16MHz I2CCLK and 400KHz transmission frequency
3332
#define I2C2_TIMING_VALS ((0x1<<28)|(0x3<<20)|(0x2<<16)|(0x3<<8)|(0x9))
3433

3534
void i2c2_init(void);
36-
void i2c2_write(uint8_t NBYTES, const uint16_t w_buffer);
37-
void i2c2_write_read(uint8_tNBYTES, const uint16_ttarget_reg, uint32_t*r_buffer);
35+
void i2c2_write(constuint8_t NBYTES, const uint16_t w_buffer);
36+
void i2c2_read(const uint8_tNBYTES);
3837
uint8_t i2c2_check_bus(void);
39-
void i2c2_resolve_deadlock(void);
40-
void I2C2_EV_IRQHandler(void);
4138

4239
#endif /* I2C_H */

‎src/i2c.c‎

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ Purpose: configure I2C2 and implement read and write functions
1414
#include "nvic.h"
1515
#include "tcnt.h"
1616

17+
volatile uint8_t g_i2c2_rx_count = 0;
18+
extern volatile uint32_t g_read_buffer;
19+
1720
//initialize I2C2 registers: 100KHz SCL Frequency, 7-bit addressing mode
1821
void i2c2_init(void) {
1922
gpio_i2c2_init(); //set up gpio for i2c2
2023

2124
I2C2_CR1 &= ~1; //disable I2C2 Peripheral
22-
I2C2_CR1 |= (1 << 4); //enable NACK interrupt
25+
I2C2_CR1 |= (1 << 2); //enable receive interrupt
2326

2427
I2C2_TIMINGR |= I2C2_TIMING_VALS;
2528

@@ -28,75 +31,49 @@ void i2c2_init(void) {
2831
}
2932

3033
//write to the target; this function only allows up to 2 bytes of data transmission at once
31-
void i2c2_write(uint8_t NBYTES, const uint16_t w_buffer) {
34+
void i2c2_write(constuint8_t NBYTES, const uint16_t w_buffer) {
3235
I2C2_CR2 &= ~(1 << 10); //set to Write
3336
I2C2_CR2 &= ~(0xFF << 16); //clear NBYTES; if this is not done then sometimes no stop condition
3437
I2C2_CR2 |= (NBYTES << 16); //NBYTES = NBYTES parameter
3538

36-
//loop until bus is idle
3739
volatile int count = 0;
3840
uint8_t timeout = 0xFF;
39-
while (timeout != 1) timeout = i2c2_check_bus();
41+
while (timeout != 1) { //loop until bus is idle
42+
timeout = i2c2_check_bus();
43+
}
4044

4145
I2C2_CR2 |= (1 << 13); //send start condition
4246

4347
//loop until all bytes are sent
4448
for (count = NBYTES-1; count > -1; count--) {
4549
while (!((I2C2_ISR >> 1) & 1)); //loop until TXIS flag is set
46-
I2C2_TXDR = (uint8_t)((w_buffer >> (8*count)) &0xFF);
50+
I2C2_TXDR = (uint8_t) (w_buffer >> (8*count));
4751
}
4852

49-
//delay for target device to process 2nd data byte
50-
timer3_delay_us(500);
53+
if (NBYTES > 1) {
54+
timer3_delay_us(30); //delay for target device to process 2nd data byte
55+
}
5156

5257
I2C2_CR2 |= (1 << 14); //send STOP condition
5358
I2C2_ICR |= (1 << 5); //clear stop flag
5459
}
5560

56-
//Write to a register in the target device then read and store 4 bytes to the r_buffer
57-
void i2c2_write_read(uint8_t NBYTES, const uint16_t target_reg, uint32_t *r_buffer) {
58-
*r_buffer = 0; //clear r_buffer
59-
60-
//complete write section first:
61-
I2C2_CR2 &= ~(1 << 10); //set to Write
62-
I2C2_CR2 &= ~(0xFF << 16); //clear NBYTES; if this is not done then sometimes no stop condition
63-
I2C2_CR2 |= (1 << 16); //NBYTES = 1
64-
65-
//loop until bus is idle
66-
volatile int count = 0;
67-
uint8_t timeout = 0xFF;
68-
while (timeout != 1) timeout = i2c2_check_bus();
69-
70-
I2C2_CR2 |= (1 << 13); //send start condition
71-
72-
while (!((I2C2_ISR >> 1) & 1)); //loop until TXIS flag is set
73-
I2C2_TXDR = target_reg & 0xFF; //only use first byte
74-
75-
//repeated START to do read section:
76-
while ((I2C2_CR2 >> 13) & 1); //loop until START bit is not set
77-
61+
//read from the i2c bus
62+
void i2c2_read(const uint8_t NBYTES) {
7863
I2C2_CR2 |= (1 << 10); //set to Read
7964
I2C2_CR2 &= ~(0xFF << 16); //clear NBYTES; if this is not done then sometimes no stop condition
8065
I2C2_CR2 |= (NBYTES << 16); //NBYTES = 4 for the TSL2591 data registers
8166

82-
//loop until bus is idle
83-
count = 0;
84-
timeout = 0xFF;
85-
while (timeout != 1) timeout = i2c2_check_bus();
67+
volatile int count = 0;
68+
uint8_t timeout = 0xFF;
69+
while (timeout != 1) { //loop until bus is idle
70+
timeout = i2c2_check_bus();
71+
}
8672

8773
I2C2_CR2 |= (1 << 13); //send start condition
8874

89-
//loop until all bytes are read
90-
for (count = 0; count < NBYTES; count++) {
91-
while (!((I2C2_ISR >> 2) & 1)); //loop until RXNE flag is set
92-
*r_buffer |= (I2C2_RXDR & 0xFF) << (count*8);
93-
}
94-
95-
//NOTE: NACK is automatically sent after the last byte reception.
96-
97-
I2C2_CR2 |= (1 << 14); //send STOP condition
98-
I2C2_ICR |= (1 << 5); //clear stop flag
99-
}
75+
g_read_buffer = 0;
76+
}
10077

10178
//Use timers to check if the bus goes idle; returns 1 if idle and 0 if not idle
10279
uint8_t i2c2_check_bus(void) {
@@ -118,14 +95,36 @@ uint8_t i2c2_check_bus(void) {
11895
}
11996
}
12097

121-
//Function to resolve I2C deadlocks - not completed
122-
void i2c2_resolve_deadlock(void) {
123-
}
124-
125-
//IRQ handler for I2C2 event interrupts; for now for NACKs
98+
//IRQ handler for I2C2 event interrupts - for receives!
12699
void I2C2_EV_IRQHandler(void) {
127100
nvic_disable();
128-
//do something
101+
102+
static uint8_t bytes_rx; //holds number of bytes received
103+
104+
//if this is the first received byte, init a count var to 1
105+
if (g_i2c2_rx_count == 0) {
106+
///*
107+
bytes_rx = 0;
108+
g_read_buffer |= ((uint8_t) I2C2_RXDR) << (g_i2c2_rx_count*8);
109+
//*/
110+
111+
bytes_rx = 1;
112+
g_i2c2_rx_count = 1;
113+
}
114+
else {
115+
///*
116+
g_read_buffer |= ((uint8_t) I2C2_RXDR) << (bytes_rx*8);
117+
//*/
118+
119+
bytes_rx++;
120+
}
121+
122+
if (bytes_rx == I2C2_NBYTES) {
123+
I2C2_CR2 |= (1 << 14); //send STOP condition
124+
I2C2_ICR |= (1 << 5); //clear stop flag
125+
bytes_rx = 0;
126+
g_i2c2_rx_count = 0;
127+
}
129128
nvic_enable();
130129
}
131130

‎src/main.c‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Purpose: To get the LD2 on the Nucleo-L476RG to turn on.
2727
extern volatile uint8_t global_button_flag;
2828

2929
volatile uint32_t lux_data;
30+
volatile uint32_t g_read_buffer = 0;
3031

3132
//task prototypes
3233
void task1_handler(void *args); //handles comms with lux sensor
@@ -57,10 +58,11 @@ static void hardware_init(void) {
5758
i2c2_write(2, TSL2591_INIT_MESSAGE);
5859
tsl2591_write_settings(again_low, atime_100ms);
5960

60-
uint32_t raw_data;
61-
i2c2_write_read(4, TSL2591_DATA_REGISTER, &raw_data);
62-
lux_data = rawdata_to_lux(raw_data, again_low, atime_100ms);
61+
i2c2_write(1, TSL2591_DATA_REGISTER);
62+
i2c2_read(4);
6363

64+
timer3_delay_us(50000);
65+
lux_data = rawdata_to_lux(g_read_buffer, again_low, atime_100ms);
6466

6567
char lux_buf[] = " "; //init an empty buffer for lux measurements. -> has size [15] (added null term)
6668
snprintf(lux_buf, 15, "%lu ", lux_data);
@@ -72,7 +74,6 @@ static void hardware_init(void) {
7274
lcd_text_buffer_t lux_text_buffer = {lux_buf};
7375

7476
lcd_output_text(lux_text_buffer);
75-
7677
}
7778

7879
int main(void) {
@@ -107,7 +108,7 @@ void task1_handler(void *args) {
107108
while(1) {
108109
/*
109110
gpio_led_on();
110-
i2c2_write_read(4, TSL2591_DATA_REGISTER, &raw_data);
111+
i2c2_write_read(4, TSL2591_DATA_REGISTER);
111112
lux_data = rawdata_to_lux(raw_data, again_low, atime_100ms);
112113
*/
113114
}

‎src/nvic.c‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ Purpose: To control interrupts through the NVIC;
1111
//enable NVIC
1212
void nvic_enable(void) {
1313
NVIC_ISER1 |= (1 << 8); //enable interrupt 40 (user button)
14+
NVIC_ISER1 |= (1 << 1); //enable interrupt 33 (I2C2_EV)
1415
//NVIC_ISER0 |= (1 << 28); //enable interrupt 28 (TIM2 global interrupt)
1516
}
1617

1718
//disable NVIC
1819
void nvic_disable(void) {
1920
NVIC_ICER1 |= (1 << 8); //disable interrupt 40 (user button)
21+
NVIC_ICER1 |= (1 << 1); //disable interrupt 33 (I2C2_EV)
2022
//NVIC_ICER0 |= (1 << 28); //disable interrupt 28 (TIM2 global interrupt)
2123
}
2224

2325
//change priorities of nvic
2426
void nvic_priority(void) {
25-
//change priority of button interrupt (40) to lowest
26-
NVIC_IPR10 |= (0xF << 4);
27-
//change priority of TIM2 global interrupt (28) to lowest
28-
//NVIC_IPR7 |= (0xF << 0);
29-
27+
NVIC_IPR10 |= (0xF << 4); //change priority of button interrupt (40) to lowest
28+
NVIC_IPR8 |= (0xE << 12); //change priority of I2C2 receive interrupt (33) to second lowest
29+
//NVIC_IPR7 |= (0xF << 0); //change priority of TIM2 global interrupt (28) to lowest
3030
}
3131

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /