Top.Mail.Ru
Уведомления
Очистить все

[Закреплено] STM32 для начинающих

Страница 4 / 17
(@aleksej-6)
Level 3

@aveal Здравствуйте )

Спасибо, попробую !

ОтветитьЦитата
Размещено : 04.09.2022 11:35
(@aleksej-6)
Level 3

Ещё раз здравствуйте !

Заработала ) Только почему то пришлось в функции записи и чтения, при вызове включать spi, передавать (принимать) данные. А в конце, соответственно,  в функции передаче (чтения) выключать spi:

SPI1->CR1 |= 1<<SPI_CR1_SPE_Pos; // Включаем SPI

...

передаём данные

...

SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; // Выключаем SPI      

Если этого не сделать, то передача (приём) один раз в цикле выполниться и прекращается. Хотя сигналы по шине spi как по входу так и по выходу не прекращаются .. Но главное работает )

Надо будет "перетащить" попробовать чтение и запись на прерывания ) 

ОтветитьЦитата
Размещено : 05.09.2022 14:35
(@eduard)
Level 4 Moderator
От: @aleksej-6

SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; // Выключаем SPI

А это точно выключит его?
Если в этой позиции была 1, то "или" с этой единицей тоже даст единицу.
Так наверное правильнее:

SPI1->CR1 &= ~(1<<SPI_CR1_SPE_Pos); // Выключаем SPI

Я бы вообще вот так писал:

SPI1->CR1 &= ~SPI_CR1_SPE;
ОтветитьЦитата
Размещено : 06.09.2022 06:39
(@aleksej-6)
Level 3

@eduard Эдуард здравствуйте !

Я для "этого" и выложил код про выключение ) Честно говоря не разу сам не работал с таким способом (записью) конфигурацией регистров.. 

Сейчас у себя переправлю, спасибо ! 

ОтветитьЦитата
Размещено : 06.09.2022 08:53
Aveal
(@aveal)
Top level Admin

@aleksej-6 да, получается, что SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; на самом деле не выключает SPI, поэтому можно один раз включать при инициализациии SPI1->CR1 |= SPI_CR1_SPE; и дальше уже спокойно передавать

 

 

 

 

ОтветитьЦитата
Создатель темы Размещено : 06.09.2022 10:22
(@aleksej-6)
Level 3
От: @aveal

@aleksej-6 да, получается, что SPI1->CR1 |= 0<<SPI_CR1_SPE_Pos; на самом деле не выключает SPI, поэтому можно один раз включать при инициализациии SPI1->CR1 |= SPI_CR1_SPE; и дальше уже спокойно передавать

 

 

 

 

Две недели мучился с этим spi, пробовал всё подряд   😀

Спасибо !

ОтветитьЦитата
Размещено : 06.09.2022 11:15
Aveal
(@aveal)
Top level Admin

@aleksej-6 👍 🙂 

ОтветитьЦитата
Создатель темы Размещено : 06.09.2022 12:48
(@aleksej-6)
Level 3

Доброго времени )

Пытаюсь разобраться с интерфейсом 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 и ошибках интерфейса, используется этот бит, он как рестарт для компа... Его перед началом инициализации необходимо установить, а затем скинуть (ибо сам не сбрасывается)... Затем произвести настройки интерфейса, а затем включить...
И тогда всё будет работать нормально... Сам провозился неделю с данной проблемой... Пока дотошно референс мануал не пересмотрел...

ОтветитьЦитата
Размещено : 13.11.2022 10:24
Aveal
(@aveal)
Top level Admin

@aleksej-6 I2C по сравнению с другой периферией проблемный в STM32... Существует еще эффект с порядком инициализации - сам модуль I2C / GPIO для I2C. Не помню уже детально, но тоже на проверке флага зависает, если очередность инициализации нарушается.

ОтветитьЦитата
Создатель темы Размещено : 13.11.2022 11:18
(@aleksej-6)
Level 3

Спасибо, попробую проверять всё )

ОтветитьЦитата
Размещено : 13.11.2022 11:20
(@aleksej-6)
Level 3

При использовании  HAL_I2C_Master_Transmit_IT - тоже контроллер виснет...

ОтветитьЦитата
Размещено : 13.11.2022 13:24
(@eduard)
Level 4 Moderator

@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 это практически бесполезно.

ОтветитьЦитата
Размещено : 13.11.2022 15:17
(@aleksej-6)
Level 3

@eduard Здравствуйте ! 

Микроконтроллер 411

Сейчас у меня уже ночь на дворе, завтра дальше буду разбираться, спасибо !  

ОтветитьЦитата
Размещено : 13.11.2022 15:27
(@eduard)
Level 4 Moderator

У этого МК I2C попроще, чем у F407.
Но и отличается от того, что я делал для других.
Сгенерите проект в CubeMX с активизацией I2C и посмотрите код, сразу будет видно, какие шаги нужно сделать для того, что бы запустить.

ОтветитьЦитата
Размещено : 13.11.2022 21:45
(@aleksej-6)
Level 3

Эдуард здравствуйте ещё раз !

Ничего не понимаю пока, на момент зависания контроллера, на выводе SCL  нулевой уровень (с контроллера)..

ОтветитьЦитата
Размещено : 14.11.2022 12:43
Страница 4 / 17
Поделиться: