Untitled
unknown
plain_text
a year ago
5.4 kB
11
Indexable
#include "ra6m3.h"
// Configuration
#define I2C_CLOCK_FREQUENCY 1000000 // 1 MHz (Fast Mode Plus)
#define I2C_RETRY_COUNT 3 // Retry attempts for stuck conditions
#define I2C_DMA_THRESHOLD 32 // Threshold for using DMA
#define I2C_PERIPHERAL_BASE RIIC0 // Use RIIC0 peripheral
#define SDA_PIN P1_2 // Replace with your SDA pin
#define SCL_PIN P1_3 // Replace with your SCL pin
// State variables
volatile bool transfer_complete = false;
volatile bool transfer_error = false;
// Function prototypes
void i2c_init(void);
void i2c_set_clock(void);
void i2c_bus_recovery(void);
void i2c_isr_handler(void);
void dma_init(void); // Optional: Initialize DMA for larger transfers
int i2c_write(uint8_t addr, uint8_t *data, uint32_t length);
int i2c_read(uint8_t addr, uint8_t *data, uint32_t length);
// I2C Initialization
void i2c_init(void)
{
// Enable peripheral clock for RIIC
R_MSTP->MSTPCRB_b.MSTPB21 = 0; // Enable RIIC0 peripheral
// Set SDA and SCL pins to proper mode
PORT1->PDR_b.B2 = 1; // SDA
PORT1->PDR_b.B3 = 1; // SCL
PORT1->PMR_b.B2 = 1; // SDA
PORT1->PMR_b.B3 = 1; // SCL
// Reset and enable RIIC peripheral
I2C_PERIPHERAL_BASE->CR1 = 0x00; // Disable RIIC
I2C_PERIPHERAL_BASE->CR1 = 0x01; // Reset RIIC
// Set I2C clock frequency
i2c_set_clock();
// Enable I2C interrupts
NVIC_EnableIRQ(RIIC0_TXI_IRQn);
NVIC_EnableIRQ(RIIC0_RXI_IRQn);
NVIC_EnableIRQ(RIIC0_TEI_IRQn);
NVIC_EnableIRQ(RIIC0_NAKI_IRQn);
// Enable RIIC
I2C_PERIPHERAL_BASE->CR2 |= 0x01;
}
void i2c_set_clock(void)
{
uint32_t pclk = 120000000; // Peripheral clock frequency
uint32_t ccr = pclk / (I2C_CLOCK_FREQUENCY * 8) - 1;
// Set clock settings for Fast Mode Plus
I2C_PERIPHERAL_BASE->CCR = ccr & 0xFF;
I2C_PERIPHERAL_BASE->CCR2 = (ccr >> 8) & 0xFF;
}
// I2C Write
int i2c_write(uint8_t addr, uint8_t *data, uint32_t length)
{
int retry = I2C_RETRY_COUNT;
while (retry-- > 0)
{
transfer_complete = false;
transfer_error = false;
// Send start condition
I2C_PERIPHERAL_BASE->CR2 |= 0x04; // Start condition
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x01))
; // Wait for start condition
// Send address
I2C_PERIPHERAL_BASE->TDR = addr << 1; // Write bit
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x02))
; // Wait for address transmission
// Send data
for (uint32_t i = 0; i < length; i++)
{
I2C_PERIPHERAL_BASE->TDR = data[i];
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x02))
; // Wait for byte transmission
}
// Send stop condition
I2C_PERIPHERAL_BASE->CR2 |= 0x08; // Stop condition
while (I2C_PERIPHERAL_BASE->CR2 & 0x08)
; // Wait for stop condition
if (!transfer_error)
{
return 0; // Success
}
i2c_bus_recovery(); // Recover and retry
}
return -1; // Failed after retries
}
// I2C Read
int i2c_read(uint8_t addr, uint8_t *data, uint32_t length)
{
int retry = I2C_RETRY_COUNT;
while (retry-- > 0)
{
transfer_complete = false;
transfer_error = false;
// Send start condition
I2C_PERIPHERAL_BASE->CR2 |= 0x04; // Start condition
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x01))
; // Wait for start condition
// Send address
I2C_PERIPHERAL_BASE->TDR = (addr << 1) | 0x01; // Read bit
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x02))
; // Wait for address transmission
// Receive data
for (uint32_t i = 0; i < length; i++)
{
while (!(I2C_PERIPHERAL_BASE->SR2 & 0x04))
; // Wait for received byte
data[i] = I2C_PERIPHERAL_BASE->RDR;
}
// Send stop condition
I2C_PERIPHERAL_BASE->CR2 |= 0x08; // Stop condition
while (I2C_PERIPHERAL_BASE->CR2 & 0x08)
; // Wait for stop condition
if (!transfer_error)
{
return 0; // Success
}
i2c_bus_recovery(); // Recover and retry
}
return -1; // Failed after retries
}
// Bus Recovery
void i2c_bus_recovery(void)
{
// Toggle SCL manually to free stuck bus
PORT1->PDR_b.B3 = 1; // SCL as GPIO
for (int i = 0; i < 9; i++)
{
PORT1->PODR_b.B3 = 1; // SCL High
for (volatile int delay = 0; delay < 1000; delay++)
;
PORT1->PODR_b.B3 = 0; // SCL Low
for (volatile int delay = 0; delay < 1000; delay++)
;
}
PORT1->PDR_b.B3 = 0; // Return SCL to peripheral control
}
// ISR Handler (Simplified)
void i2c_isr_handler(void)
{
if (I2C_PERIPHERAL_BASE->SR1 & 0x01) // Transfer complete
{
transfer_complete = true;
}
else if (I2C_PERIPHERAL_BASE->SR1 & 0x02) // Error
{
transfer_error = true;
}
}
// Main
int main(void)
{
uint8_t data[64];
i2c_init();
// Example write
data[0] = 0xAA;
if (i2c_write(0x50, data, 1) == 0)
{
// Write success
}
// Example read
if (i2c_read(0x50, data, 10) == 0)
{
// Read success
}
while (1)
{
// Main loop
}
}Editor is loading...
Leave a Comment