I2C No ack error
Moderator: RoccoMarco
I2C No ack error
I'm trying to write to a 24lc256 with all the address pins at ground, it should have an address of 0x50. When I call i2cMasterTransmitTimeout I see the correct start bit and address and I think that the ACK is there but only the first byte is sent over the bus and i2cGetErrors responds with a value of 4.
The EEPROM works fine when I bit bang the i2c.
static const I2CConfig i2cconfig =
{
OPMODE_I2C, 100000, STD_DUTY_CYCLE
};
unsigned char rxBuf[16];
unsigned char txBuf[16];
int main(void)
{
halInit();
chSysInit();
i2cStart(&I2CD1, &i2cconfig);
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SCL */
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SDA */
txBuf[0] = 0 ;
txBuf[1] = 0 ;
i2cStart(&I2CD1, &i2cconfig);
i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, 0x50 , txBuf, 2, rxBuf, 8, TIME_INFINITE );
i2cErrors = i2cGetErrors(&I2CD1);
i2cReleaseBus(&I2CD1);
i2cStop(&I2CD1);
and here are scope traces that show the complete trace and the rise/fall time
The EEPROM works fine when I bit bang the i2c.
static const I2CConfig i2cconfig =
{
OPMODE_I2C, 100000, STD_DUTY_CYCLE
};
unsigned char rxBuf[16];
unsigned char txBuf[16];
int main(void)
{
halInit();
chSysInit();
i2cStart(&I2CD1, &i2cconfig);
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SCL */
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SDA */
txBuf[0] = 0 ;
txBuf[1] = 0 ;
i2cStart(&I2CD1, &i2cconfig);
i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, 0x50 , txBuf, 2, rxBuf, 8, TIME_INFINITE );
i2cErrors = i2cGetErrors(&I2CD1);
i2cReleaseBus(&I2CD1);
i2cStop(&I2CD1);
and here are scope traces that show the complete trace and the rise/fall time
- Attachments
-
- NewFile1.png (6.58 KiB) Viewed 8976 times
-
- NewFile0.png (6.89 KiB) Viewed 8976 times
- Giovanni
- Site Admin
- Posts: 14893
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 997 times
Re: I2C No ack error
Hi.
Do you have external pull-up resistors? is the address the correct one?
Please also look at the following guide: http://www.chibios.org/dokuwiki/doku.ph ... e_shooting
Giovanni
Do you have external pull-up resistors? is the address the correct one?
Please also look at the following guide: http://www.chibios.org/dokuwiki/doku.ph ... e_shooting
Giovanni
Re: I2C No ack error
4.7K pullups on both lines.
The first scope screenshot shows the rise and fall time of the signals. From what I've read within spec for 100KHz timing.
It's a stm32f4discovery board and the pins I'm using are marked as free in the user manual.
Anything unusual in the code?
The first scope screenshot shows the rise and fall time of the signals. From what I've read within spec for 100KHz timing.
It's a stm32f4discovery board and the pins I'm using are marked as free in the user manual.
Anything unusual in the code?
Re: I2C No ack error
I think I figured out I'm reading the trace incorrectly. Only the 9th rising edge of sda should be at gnd level for the ack.
From and i2c tutorial I found "If the receiving device sends back a low ACK bit, then it has received the data and is ready to accept another byte"
Shouldn't the ack have a bar over it to indicate it's asserted low or is that notation no longer common?
From and i2c tutorial I found "If the receiving device sends back a low ACK bit, then it has received the data and is ready to accept another byte"
Shouldn't the ack have a bar over it to indicate it's asserted low or is that notation no longer common?
Re: I2C No ack error
hi user99
I successfully use 24LC via I2C and have some clues for your case:
1)
Fist you must set pal mode than start I2C. The best place for tuning pins is board.h file. For example take a look at my one at boards/NONSTANDARD_STM32F4_BARTHESS1
2) Are you able to power cycle your 24LC via your firmware? This IC has no watchdog in it. It means IC must be power cycled if previous transaction interrupted by something (mostly by JTAG reset). Otherwise it will no ack. Workaround: insert sleep about 1s before first transaction.
Update: Please use code box for source samples in future.
I successfully use 24LC via I2C and have some clues for your case:
1)
Code: Select all
i2cStart(&I2CD1, &i2cconfig);
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SCL */
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN ); /* SDA */Fist you must set pal mode than start I2C. The best place for tuning pins is board.h file. For example take a look at my one at boards/NONSTANDARD_STM32F4_BARTHESS1
2) Are you able to power cycle your 24LC via your firmware? This IC has no watchdog in it. It means IC must be power cycled if previous transaction interrupted by something (mostly by JTAG reset). Otherwise it will no ack. Workaround: insert sleep about 1s before first transaction.
Update: Please use code box for source samples in future.
Re: I2C No ack error
After a lot of headache I finally found that a different i2c config works, at least it doesn't stop after the first byte.
I found this on a post from someone who also had problems running the STM32F4 with STD_DUTY_CYCLE.
I found this on a post from someone who also had problems running the STM32F4 with STD_DUTY_CYCLE.
Code: Select all
/* this didn't work
static const I2CConfig i2c1cfg =
{
OPMODE_I2C,
100000,
STD_DUTY_CYCLE
};
*/
// this one does
static I2CConfig i2c1cfg =
{
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2
};
Re: I2C No ack error
Hi,
I faced a problem in reading EEPROM 24LC512 using I2C STM32F103C8T6. Whenever I tried to use i2cMasterTransmitTimeout() and it hang at ch.dbg.panic_msg = reason when I commented the function and it works fine. I tested EEPROM on Arduino and it works just fine so it's not EEPROM problem. Debug info is showed as following.



