Зависает I2C (STM32F10RBT7)

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Зависает I2C (STM32F10RBT7)

Сообщение pokk »

Добрый день, сил уже нету с i2c разбираться, ни в какую он не хочет стабильно работать.
Уже весь проект перелопатил все сторонние воздействия от кода исключил, осталась только одна функция отправки данных по i2c которая крутится в цикле. Проблема в следующем программа зависает на строчке

Код: Выделить всё

 while (!(I2C2->SR1 & I2C_SR1_ADDR)){};
Причём это происходит совсем неявно т.е может спокойно передаться 1000 посылок, потом зависнуть, а в следующий раз (после рестарта) штук 50 передаться. Так же выявил, что стабильность передачи зависит от задержки между пакетами, и вот тут начинается самое весёлое. без задержки всё работает(отправляется пакетов больше 10000) потом при какой-то магической задержки перестаёт работать(количество отправленных пакетов <100 в основном 15-60), а при увеличения её продолжает работать. Так эти задержки относятся и коду т.е если за комментировал какое-то условие(для строба синхронизации) то работает обратно вернул не работает :shock:
Спойлер

Код: Выделить всё

int main(void){
	GPIO_InitTypeDef  GPIO_InitStructure;
	I2C_InitTypeDef  I2C_InitStructure;
//========================
	//I2C_Setup_fsm(&ModeDisplayUpdate);


	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE);//

	/* I2C2 SDA and SCL configuration */
	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	/*SCL is pin06 and SDA is pin 07 for I2C2*/


    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

	//I2C_DeInit(I2C2);
//	I2C_Cmd(I2C2,DISABLE);
//	GPIO_DeInit(GPIOB);
//	GPIO_AFIODeInit();

	/* I2C2 configuration */
	I2C_StructInit(&I2C_InitStructure);
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED ;
	I2C_Init(I2C2, &I2C_InitStructure);

	// I2C2->CR1&=~I2C_CR1_SMBUS; // I2C MODE enable
	// I2C2->CR2|=I2C_CR2_FREQ_2; // Peripheral clock frequency 36MHz
	// I2C2->CR2|=I2C_CR2_FREQ_4; // Peripheral clock frequency 36MHz
	// I2C2->CCR&=~I2C_CCR_CCR; // Clear CCR bit field
	// I2C2->CCR|=0x64; // CCR=I2C_freq_clock/(2*I2C_freq_speed) = 36000000/(2*100000) - just for standart MODE (not fast) {see Ref.M. p.752}
	// I2C2->CCR&=~I2C_CCR_FS; //Standart Mode I2C
	// I2C2->TRISE|=20; // rise_time = 1000ns, T_pclk1=28ns (1/36000000) => TRISE=rise_time/T_pclk1 {see Ref.M. p.753}
	// I2C2->CR1|=I2C_CR1_PE;// peripheral enable
	// I2C_AcknowledgeConfig(I2C2, ENABLE);

	//------------------------------------------------------------------------------
	/*enable I2C*/
	//I2C_Cmd(I2C2,ENABLE);
//========================
//============Главный цикл==================
//========================
    while(1){
	//---------------------------------------------------------------------------
	//I2C2->CR1|=I2C_CR1_PE;// peripheral enable
	//--------------Cтроб для синхронизации с осциллографом(поиска места обрыва)--
		if(TEST_delay123>=CounterPascet-1){
			TEST_DELAY_OFF
		}
	//---------------------------------------------------------------------------
		I2C2->CR1 |= I2C_CR1_START;
	//---------------------------------------------------------------------------
		while (!(I2C2->SR1 & I2C_SR1_SB)){};
		//EV5: SB=1, cleared by reading SR1 register followed by writing DR register with Address.
		(void) I2C2->SR1;
		I2C2->DR = I2C_ADDR_LCD_KEY_LED;
	//----------------------------------------------------------------------------------------------
		while (!(I2C2->SR1 & I2C_SR1_ADDR)){};
		//EV6:ADDR=1, cleared by reading SR1 register followed by reading SR2.
		(void)I2C2->SR1;
		(void)I2C2->SR2;
		while (!(I2C2->SR1 & I2C_SR1_TXE)){};
		//EV8_1:TxE=1, shift register empty, data register empty, write Data1 in DR.
		I2C2->DR = 0xAA;
	//----------------------------------------------------------------------------------------------
		while (!(I2C2->SR1 & I2C_SR1_TXE)){};
		//EV8:TxE=1, shift register not empty, dataregister empty, cleared by writing DR register
		I2C2->DR = 0xff;
	//----------------------------------------------------------------------------------------------
		while (!(I2C2->SR1 & I2C_SR1_TXE)){};
		while (!(I2C2->SR1 & I2C_SR1_BTF)){}
		//EV8_2:TxE=1, BTF = 1, Program Stop request. TxE and BTF are cleared by hardware by the Stop condition
		I2C2->CR1 |= I2C_CR1_STOP;
	//----------------------------------------------------------------------------------------------
		while(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF));
	//--------------Cтроб для синхронизации с осциллографом(поиска места обрыва)--------------------
        if(TEST_delay123>=CounterPascet-1){
            TEST_DELAY_ON
        }
		//I2C2->CR1&=~I2C_CR1_PE;// peripheral disable
		//---------- ЗАДЕРЖКИ-------------------------------------------------------------
		//---------- увеличение что бы было сразу было понятно работает или нет---------------
         delay123=TEST_delay123;
         //delay123=27;
         //delay1=1;
         //delay123=60;
         //delay123=11;
		 while(delay123--);
		 TEST_delay123++;
         if(TEST_delay123>=0xFFFF){TEST_delay123=0xFFFF;}
////------------------------------------------------------------------------------------------------
	}
}
PS: В момент зависания на осциллограмме видно, что стартовый бит выставился, а вот адрес даже не начал передаваться.
Реклама
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: Зависает I2C (STM32F10RBT7)

Сообщение Mishany »

Могу предложить рабочий пример инициализации, может что заметите?
Спойлер

Код: Выделить всё

void I2C_Configuration(void)
{
   I2C_InitTypeDef  I2C_InitStructure;
   GPIO_InitTypeDef  GPIO_InitStructure; 

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);

   /* Configure I2C1 pins: PB6->SCL and PB7->SDA */
   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
   GPIO_Init(GPIOB, &GPIO_InitStructure);
		
   I2C_DeInit(I2C1);
   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
   I2C_InitStructure.I2C_OwnAddress1 = 0x30;
   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
   I2C_InitStructure.I2C_ClockSpeed = 100000;
    
   I2C_Cmd(I2C1, ENABLE);
   I2C_Init(I2C1, &I2C_InitStructure);

   I2C_AcknowledgeConfig(I2C1, ENABLE);
}
Реклама
Аватара пользователя
moLCHec
Мявтор!
Сообщения: 825
Зарегистрирован: Вс дек 18, 2005 20:04:42
Откуда: Свердловская обл.
Контактная информация:

Re: Зависает I2C (STM32F10RBT7)

Сообщение moLCHec »

Интерфейс этот сам по себе глючный, чуть что не так зависает и спасает только сброс питания.
Непонятно отчего он себя так ведет на разной архитектуре, возможно там клонируется прямо реализация в кристалле.
После траханья с ним в нескольких проектах зарекся его использовать.
Настоящий кот всегда либо голоден,
либо невыспался ...
Ответить

Вернуться в «ARM»