写个S32K144 LPI2C的驱动
时间: 2023-08-27 19:21:25 浏览: 243
好的,下面是一个基本的S32K144 LPI2C的驱动的代码框架,供您参考:
```c
#include "S32K144.h"
// 定义I2C时钟频率
#define I2C_CLOCK_FREQ 100000 // 100 kHz
// 定义I2C读写操作标志
#define I2C_WRITE 0
#define I2C_READ 1
// 定义I2C传输状态标志
#define I2C_IDLE 0
#define I2C_BUSY 1
// 定义I2C错误代码
#define I2C_OK 0
#define I2C_ERROR -1
// 定义I2C传输结构体
typedef struct {
uint8_t addr; // 7位I2C设备地址
uint8_t dir; // 读写方向
uint8_t *data; // 数据缓冲区指针
uint32_t len; // 数据长度
uint32_t index; // 当前传输数据的下标
uint8_t status; // 传输状态
uint8_t error; // 错误代码
} i2c_transfer_t;
// 定义LPI2C模块指针
LPI2C_Type *i2c = LPI2C0;
// 定义I2C传输结构体实例
i2c_transfer_t i2c_transfer;
// I2C初始化函数
void i2c_init() {
// 使能LPI2C时钟
PCC->PCCn[PCC_LPI2C0_INDEX] |= PCC_PCCn_CGC_MASK;
// 设置LPI2C引脚复用
PORTD->PCR[8] = PORT_PCR_MUX(2) | PORT_PCR_ODE_MASK; // SCL
PORTD->PCR[9] = PORT_PCR_MUX(2) | PORT_PCR_ODE_MASK; // SDA
// 重置LPI2C模块
i2c->MCR |= LPI2C_MCR_RST_MASK;
while (i2c->MCR & LPI2C_MCR_RST_MASK);
// 配置LPI2C时钟
uint32_t clock_freq = (uint32_t)(CLOCK_GetBusClkFreq() / 1000000);
i2c->MCCR0 = (clock_freq / (5 * I2C_CLOCK_FREQ)) - 1;
i2c->MCCR1 = (clock_freq / (5 * I2C_CLOCK_FREQ)) - 1;
// 配置LPI2C控制寄存器
i2c->MCR |= LPI2C_MCR_MEN_MASK; // 使能LPI2C模块
i2c->MCFGR1 = LPI2C_MCFGR1_PRESCALE(0); // 设置预分频器
i2c->MCFGR2 = LPI2C_MCFGR2_BUSIDLE(10); // 设置总线空闲时间
i2c->MCFGR3 = LPI2C_MCFGR3_PINLOW(10) | LPI2C_MCFGR3_SDAHOLD(10); // 配置SDA低电平时间和SDA保持时间
i2c->MCR |= LPI2C_MCR_FRZ_MASK; // 冻结LPI2C模块
}
// 发起I2C传输函数
int i2c_transfer(uint8_t addr, uint8_t dir, uint8_t *data, uint32_t len) {
// 判断是否有其他传输正在进行
if (i2c_transfer.status == I2C_BUSY) {
return I2C_ERROR;
}
// 保存传输信息
i2c_transfer.addr = (addr << 1) | dir;
i2c_transfer.dir = dir;
i2c_transfer.data = data;
i2c_transfer.len = len;
i2c_transfer.index = 0;
i2c_transfer.status = I2C_BUSY;
i2c_transfer.error = I2C_OK;
// 配置LPI2C传输
i2c->MTDR = i2c_transfer.addr;
i2c->MCR &= ~LPI2C_MCR_FRZ_MASK; // 解冻LPI2C模块
i2c->MCR |= LPI2C_MCR_TX_MASK; // 设置为发送模式
i2c->MCR &= ~LPI2C_MCR_MEN_MASK; // 禁止LPI2C模块
i2c->MCR |= LPI2C_MCR_MEN_MASK; // 使能LPI2C模块
return I2C_OK;
}
// LPI2C中断服务函数
void LPI2C0_IRQHandler() {
// 判断是否是传输完成中断
if (i2c->MSR & LPI2C_MSR_MBF_MASK) {
// 判断是否是读取模式
if (i2c_transfer.dir == I2C_READ) {
i2c_transfer.data[i2c_transfer.index++] = i2c->MRDR;
} else {
// 判断是否还有数据需要发送
if (i2c_transfer.index < i2c_transfer.len) {
i2c->MTDR = i2c_transfer.data[i2c_transfer.index++];
} else {
// 传输完成,禁用LPI2C中断
i2c_transfer.status = I2C_IDLE;
i2c->MIER &= ~LPI2C_MIER_TDIE_MASK;
}
}
}
// 判断是否是传输错误中断
if (i2c->MSR & LPI2C_MSR_NDF_MASK) {
i2c_transfer.status = I2C_IDLE;
i2c_transfer.error = I2C_ERROR;
i2c->MIER &= ~LPI2C_MIER_TDIE_MASK;
}
}
```
这是一个基本的I2C驱动框架,实现了基本的读写操作和错误处理。需要注意的是,该代码只是一个框架,实际使用时还需要根据具体的需求进行修改和优化。同时,该代码中使用了LPI2C模块来实现I2C通信,如果您使用的是别的I2C控制器,代码需要进行相应的修改。
阅读全文