|
Проблемы по I2C STM32F103RC |
|
|
|
Feb 26 2017, 09:42
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Здравствуйте. Прошу помощи, бьюсь уже 3 день немого понять где проблема. Опрашиваю память M24C16 по I2C. Нет прерывания ДАЖЕ по старту. Код инициализации: CODE 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); //
Обработчик: CODE 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 - Feb 28 2017, 10:41
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
|
|
|
|
2 страниц
< 1 2
|
 |
Ответов
(15 - 27)
|
Mar 4 2017, 08:45
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Извиняюсь. Долго не был в сети. На скрине показано что откуда то появляется непонятные 255+ACK при этом если смотреть пошагово то это приходит в I2C2->DR. Не могу понять что это....
По поводу частоты, здесь мне нужна однозначно 100КГц так как одно из устройств скофигурировано на нее. Так что 400 да же пробовать не хочется. Попробую поллинг и отпишусь. Может у кого есть рабочий кусок работы с прерываниями. ЗАРАНЕЕ БЛОГОДАРЕН
|
|
|
|
|
Mar 4 2017, 09:48
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(Obam @ Mar 4 2017, 09:33)  Вот так бы изначально и писали, что штатно подтверждены байты 255, а не DR=255+ACK. Далее... по сигналлограмме криминалов не видно, каждый байт подтверждён (аппаратно - O'k): адрес ведомого сооответствует ему? адрес данных в ведомом подтверждён ведомым (вашей 24с16)? И если это чтение (судя по сигналлограмме), так может содержимое таково? Да. Адресс ведомого по даташиту 0xA0. При чтении соответственно 0xA1. Читаем соответственно 1 байт в памяти. (Это M24C16 память). Очень смущает это 255+ACK. Ведь по идее этого быть не должно. Содержимое наверно таково и есть так как писать еще не пробовал и соответственно чистая память при инициализации может быть такова
|
|
|
|
|
Mar 4 2017, 11:20
|
Группа: Участник
Сообщений: 8
Регистрация: 13-12-12
Пользователь №: 74 834

|
Цитата(dimon_rub @ Mar 4 2017, 12:48)  и соответственно чистая память при инициализации может быть такова так в datasheet же так и сказано: Цитата The device is delivered with all the memory array bits set to 1 (each byte contains FFh)
|
|
|
|
|
Mar 4 2017, 12:18
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(MoskWin32 @ Mar 4 2017, 11:20)  так в datasheet же так и сказано: Это я увидел. Пытаюсь поднять на поллинге че то нет падения SCL при старте.... CODE void I2C_Initial(void) { I2C_InitTypeDef I2C_InitStructure;
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 = 0x01; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 100000; /* 100kHz */
I2C_Cmd(I2C2, ENABLE); I2C_Init(I2C2, &I2C_InitStructure); }
void I2C_ByteWrite(u8* pBuffer, u8 WriteAddr) { while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); WC_EEPROM_WRITE(); /* шлем старт */ I2C_GenerateSTART(I2C2, ENABLE); /* ждем подтверждение */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS(I2C_ADDRESS_M24C16, I2C_MODE_WRITE), I2C_Direction_Transmitter); /* ждем подтверждение */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* шлем адрес регистра */ I2C_SendData(I2C2, 0x01); /* ждем окончания передачи */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* шлем данные */ I2C_SendData(I2C2, *pBuffer); /* ждем */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* шлем стоп */ I2C_GenerateSTOP(I2C2, ENABLE); WC_EEPROM_READ(); }
void I2C_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead) { /* ждем пока шина не освободится */ while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); /* шлем старт */ I2C_GenerateSTART(I2C2, ENABLE); //I2C2->CR1 |= CR1_START_Set; while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS(I2C_ADDRESS_M24C16, I2C_MODE_READ), I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* шлем адрес чтения */ I2C_SendData(I2C2, ReadAddr); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* шлем старт второй раз */ I2C_GenerateSTART(I2C2, ENABLE); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS(I2C_ADDRESS_M24C16, I2C_MODE_READ), I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* Пока есть что читать */ while (NumByteToRead) { if (NumByteToRead == 1) { I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); } if (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED)) { *pBuffer = I2C_ReceiveData(I2C2); pBuffer++; NumByteToRead--; } } I2C_AcknowledgeConfig(I2C2, ENABLE); }
Сообщение отредактировал IgorKossak - Mar 4 2017, 17:05
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Mar 4 2017, 13:53
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
SCL появилось (БЫЛО ВКЛЮЧЕНО ТАКТИРОВАНИЕ USART3). Бьюсь дальше. Пишет вроде красиво, чтение пока хромает
|
|
|
|
|
Mar 4 2017, 15:46
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Ну вроде все работает. Выкладываю код может кому пригодится. Поллинг I2C M24C16. CODE void I2C_Initial(void) { I2C_InitTypeDef I2C_InitStructure;
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 = 0x01; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 100000; /* 100kHz */ I2C_Cmd(I2C2, ENABLE);
I2C_Init(I2C2, &I2C_InitStructure); }
void I2C_ByteWrite(u8* pBuffer, u8 WriteAddr) { while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); WC_EEPROM_WRITE(); /* шлем старт */ I2C_GenerateSTART(I2C2, ENABLE); /* ждем подтверждение */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS_M24C16, I2C_Direction_Transmitter); /* ждем подтверждение */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* шлем адрес регистра */ I2C_SendData(I2C2, WriteAddr); /* ждем окончания передачи */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* шлем данные */ I2C_SendData(I2C2, *pBuffer); /* ждем */ while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* шлем стоп */ I2C_GenerateSTOP(I2C2, ENABLE); WC_EEPROM_READ(); }
void I2C_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead) { /* ждем пока шина не освободится */ while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); /* шлем старт */ I2C_GenerateSTART(I2C2, ENABLE); //I2C2->CR1 |= CR1_START_Set; while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS_M24C16, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* шлем адрес чтения */ I2C_SendData(I2C2, ReadAddr); //I2C2->DR = 0x01; while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
///* Для очистки EV6 запускаем модуль снова */ //I2C_Cmd(I2C2, ENABLE);
/* шлем старт второй раз */ I2C_GenerateSTART(I2C2, ENABLE); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); /* шлем адрес */ I2C_Send7bitAddress(I2C2, I2C_ADDRESS_M24C16, I2C_Direction_Receiver); while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
while (NumByteToRead) { if (NumByteToRead == 1) { I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); } if (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED)) { *pBuffer = I2C2->DR; pBuffer++; NumByteToRead--; } } I2C_AcknowledgeConfig(I2C2, ENABLE); } Остался один вопрос. Или я уже не соображаю или .... КАК обратится к ячейки памяти если максимальный адрес 0xFFF а у нас соответственно можно в функцию I2C_SendData только 8 бит. Даже при передаче по 10бит не получается как то.
Сообщение отредактировал IgorKossak - Mar 4 2017, 17:05
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Mar 4 2017, 22:16
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
ВСЕМ ОГРОМНОЕ СПАСИБО ЗА ПОМОЩЬ. В ближайщее время сделаю на прерываниях отпишусь
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|