Перейти к содержанию
    

Проблемы по I2C STM32F103RC

Здравствуйте. Прошу помощи, бьюсь уже 3 день немого понять где проблема. Опрашиваю память M24C16 по I2C. Нет прерывания ДАЖЕ по старту.

Код инициализации:

    I2C_InitTypeDef  I2C_InitStructure;
   NVIC_InitTypeDef NVIC_InitStruct;

   I2C_DeInit(I2C2);
   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C_DutyCycle_16_9;
   I2C_InitStructure.I2C_OwnAddress1 = 0x04;
   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
   I2C_InitStructure.I2C_ClockSpeed = 100000;  /* 100kHz */

   I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);
   I2C_ITConfig(I2C2, I2C_IT_ERR, ENABLE);

   I2C_Init(I2C2, &I2C_InitStructure);
   I2C_Cmd(I2C2, ENABLE);

   NVIC_InitStruct.NVIC_IRQChannel = I2C2_EV_IRQn;
   NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStruct);
   NVIC_EnableIRQ(I2C2_EV_IRQn);
   NVIC_SetPriority(I2C2_EV_IRQn, 0); //


NVIC_InitStruct.NVIC_IRQChannel = I2C2_ER_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
   NVIC_EnableIRQ(I2C2_ER_IRQn);
   NVIC_SetPriority(I2C2_ER_IRQn, 1); //

Обработчик:

	volatile uint16_t sr1 = I2C2->SR1;
volatile uint16_t sr2 = I2C2->SR2;
if (!(sr2 & I2C_SR2_MSL)) return;

if( sr1 & I2C_SR1_SB)  //принят ответ ACK, отправка адресса
{
	i2c_state = I2C_SEND_ADR_DEV;
    I2C2->DR = (uint16_t) i2c_buffer.device_adr;
}

if(sr1 & I2C_SR1_TXE)	//принят ответ ACK, данных и стоп
{
	switch (i2c_state)
	{
		case I2C_SEND_ADR_DEV:
			i2c_state = I2C_SEND_ADR_MEM;
			I2C2->DR = (uint16_t) i2c_buffer.start_adr;
			break;
		case I2C_SEND_ADR_MEM:

			if( i2c_buffer.pos_head < i2c_buffer.pos_tail && i2c_buffer.pos_head < i2c_buffer.len)
		    {
				i2c_state = I2C_SEND_DATA;
		        I2C1->DR = i2c_buffer.buffer[i2c_buffer.pos_head];
		        i2c_buffer.pos_head++;
		    }
			else
			{
		    	i2c_buffer.pos_tail = 0;
		    	i2c_buffer.pos_head = 0;
		        i2c_state = I2C_EMPTY;
		        I2C1->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		case I2C_SEND_DATA:
			i2c_state = I2C_SEND_ADR_MEM;
			I2C2->DR = (uint16_t) i2c_buffer.start_adr;
			i2c_buffer.start_adr++;
			break;
		default:
			break;
	}
}
if( sr1 & I2C_SR1_RXNE ) 		//прерывание по чтению
{
	switch (i2c_state)
	{
		case I2C_SEND_ADR_DEV:
			i2c_state = I2C_SEND_ADR_MEM;
			I2C2->DR = (uint16_t) i2c_buffer.start_adr;
			break;
		case I2C_SEND_ADR_MEM:
			i2c_state = I2C_SEND_ADR_DEV2;
		    I2C2->DR = (uint16_t) i2c_buffer.device_adr;
			break;
		case I2C_SEND_ADR_DEV2:
			if(i2c_buffer.pos_tail < i2c_buffer.len)
		    {
			i2c_state = I2C_RECEIVE_DATA;
		        i2c_buffer.buffer[i2c_buffer.pos_tail] = I2C2->DR;
		        i2c_buffer.pos_tail++;
		    }
			else
			{
		        i2c_state = I2C_EMPTY;
		        I2C1->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		case I2C_RECEIVE_DATA:
			if(i2c_buffer.pos_tail < i2c_buffer.len)
		    {
			i2c_state = I2C_RECEIVE_DATA;
		        i2c_buffer.buffer[i2c_buffer.pos_tail] = I2C2->DR;
		        i2c_buffer.pos_tail++;
		    }
			else
			{
		        i2c_state = I2C_EMPTY;
		        I2C1->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		default:
			break;
	}
}

ПОМОГИТЕ!!!!!!!!

Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте. Прошу помощи, бьюсь уже 3 день немого понять где проблема. Опрашиваю память M24C16 по I2C. Нет прерывания ДАЖЕ по старту.

1. Не включено тактирование I2C2. Может где в другом месте включается, но между строк я читать не умею. I2C_Init() это не делает, AFAIK.

2. I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE) надо бы делать после I2C_Init().

 

Это навскидку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Не включено тактирование I2C2. Может где в другом месте включается, но между строк я читать не умею. I2C_Init() это не делает, AFAIK.

2. I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE) надо бы делать после I2C_Init().

 

Это навскидку.

 

Тактирование есть.

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

А вот за это спасибо. попробую.

Может еще что то.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Не включено тактирование I2C2. Может где в другом месте включается, но между строк я читать не умею. I2C_Init() это не делает, AFAIK.

2. I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE) надо бы делать после I2C_Init().

 