Source code (Please let me know if I should skip irrelevant code next time for easier reading)
I faced a problem in reading EEPROM 24LC512 using I2C STM32F103C8T6. Whenever I tried to use i2cMasterTransmitTimeout() and it hang at ch.dbg.panic_msg = reason when I commented the function and it works fine. I tested EEPROM on Arduino and it works just fine so it's not EEPROM problem. Debug info is showed as following.



Source code (Please let me know if I should skip irrelevant code next time for easier reading)
Code: Select all
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "onewire.h"
static int32_t ftomod(float value);
static uint32_t ftodp(float value);
void setRTCAlarmPeriod(uint32_t seconds);
void powerStandby(void);
#define RTC_ALARM_PERIOD 10
RTCDateTime timespec;
RTCAlarm alarmspec;
#define ADC_GRP1_NUM_CHANNELS 1
#define ADC_GRP1_BUF_DEPTH 8
#define EEPROM_ADD 0x50
static BaseSequentialStream* chp = (BaseSequentialStream*)&SD2;
static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
static float mean;
/*
* ADC conversion group.
* Mode: Linear buffer, 8 samples of 1 channel, SW triggered.
* Channels: IN10.
*/
static const ADCConversionGroup adcgrpcfg1 = {
FALSE,
ADC_GRP1_NUM_CHANNELS,
NULL,
NULL,
0, 0, /* CR1, CR2 */
0, /* SMPR1 */
ADC_SMPR2_SMP_AN8(ADC_SAMPLE_1P5),
ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
0, /* SQR2 */
ADC_SQR3_SQ1_N(ADC_CHANNEL_IN8)
};
/*
* I2C1 config.
*/
static const I2CConfig i2cfg1 = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
i2cflags_t i2cflags = 0;
static uint8_t tx_data[4];
static uint8_t rx_data[4];
static systime_t calc_timeout(size_t bytes, uint32_t clock) {
const uint32_t bitsinbyte = 10;
uint32_t tmo_ms;
tmo_ms = ((bytes + 1) * bitsinbyte * 1000);
tmo_ms /= clock;
tmo_ms += 10; /* some additional milliseconds to be safer */
return MS2ST(tmo_ms);
}
static THD_WORKING_AREA(waEEPROM, 128);
static THD_FUNCTION(Thread_EEPROM, arg) {
msg_t status = MSG_OK;
systime_t tmo = calc_timeout(3, 100000);
(void)arg;
chRegSetThreadName("EEPROM");
while(true) {
chprintf(chp, "EEPROM\r\n");
i2cAcquireBus(&I2CD1);\
tx_data[0] = 0x00;
tx_data[1] = 0x00;
//status = i2cMasterReceiveTimeout(&I2CD1, EEPROM_ADD, rx_data, 2, tmo);
status = i2cMasterTransmitTimeout(&I2CD1, EEPROM_ADD, tx_data, 2, rx_data, 2, tmo);
if (MSG_OK != status)
i2cflags = i2cGetErrors(&I2CD1);
//osalDbgCheck(MSG_OK == status);
i2cReleaseBus(&I2CD1);
chprintf(chp, "Status: %d, Data: %d, %d\r\n", status, rx_data[0], rx_data[1]);
chThdSleepSeconds(1);
}
}
/*
* Light sensor measurement thread.
*/
static THD_WORKING_AREA(waLightSensor, 128);
static THD_FUNCTION(Thread_LightSensor, arg) {
uint8_t i;
(void)arg;
chRegSetThreadName("lightsensor");
// Convert ADC
adcConvert(&ADCD1, &adcgrpcfg1, samples1, ADC_GRP1_BUF_DEPTH);
// Turn off ADC
adcStop(&ADCD1);
// Calculate mean value
mean = 0;
for (i = 0; i < ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH; i++) {
mean += samples1[i];
}
mean = (float)(mean / (ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH));
//last_value = (float)(mean * 3.218 / 4095);
//sensor_value = (float)(97500 * last_value / (3.218 - last_value));
chprintf(chp, "Mean: %d.%03d\n\r", ftomod(mean), ftodp(mean));
//chprintf(chp, "Voltage output: %d.%03dV\n\r", ftomod(last_value), ftodp(last_value));
//chprintf(chp, "Resistant: %d\n\r", ftomod(sensor_value));
//chThdSleepSeconds(RTC_ALARM_PERIOD);
//chprintf(chp, "\033[2J\033[1;1H");
}
/*
* DS18B20 thread
*/
static THD_WORKING_AREA(waDS18B20, 128);
static THD_FUNCTION(Thread_DS18B20, arg) {
float temperature = 0.0;
(void)arg;
chRegSetThreadName("ds18b20");
// Read temperature
temperature = oneWireReadTemperature();
// Stop gpt
oneWireStop();
chprintf(chp, "Temperature: %d.%01d\n\r", ftomod(temperature), ftodp(temperature));
//chThdSleepSeconds(RTC_ALARM_PERIOD);
}
int main(void) {
halInit();
chSysInit();
// Serial UART2
sdStart(&SD2, NULL);
chprintf(chp, "iSensor\r\n");
// MOSFET drive
//palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_OPENDRAIN);
//palSetPad(GPIOB, 11);
//chThdSleepSeconds(1);
// Onewire for DS18B20
//oneWireInit();
// DS18B20 sensor thread
//chThdCreateStatic(waDS18B20, sizeof(waDS18B20), NORMALPRIO + 2, Thread_DS18B20, NULL);
// Setting up analog inputs
//palSetPadMode(GPIOB, 0, PAL_MODE_INPUT_ANALOG);
// Activates the ADC1 driver and the temperature sensor.
//adcStart(&ADCD1, NULL);
// Light sensor thread
//chThdCreateStatic(waLightSensor, sizeof(waLightSensor), NORMALPRIO + 2, Thread_LightSensor, NULL);
// I2C
palSetPadMode(GPIOB, 6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); /* SCL */
palSetPadMode(GPIOB, 7, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); /* SDA */
i2cStart(&I2CD1, &i2cfg1);
chThdCreateStatic(waEEPROM, sizeof(waEEPROM), NORMALPRIO + 1, Thread_EEPROM, NULL);
setRTCAlarmPeriod(RTC_ALARM_PERIOD);
while(true) {
chprintf(chp, "SLEEP...\r\n");
chThdSleepSeconds(3);
//powerStandby();
}
return 0;
}
void setRTCAlarmPeriod(uint32_t seconds) {
uint32_t tv_sec;
/* compile ability test */
rtcGetTime(&RTCD1, ×pec);
/* set alarm in near future */
rtcSTM32GetSecMsec(&RTCD1, &tv_sec, NULL);
alarmspec.tv_sec = tv_sec + seconds;
rtcSetAlarm(&RTCD1, 0, &alarmspec);
}
void powerStandby(void) {
//palClearPad(GPIOB, 11);
// Turn off Serial
sdStop(&SD2);
palSetGroupMode(GPIOA, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG);
palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG);
palSetGroupMode(GPIOC, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG);
rccDisableAHB(RCC_AHBENR_DMA1EN | RCC_AHBENR_SRAMEN | RCC_AHBENR_FLITFEN | \
RCC_AHBENR_CRCEN, lp);
rccDisableAPB2(RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN | \
RCC_APB2ENR_TIM1EN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN, lp);
rccDisableAPB1(RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_WWDGEN | \
RCC_APB1ENR_USART2EN | RCC_APB1ENR_I2C1EN | RCC_APB1ENR_CAN1EN | \
RCC_APB1ENR_USBEN, lp);
chSysLock();
PWR->CR |= PWR_CR_CWUF;
//PWR->CR |= PWR_CR_PDDS | PWR_CR_LPDS;
PWR->CR |= PWR_CR_PDDS;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__WFI();
}
/*
* Retrieve the integer part of value
*/
static int32_t ftomod(float value){
if (value >= 0)
return (int32_t) value;
else
return (int32_t) -1 * value;
}
/*
* Retrieve the decimal part of value
*/
static uint32_t ftodp(float value) {
if (value >= 0)
return (uint32_t) ((value - ftomod (value)) * 1000);
else
return (uint32_t) ((-value - ftomod (value)) * 1000);
}
- Giovanni
- Site Admin
- Posts: 14893
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 997 times
Re: I2C No ack error
Hi,
The reason is "not ready" meaning that the driver is not in the ready state, what is the state when the problem occurs?
Giovanni
The reason is "not ready" meaning that the driver is not in the ready state, what is the state when the problem occurs?
Giovanni
Re: I2C No ack error
On a quick look, the code looks sensible (and, yes, strip the code down to the minimum which shows the problem).
Two hardware things to check:
1. Do you have pullups on the I2C lines? (Typically in the region of 2K2 to 4K7; higher should work if lines are short and speed is low)
2. Are other pins assigned to the same I2C functions (perhaps in the board file)?
Does the problem arise on the first attempt to communicate with the EEPROM?
You might need to put a scope on the lines to see what's going on.
Two hardware things to check:
1. Do you have pullups on the I2C lines? (Typically in the region of 2K2 to 4K7; higher should work if lines are short and speed is low)
2. Are other pins assigned to the same I2C functions (perhaps in the board file)?
Does the problem arise on the first attempt to communicate with the EEPROM?
You might need to put a scope on the lines to see what's going on.
Re: I2C No ack error
Giovanni wrote:Hi,
The reason is "not ready" meaning that the driver is not in the ready state, what is the state when the problem occurs?
Giovanni
I printed out I2CD1.state and it says state 5. I guess it's I2C_LOCKED = 5 /**> Bus or driver locked. */.