parent
61a5785908
commit
8e27f8818e
@ -0,0 +1,13 @@
|
||||
#ifndef __I2C_MASTER_H__
|
||||
#define __I2C_MASTER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stm32h5xx_ll_i2c.h>
|
||||
|
||||
|
||||
extern int I2C_Write(I2C_TypeDef* I2Cx, uint8_t addr, const uint8_t* data, uint16_t len);
|
||||
extern int I2C_Read(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t* data, uint16_t len);
|
||||
extern int I2C_ReadReg(I2C_TypeDef* I2Cx, uint8_t addr, const uint8_t* reg, uint16_t reglen, uint8_t* data, uint16_t datalen);
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,134 @@
|
||||
/***************************************************************************//**
|
||||
* @file i2c_master.c
|
||||
* @brief I2C master functions for STM32H5 using LL library
|
||||
*//****************************************************************************/
|
||||
|
||||
//------------------------------C library---------------------------------------
|
||||
#include <stdint.h>
|
||||
//----------------------------user includes-------------------------------------
|
||||
#include "i2c_master.h"
|
||||
#include "main.h"
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
#define I2C_TIMEOUT_US 5000
|
||||
|
||||
|
||||
// SOFTEND in the write section prevents STOP --> Restart possible
|
||||
// AUTOEND in the read section generates correct STOP
|
||||
// TXIS/RXNE polling is mandatory for H5
|
||||
// STOP-flag-clear is necessary, otherwise the next transaction will hang.
|
||||
|
||||
|
||||
/* Functions -----------------------------------------------------------------*/
|
||||
|
||||
static int I2C_Tout(I2C_TypeDef* I2Cx, int val) {
|
||||
LL_I2C_GenerateStopCondition(I2Cx);
|
||||
LL_I2C_Disable(I2Cx);
|
||||
LL_I2C_Enable(I2Cx);
|
||||
LL_I2C_ClearFlag_NACK(I2Cx);
|
||||
LL_I2C_ClearFlag_STOP(I2Cx);
|
||||
LL_I2C_ClearFlag_ADDR(I2Cx);
|
||||
return val;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Write data to I2C slave device
|
||||
* @param I2Cx: I2C peripheral (e.g. I2C1)
|
||||
* @param addr: 7-bit I2C slave address, left-aligned
|
||||
* @param data: pointer to data buffer to write
|
||||
* @param len: number of bytes to write
|
||||
* @return 0 on success, -1 on TXIS timeout, -2 on STOP timeout
|
||||
*//****************************************************************************/
|
||||
int I2C_Write(I2C_TypeDef* I2Cx, uint8_t addr, const uint8_t* data, uint16_t len) {
|
||||
LL_I2C_HandleTransfer(I2Cx, addr, LL_I2C_ADDRSLAVE_7BIT, len, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_TXIS(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -1); // error: TXIS timeout
|
||||
}
|
||||
}
|
||||
LL_I2C_TransmitData8(I2Cx, data[i]); // send data
|
||||
}
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_STOP(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -2); // error: STOP timeout
|
||||
}
|
||||
}
|
||||
LL_I2C_ClearFlag_STOP(I2Cx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Read data from I2C slave device
|
||||
* @param I2Cx: I2C peripheral (e.g. I2C1)
|
||||
* @param addr: 7-bit I2C slave address, left-aligned
|
||||
* @param data: pointer to data buffer to store read data
|
||||
* @param len: number of bytes to read
|
||||
* @return 0 on success, -1 on RXNE timeout, -2 on STOP timeout
|
||||
*//****************************************************************************/
|
||||
int I2C_Read(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t* data, uint16_t len) {
|
||||
LL_I2C_HandleTransfer(I2Cx, addr, LL_I2C_ADDRSLAVE_7BIT, len, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -1); // error: RXNE timeout
|
||||
}
|
||||
}
|
||||
data[i] = LL_I2C_ReceiveData8(I2Cx); // read data
|
||||
}
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_STOP(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -2); // error: STOP timeout
|
||||
}
|
||||
}
|
||||
LL_I2C_ClearFlag_STOP(I2Cx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Read data from I2C slave device register
|
||||
* @param I2Cx: I2C peripheral (e.g. I2C1)
|
||||
* @param addr: 7-bit I2C slave address, left-aligned
|
||||
* @param reg: pointer to register address buffer (1-2 bytes)
|
||||
* @param reglen: number of bytes in register address (1 or 2)
|
||||
* @param data: pointer to data buffer to store read data
|
||||
* @param datalen: number of bytes to read
|
||||
* @return 0 on success, -1 on TXIS timeout, -2 on RXNE timeout, -3 on STOP timeout
|
||||
*//****************************************************************************/
|
||||
int I2C_ReadReg(I2C_TypeDef* I2Cx, uint8_t addr, const uint8_t* reg, uint16_t reglen, uint8_t* data, uint16_t datalen) {
|
||||
LL_I2C_HandleTransfer(I2Cx, addr, LL_I2C_ADDRSLAVE_7BIT, reglen, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
|
||||
for (uint16_t i = 0; i < reglen; i++) {
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_TXIS(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -1); // error: TXIS timeout
|
||||
}
|
||||
}
|
||||
LL_I2C_TransmitData8(I2Cx, reg[i]); // send register address
|
||||
}
|
||||
LL_I2C_HandleTransfer(I2Cx, addr, LL_I2C_ADDRSLAVE_7BIT, datalen, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ);
|
||||
for (uint16_t i = 0; i < datalen; i++) {
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_RXNE(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -2); // error: RXNE timeout
|
||||
}
|
||||
}
|
||||
data[i] = LL_I2C_ReceiveData8(I2Cx); // read data
|
||||
}
|
||||
uint32_t tref = usTimerGetAbs();
|
||||
while (!LL_I2C_IsActiveFlag_STOP(I2Cx)) {
|
||||
if (usTimerGetRel(tref) > I2C_TIMEOUT_US) { // timeout expired
|
||||
return I2C_Tout(I2Cx, -3); // error: STOP timeout
|
||||
}
|
||||
}
|
||||
LL_I2C_ClearFlag_STOP(I2Cx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue