Ещё раз здравствуйте !
Заработала ) Только почему то пришлось в функции записи и чтения, при вызове включать spi, передавать (принимать) данные. А в конце, соответственно, в функции передаче (чтения) выключать spi:
SPI1->CR1 |= 1<<SPI_CR1_SPE_Pos; // Включаем SPI ...
передаём данные
... SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; // Выключаем SPI
Если этого не сделать, то передача (приём) один раз в цикле выполниться и прекращается. Хотя сигналы по шине spi как по входу так и по выходу не прекращаются .. Но главное работает )
Надо будет "перетащить" попробовать чтение и запись на прерывания )
SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; // Выключаем SPI
А это точно выключит его?
Если в этой позиции была 1, то "или" с этой единицей тоже даст единицу.
Так наверное правильнее:
SPI1->CR1 &= ~(1<<SPI_CR1_SPE_Pos); // Выключаем SPI
Я бы вообще вот так писал:
SPI1->CR1 &= ~SPI_CR1_SPE;
@eduard Эдуард здравствуйте !
Я для "этого" и выложил код про выключение ) Честно говоря не разу сам не работал с таким способом (записью) конфигурацией регистров..
Сейчас у себя переправлю, спасибо !
@aleksej-6 да, получается, что SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; на самом деле не выключает SPI, поэтому можно один раз включать при инициализациии SPI1->CR1 |= SPI_CR1_SPE; и дальше уже спокойно передавать
@aleksej-6 да, получается, что SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; на самом деле не выключает SPI, поэтому можно один раз включать при инициализациии SPI1->CR1 |= SPI_CR1_SPE; и дальше уже спокойно передавать
Две недели мучился с этим spi, пробовал всё подряд 😀
Спасибо !
Доброго времени )
Пытаюсь разобраться с интерфейсом I2C, использую вот такой код для работы с eeprom at24c02:
void I2C_Write (uint8_t reg_addr, uint8_t data_f)
{
//стартуем
I2C2->CR1 |= I2C_CR1_START;
while(!(I2C2->SR1 & I2C_SR1_SB)); //LED_ON();
(void) I2C2->SR1;
//передаем адрес устройства
ADDR = 0b10100000;
I2C2->DR = ADDR;
while(!(I2C2->SR1 & I2C_SR1_ADDR));
(void) I2C2->SR1;
(void) I2C2->SR2;
//передаем адрес регистра
I2C2->DR = reg_addr;
while(!(I2C2->SR1 & I2C_SR1_TXE));
//read status register to clear ADDR flag
(void) I2C2->SR2;
//пишем данные
I2C2->DR = data_f;
//while(!(I2C2->SR1 & I2C_SR1_BTF)); // wait BTF bit (ждём и дождаться не можем, но записали !!!)
(void) I2C2->SR2; //read status register to clear ADDR flag
I2C2->CR1 |= I2C_CR1_STOP;
}
uint8_t I2C_Read(uint8_t reg_addr)
{
// 1) стартуем
I2C2->CR1 |= I2C_CR1_START;
while(!(I2C2->SR1 & I2C_SR1_SB)){}; //LED_ON();
(void) I2C2->SR1;
// 2) передаем адрес устройства
ADDR = 0b10100000; // Iic_Send_Byte(0xA0)
I2C2->DR = ADDR; //
while(!(I2C2->SR1 & I2C_SR1_ADDR)){};
(void) I2C2->SR1;
(void) I2C2->SR2;
//reg_addr = 1;
// 3) передаем адрес регистра
I2C2->DR = reg_addr;
while(!(I2C2->SR1 & I2C_SR1_TXE)){};
I2C2->CR1 |= I2C_CR1_STOP;
// 4) принимаем сигнал ACK, enable ack if we select it
//I2C1->CR1 |= I2C_CR1_ACK;
// 5) рестарт
I2C2->CR1 |= I2C_CR1_START;
while(!(I2C2->SR1 & I2C_SR1_SB)){};
(void) I2C2->SR1;
// 6) передаем адрес устройства, но теперь для чтения - 0xA1
ADDR = 0b10100001;
I2C2->DR = ADDR; //
while(!(I2C2->SR1 & I2C_SR1_ADDR)){};
(void) I2C2->SR1;
(void) I2C2->SR2;
// 7) читаем
I2C2->CR1 &= ~I2C_CR1_ACK;
while(!(I2C2->SR1 & I2C_SR1_RXNE)){};
data_f = I2C2->DR;
I2C2->CR1 |= I2C_CR1_STOP;
return data_f;
}
Если вызвать "I2C_Write", программа зависает на "wait BTF bit"
Далее закомментируем "I2C_Write" и вызываем "I2C_Read" - данные считываются, программа записи записала данные !
Информации очень много по этому вопросу, но чего бы не делал - ничего не выходит.
Пишут следующее:
Проблема с установкой бита заключается в том, что при начальной инициализации интерфейса (может по причине порядка конфигурации портов либо ещё какие глюки) устанавливается бит BUSY, в самом самом начале, даже не успев включить интерфейс... Нашёл в регистре CR1 бит 15... В мануале указано, что при глюках флага BUSY и ошибках интерфейса, используется этот бит, он как рестарт для компа... Его перед началом инициализации необходимо установить, а затем скинуть (ибо сам не сбрасывается)... Затем произвести настройки интерфейса, а затем включить...
И тогда всё будет работать нормально... Сам провозился неделю с данной проблемой... Пока дотошно референс мануал не пересмотрел...
@aleksej-6 I2C по сравнению с другой периферией проблемный в STM32... Существует еще эффект с порядком инициализации - сам модуль I2C / GPIO для I2C. Не помню уже детально, но тоже на проверке флага зависает, если очередность инициализации нарушается.
Спасибо, попробую проверять всё )
При использовании HAL_I2C_Master_Transmit_IT - тоже контроллер виснет...
@aleksej-6 Я рассматривал работу с I2c на контроллере STM32F407xx https://microtechnics.ru/profilegrid_blogs/chast-12-stm32-i-c-i2c-v-cortex-m4/#more-17595 и https://microtechnics.ru/profilegrid_blogs/chast-13-stm32-i-c-eeprom-at24cxx/#more-17599
Здесь есть библиотеки для работы с I2C https://disk.yandex.ru/d/ymB60PAjT5rjTw
Посмотрите, есть ли библиотека для вашего МК.
Как работать с I2C зависит от того, какой МК используете.
Скажите какой МК у Вас и я подскажу, куда двигаться.
И не стремитесь по каждому чиху использовать прерывания. С I2C это практически бесполезно.
@eduard Здравствуйте !
Микроконтроллер 411
Сейчас у меня уже ночь на дворе, завтра дальше буду разбираться, спасибо !
У этого МК I2C попроще, чем у F407.
Но и отличается от того, что я делал для других.
Сгенерите проект в CubeMX с активизацией I2C и посмотрите код, сразу будет видно, какие шаги нужно сделать для того, что бы запустить.
Эдуард здравствуйте ещё раз !
Ничего не понимаю пока, на момент зависания контроллера, на выводе SCL нулевой уровень (с контроллера)..