I'm writing here because I'm not able to make I2C bus work in my project. I need to make my nucleo-f411 board communicate with a ds1307 RTC.
The electrical connection is done using a 100 Ohm resistor on SDA and on SDL placed between the uC and the RTC and a 4,7KOhm resistor placed between sda and VCC and another one between SCL and VCC. The VCC is 5V. This is the voltage of RTC supply. I know that it's not the best thing to do to put a 5V signal as input of a 3.3V supplied uC but these pins should be 5V tolerant.
The version of ChibiOS that I'm using is the 3.0.1. The problem that i get is the following: if in the function "rtc_init()" i execute the i2C_start() before the pin configuration as alternate function, when I try to execute the i2cMasterTransmitTimeout I get, as return value, MSG_TIMEOUT. Otherwise if I execute the I2C_start() after the pin configuration as alternate function i get MSG_RESET and the i2cGetErrors gives me a return value of 4 that should correspond to an ACK_FAILURE.
The code that I'm trying to execute is more or less the following one (I reported only that part that uses I2c because the whole code is extended and distributed on more modules):
Code: Select all
#define RTC_SDA_PORT GPIOB
#define RTC_SDA_PIN 6
#define RTC_SCL_PORT GPIOB
#define RTC_SCL_PIN 7
#define RTC_I2CD I2CD1
#define DS1307_ADDRESS 0x68
#define TMO MS2ST(20)
typedef struct{
uint8_t secReg;
uint8_t minReg;
uint8_t hourReg;
uint8_t dayOfWeekReg;
uint8_t dayReg;
uint8_t monthReg;
uint8_t yearReg;
uint8_t ctrlReg;
} rtc_rawDataRx_t;
typedef struct{
uint8_t startRegister;
uint8_t secReg;
uint8_t minReg;
uint8_t hourReg;
uint8_t dayOfWeekReg;
uint8_t dayReg;
uint8_t monthReg;
uint8_t yearReg;
uint8_t ctrlReg;
} rtc_rawDataTx_t;
typedef struct{
rtc_rawDataRx_t rawDataRx;
rtc_rawDataTx_t rawDataTx;
rtc_data_t dataTx;
rtc_data_t dataRx;
bool isRunning;
bool isInitiated;
msg_t status;
bool initFlag;
}rtc_t;
static const I2CConfig i2cfg1 =
{ OPMODE_I2C, 400000, FAST_DUTY_CYCLE_2 };
rtc_t rtc;
void rtc_init (void)
{
palSetPadMode(RTC_SDA_PORT, RTC_SDA_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
palSetPadMode(RTC_SCL_PORT, RTC_SCL_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
palSetPadMode(RTC_SDA_PORT, RTC_SDA_PIN, PAL_MODE_ALTERNATE(4));
palSetPadMode(RTC_SCL_PORT, RTC_SCL_PIN, PAL_MODE_ALTERNATE(4));
chThdSleepMilliseconds (200);
i2cStart(&RTC_I2CD, &i2cfg1);
chThdSleepMilliseconds (200);
rtc.initFlag = true;
}
rtc_rawDataRx_t rtc_getRtcData (void)
{
i2cflags_t error;
uint8_t txbuf[1];
txbuf[0]= 0x00;
i2cAcquireBus(&RTC_I2CD);
rtc.status = i2cMasterTransmitTimeout(&RTC_I2CD, DS1307_ADDRESS, txbuf, 1, (uint8_t*)(&(rtc.rawDataRx)), (sizeof(rtc_rawDataRx_t))/8, TMO);
i2cReleaseBus(&RTC_I2CD);
if (rtc.status != MSG_OK)
{
error = i2cGetErrors (&RTC_I2CD);
}
return rtc.rawDataRx;
}
void main (void)
{
halInit();
chSysInit();
rtc_init();
rtc_getRtcData();
}