Это навскидку.

 

I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE) надо бы делать после I2C_Init(). НЕПОМОГАЕТ

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

подтяжки линий к 1 на плате есть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да есть решили с помощью осцелографа и такой то матери. ВСЕМ СПАСИБО.

Появилясь другая. Работа осщуствляется с памятью M24C16 в посылках при чтении появляется,

Это видно и на осцелографе и в трасировке. Невного переделал код прерывания.

 

void I2C2_EV_IRQHandler(void)
{
volatile uint16_t sr1 = I2C2->SR1;
volatile uint16_t sr2 = I2C2->SR2;
if (!(sr2 & I2C_SR2_MSL)) return;

if( sr1 & I2C_SR1_SB)  //принят ответ ACK, отправка адресса
{
	if (i2c_state == I2C_SEND_START) i2c_state = I2C_SEND_ADR_DEV;
	else i2c_state = I2C_SEND_ADR_DEV2;
    I2C2->DR = (uint16_t) i2c_buffer.device_adr;
}

if(sr1 & I2C_SR1_TXE)	//принят ответ ACK, данных и стоп
{
	switch (i2c_state)
	{
		case I2C_SEND_ADR_DEV:
			i2c_state = I2C_SEND_ADR_MEM;
			I2C2->DR = (uint16_t) i2c_buffer.start_adr;
			break;
		case I2C_SEND_ADR_MEM:

			if( i2c_buffer.pos_head < i2c_buffer.pos_tail && i2c_buffer.pos_head < i2c_buffer.len)
		    {
				i2c_state = I2C_SEND_ADR_MEM;     //I2C_SEND_DATA
		        I2C2->DR = i2c_buffer.buffer[i2c_buffer.pos_head];
		        i2c_buffer.pos_head++;
		    }
			else
			{
		    	i2c_buffer.pos_tail = 0;
		    	i2c_buffer.pos_head = 0;
		        i2c_state = I2C_EMPTY;
		        I2C2->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		//case I2C_SEND_DATA:
		//	i2c_state = I2C_SEND_ADR_MEM;
		//	I2C2->DR = (uint16_t) i2c_buffer.start_adr;
		//	i2c_buffer.start_adr++;
		//	break;
		default:
			break;
	}
}
if( sr1 & I2C_SR1_RXNE ) 		//прерывание по чтению
{
	switch (i2c_state)
	{
		case I2C_SEND_ADR_DEV:
			i2c_state = I2C_SEND_ADR_MEM;
			I2C2->DR = (uint16_t) i2c_buffer.start_adr;
			break;
		case I2C_SEND_ADR_MEM:
			i2c_state = I2C_SEND_START_SECOND;
			//i2c_state = I2C_SEND_ADR_DEV2;
		    //I2C2->DR = (uint16_t) i2c_buffer.device_adr;
			I2C_GenerateSTART(I2C2, ENABLE);
			break;
		case I2C_SEND_ADR_DEV2:
			if(i2c_buffer.pos_tail < i2c_buffer.len)
		    {
				i2c_state = I2C_RECEIVE_DATA;
		        i2c_buffer.buffer[i2c_buffer.pos_tail] = I2C2->DR;
		        i2c_buffer.pos_tail++;
		    }
			else
			{
		        i2c_state = I2C_EMPTY;
		        I2C2->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		case I2C_RECEIVE_DATA:
			if(i2c_buffer.pos_tail < i2c_buffer.len)
		    {
				i2c_state = I2C_RECEIVE_DATA;
		        i2c_buffer.buffer[i2c_buffer.pos_tail] = I2C2->DR;
		        i2c_buffer.pos_tail++;
		    }
			else
			{
		        i2c_state = I2C_EMPTY;
		        I2C2->CR1 |= I2C_CR1_STOP; //если закончилась то стоп
			}
			break;
		default:
			break;
	}
}
}

 

Извиняюсь появляется значение DR=255 + ACK

 

Есть подозрение что это из-за того что работаем на 100kHz а не на 400. Проверить небыло времени. Кто что думает. Спасибо. Как проверю - отпишусь

 

Извиняюсь за плохое форматирование текста

Изменено пользователем IgorKossak
бездумное цитирование

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хоть и ничего не понял, но вы не поверите: I2C на частотах меньших предельной хуже работать не станет (;

 

"DR=255 + ACK" - это сколько? 256? в байте?

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хоть и ничего не понял, но вы не поверите: I2C на частотах меньших предельной хуже работать не станет (;

О-о, я бы не зарекался, когда дело касается I2C на F1xx... Я из своего опыта об этом писал уже. Кстати, как сейчас заметил, писал в аналогичной теме нынешнего ТС. Уважаемый dimon_rub, почему Вы не продолжили в Вашей же более ранней теме?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О-о, я бы не зарекался, когда дело касается I2C на F1xx... Я из своего опыта об этом писал уже. Кстати, как сейчас заметил, писал в аналогичной теме нынешнего ТС. Уважаемый dimon_rub, почему Вы не продолжили в Вашей же более ранней теме?

T.e. для F103 существует фиксированная частота SCL и при том близкая к предельной (да, рассматриваем стандартную 400 кГц)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

T.e. для F103 существует фиксированная частота SCL и при том близкая к предельной (да, рассматриваем стандартную 400 кГц)?

Нет. Дело в другом: при переходе на 100kHz выползают состояния автомата I2C, а именно - комбинации битов флагов, - которые не описаны в документации и не предусмотрены STL, не ручаюсь за Cube. В результате обработчик прерывания, беспроблемно обслуживающий на 400kHz, вдруг затыкается на 100kHz.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет. Дело в другом: при переходе на 100kHz выползают состояния автомата I2C, а именно - комбинации битов флагов, - которые не описаны в документации и не предусмотрены STL, не ручаюсь за Cube. В результате обработчик прерывания, беспроблемно обслуживающий на 400kHz, вдруг затыкается на 100kHz.

А на 66 кГц, к примеру?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А на 66 кГц, к примеру?

- Вы умеете играть на скрипке?

- Не знаю: не пробовал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

- Вы умеете играть на скрипке?

- Не знаю: не пробовал.

Мы поняли друг-друга (:

Но разве I2C_CCR[11..0] (делитель частоты) может влиять на логику I2C-автомата

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но разве I2C_CCR[11..0] (делитель частоты) может влиять на логику I2C-автомата
Там, помнится, одним из битов выбирается режим - быстро или медленно. И в зависимости от режима формируются разные временнЫе диаграммы при одних и тех же уставках в регистрах времянок. Т.е. если не работет на 100 кГц, то точно также, только чуть медленнее не будет работать и на 66.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...