Вы меня кажется не поняли!
Я эти костыли применил после того, как намучался с вариантом "ПРАВИЛЬНО", который вот ну не работал и все тут
STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
dtvims писал(а):Вы меня кажется не поняли!
Я эти костыли применил после того, как намучался с вариантом "ПРАВИЛЬНО", который вот ну не работал и все тут
а вот это не правда
правильно у вас не было...
но вы почему то стыдитесь проверить это.... интересная позиция я так наоборот рад когда мне подсказывают правильные решения... - последний раз указанное мне правильное решение позволило увеличить быстродействие на 20%... хотя я тоже думал что написал "максимально эффективно" и ничего другого уже придумать нельзя )) (смотреть комменты к статье https://habrahabr.ru/post/276121/ )
ааа, даже 2 раза за последние 2 недели такое было...
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
Причем тут правда/не правда и тем более стыдитесь?
Давайте объясню более понятно:
1. У меня данный дисплей работал сперва на STM32F4Discovery, полностью софтварно. Но периодически переставал работать. Я думал, что проблема в контактах. Но однажды дисплей так и не включился, т.е. совсем. Он мне в том проекте уже не очень-то и нужен был, но обида за дисплей осталась.
2. Я его подключил к Arduino, как самое простое, тупо подключил и, либо работает, либо нет. Согласитесь, что использование SPI на контролерах ATmel отличается от STM32. Собственно, на Arduino дисплей заработал, но на скоростях до 4Мгц.
3. Когда я подключил дисплей к STM32F103, то дисплей у меня не заработал, как и ранее, на кодах как у Вас, с проверкой BSY, вот тогда я и начал эксперименты. Сперва нагуглил рекомендацию, что флаг надежнее проверять именно TXE, но проблему это не решило. Установил скорость SPI поменьше и понаставил искусственных задержек после передачи данных и переключений команды/данные. Дисплей ожил. Поигрался со скоростью SPI, где опыт повторился, что дисплей работает на скорости до 4-х Мгц. Далее стал убирать задержки, пока не осталась та, что осталась.
4. У меня есть другие SPI дисплеи (цветные). Вот они работают на максимуме, что способен выжать по SPI контроллер STM32, опять же при моем коде.
Возможно, разумнее проверять сразу оба флага и TXE и BSY. Сперва ждать TXE, а затем BSY.
Но скорость дисплея мне это не увеличит точно.
Upd.
Судя по рекомендации от ST в виде схемы выше, так и надо, сперва ждать TXE, затем BSY, т.к. BSY устанавливается только после начала передачи данных, а TXE сбрасывается при записи в буфер. Вот Вам и почему у меня с BSY не работало, проверка проскакивала, пока BSY еще не был установлен.
Upd2.
Прикинул время задержки. У меня стоит 1мс. При скорости SPI в 2МГц время передачи 1 бита около 1мкс (поправьте если ошибаюсь). Заметим, что чем выше скорость, тем меньше время передачи байта. Тогда время передачи байта всего 8мкс, а на скорости 21МГц вообще 0.8мкс. Я задержку пробовал уменьшить до 100мкс (менял функцию Delay на другую), но дисплей тоже не работал. Т.е. задержка потребовалась более чем в 100 раз больше. Все-таки есть в моем дисплее что-то еще, что не дает ему нормально работать, на высоких скоростях и без моего костыля с Delay работать он не будет при любых способах проверок. И при всем желании Ваш подход не позволил бы мне, ни увеличить скорость SPI, ни избавиться от искусственной задержки
Давайте объясню более понятно:
1. У меня данный дисплей работал сперва на STM32F4Discovery, полностью софтварно. Но периодически переставал работать. Я думал, что проблема в контактах. Но однажды дисплей так и не включился, т.е. совсем. Он мне в том проекте уже не очень-то и нужен был, но обида за дисплей осталась.
2. Я его подключил к Arduino, как самое простое, тупо подключил и, либо работает, либо нет. Согласитесь, что использование SPI на контролерах ATmel отличается от STM32. Собственно, на Arduino дисплей заработал, но на скоростях до 4Мгц.
3. Когда я подключил дисплей к STM32F103, то дисплей у меня не заработал, как и ранее, на кодах как у Вас, с проверкой BSY, вот тогда я и начал эксперименты. Сперва нагуглил рекомендацию, что флаг надежнее проверять именно TXE, но проблему это не решило. Установил скорость SPI поменьше и понаставил искусственных задержек после передачи данных и переключений команды/данные. Дисплей ожил. Поигрался со скоростью SPI, где опыт повторился, что дисплей работает на скорости до 4-х Мгц. Далее стал убирать задержки, пока не осталась та, что осталась.
4. У меня есть другие SPI дисплеи (цветные). Вот они работают на максимуме, что способен выжать по SPI контроллер STM32, опять же при моем коде.
Возможно, разумнее проверять сразу оба флага и TXE и BSY. Сперва ждать TXE, а затем BSY.
Но скорость дисплея мне это не увеличит точно.
Upd.
Судя по рекомендации от ST в виде схемы выше, так и надо, сперва ждать TXE, затем BSY, т.к. BSY устанавливается только после начала передачи данных, а TXE сбрасывается при записи в буфер. Вот Вам и почему у меня с BSY не работало, проверка проскакивала, пока BSY еще не был установлен.
Upd2.
Прикинул время задержки. У меня стоит 1мс. При скорости SPI в 2МГц время передачи 1 бита около 1мкс (поправьте если ошибаюсь). Заметим, что чем выше скорость, тем меньше время передачи байта. Тогда время передачи байта всего 8мкс, а на скорости 21МГц вообще 0.8мкс. Я задержку пробовал уменьшить до 100мкс (менял функцию Delay на другую), но дисплей тоже не работал. Т.е. задержка потребовалась более чем в 100 раз больше. Все-таки есть в моем дисплее что-то еще, что не дает ему нормально работать, на высоких скоростях и без моего костыля с Delay работать он не будет при любых способах проверок. И при всем желании Ваш подход не позволил бы мне, ни увеличить скорость SPI, ни избавиться от искусственной задержки
-
- Сообщения: 10
- Зарегистрирован: Пн окт 19, 2015 10:43 am
STM32F4Discovery SPI2 DMA SDCard FatFs
вот инициализация SPI с пинами. slave SD micro в составе FatFs от ChaN. Все работает , но почему именно так?
Код:
Код:
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
BSY показывает что передача физически еще идет..
а TXE показывает что можно следующий байт класть в SPI_DR
просто в STM32 данные уходят не из SPI_DR !! цепочка следующая:
1) записываем данные в SPI_DR
2) данные из SPI_DR перезаписываются в сдвиговый регистр, и уже из него уходят на MOSI... здесь важно понять что сдвиговый регистр - это еще один регистр !!! то есть при записи байта передача идет по цепочке SPI_DR -> Сдвиговый регистр -> MOSI
3) когда данные ушли из SPI_DR в сдвиговый регистр - тогда выставляется флаг TXE !! то есть байт еще передается (фактически начал передаваться из сдвигового регистра) а флаг TXE сбрасывается ! - он показывает что в SPI_DR можно загрузить следующий байт данных, КОТОРЫЙ БУДЕТ ЖДАТЬ (!) пока не уйдет текущий байт (который уже в сдвиговом уходит не спеша)...
В этом и кроются основные грабли при работе с дисплеями у которых есть вход Data/Command !
если вы отправили в SPI_DR код команды, предварительно установив DC=0
То вы проверку TXE пройдете сразу !!! так как после записи в SPI_DR байт сразу уйдет в сдвиговый !!!
если на этот момент не обратить внимание и следующим байтом послать данные
то будет ошибка !!! потому что дисплей еще не получил код команды (реально по MOSI пройдет максимум пара бит) - а вы меняете состояние линии DC !!!
в вашем драйвере вы интуитивно решили это введением задержки (фактически перед сменой DC0 в DC1). и это до определенных скоростей будет работать...
Но как видите - это не правильно !
Правильно перед сменой DC проверять флаг BSY !! так как этот флаг сбросится только тогда когда оба регистра (и SPI_DR и сдвиговый) будут пустыми !! то есть все будет отправлено и DC можно будет менять безопасно...
Соответственно TXE - это флаг того что данные можно пихать в SPI_DR - поэтому его нужно проверять перед записью в SPI_DR, то есть передача команды будет выглядеть вот так:
а передача данных после нее так:
И не нужно никаких задержек ! вне зависимости от скорости SPI от минимума до максимума все будет работать !!
Само собой если мы передаем однородные данные (только команды или только данные) - то BSY проверять не нужно (мы же не собираемся дергать DC) и проверяем только TXE !!!
Выигрыш в том что пока передаются данные - контроллер будет занят полезным - например готовить следующие байты к отправке..
Опять таки - если после данных мы решили опять передать команды (как например в том же ST7735 или ILI9341C) - то перед командой с ее сменой DC - нужно проверить флаг BSY !!
Я у себя в программе просто сделал три подпрограммы:
- передача байта (не трогая DC) Но с ожиданием TXE
- передача байта с DC0 и ожиданием BSY - это для команд
- передача байта с DC1 и ожиданием BSY - это для данных
Соответственно для инициализации использую только 2 и 3 процедуры (они передают с нужным DC и дожидаются по BSY фактического окончания передачи)
а вот при передаче данных при работе с дисплеем - использую первую ! (ну конечно иногда перед ней вызываю вторую для передачи команды COL/ROW позиционирования или доступа к GRAM)...
Вот например для ILI9341C (еще я перехожу в 16ти битные посылки при передачи данных - по скорости сравниваюсь с DMA передачей !!)
p.s. говоря байты - я подразумеваю что это могут быть и байты и слова в 2 байта ))
Дополнительно, само собой что CS тоже нужно менять после проверки BSY !! иначе у дисплеев тоже сносит крышу...
При работе с SD картой - все проще - там нет DC поэтому BSY можно не проверять, а работать одним только TXE, хотя это не верно ! например перед отключением CS карты желательно все таки проверить BSY, а то еще глюканет - но там спасает достаточно большое количество команд между отправкой последнего байта и отключением CS и как правило ни на что не влияет. Опять таки если вам нужно будет максимальное быстродействие от SD карты - то придется и там озадачиться...
а TXE показывает что можно следующий байт класть в SPI_DR
просто в STM32 данные уходят не из SPI_DR !! цепочка следующая:
1) записываем данные в SPI_DR
2) данные из SPI_DR перезаписываются в сдвиговый регистр, и уже из него уходят на MOSI... здесь важно понять что сдвиговый регистр - это еще один регистр !!! то есть при записи байта передача идет по цепочке SPI_DR -> Сдвиговый регистр -> MOSI
3) когда данные ушли из SPI_DR в сдвиговый регистр - тогда выставляется флаг TXE !! то есть байт еще передается (фактически начал передаваться из сдвигового регистра) а флаг TXE сбрасывается ! - он показывает что в SPI_DR можно загрузить следующий байт данных, КОТОРЫЙ БУДЕТ ЖДАТЬ (!) пока не уйдет текущий байт (который уже в сдвиговом уходит не спеша)...
В этом и кроются основные грабли при работе с дисплеями у которых есть вход Data/Command !
если вы отправили в SPI_DR код команды, предварительно установив DC=0
- Установка DC=0;
- отправка в DR=код команды
- Здесь проверка флага TXE
То вы проверку TXE пройдете сразу !!! так как после записи в SPI_DR байт сразу уйдет в сдвиговый !!!
если на этот момент не обратить внимание и следующим байтом послать данные
- Установка DC=1
- отправка в DR=данные команды
- Здесь проверка флага TXE
то будет ошибка !!! потому что дисплей еще не получил код команды (реально по MOSI пройдет максимум пара бит) - а вы меняете состояние линии DC !!!
в вашем драйвере вы интуитивно решили это введением задержки (фактически перед сменой DC0 в DC1). и это до определенных скоростей будет работать...
Но как видите - это не правильно !
Правильно перед сменой DC проверять флаг BSY !! так как этот флаг сбросится только тогда когда оба регистра (и SPI_DR и сдвиговый) будут пустыми !! то есть все будет отправлено и DC можно будет менять безопасно...
Соответственно TXE - это флаг того что данные можно пихать в SPI_DR - поэтому его нужно проверять перед записью в SPI_DR, то есть передача команды будет выглядеть вот так:
- Установка DC=0;
- Здесь проверка флага TXE
- отправка в DR=код команды
а передача данных после нее так:
- Здесь проверка флага BSY
- Установка DC=1
- Здесь проверка флага TXE
- отправка в DR=данные команды
И не нужно никаких задержек ! вне зависимости от скорости SPI от минимума до максимума все будет работать !!
Само собой если мы передаем однородные данные (только команды или только данные) - то BSY проверять не нужно (мы же не собираемся дергать DC) и проверяем только TXE !!!
Выигрыш в том что пока передаются данные - контроллер будет занят полезным - например готовить следующие байты к отправке..
Опять таки - если после данных мы решили опять передать команды (как например в том же ST7735 или ILI9341C) - то перед командой с ее сменой DC - нужно проверить флаг BSY !!
Я у себя в программе просто сделал три подпрограммы:
- передача байта (не трогая DC) Но с ожиданием TXE
- передача байта с DC0 и ожиданием BSY - это для команд
- передача байта с DC1 и ожиданием BSY - это для данных
Соответственно для инициализации использую только 2 и 3 процедуры (они передают с нужным DC и дожидаются по BSY фактического окончания передачи)
а вот при передаче данных при работе с дисплеем - использую первую ! (ну конечно иногда перед ней вызываю вторую для передачи команды COL/ROW позиционирования или доступа к GRAM)...
Вот например для ILI9341C (еще я перехожу в 16ти битные посылки при передачи данных - по скорости сравниваюсь с DMA передачей !!)
Код: Выделить всё
// передача данных на дисплей
void SPI2_SendByte(uint8_t sendData)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, sendData);
}
// отправка команды на дисплей
void ili9341c_CMD(uint8_t sendData)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12); // DC=0;
SPI2_SendByte(sendData);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
}
// отправка данных на дисплей
void ili9341c_DATA(uint8_t sendData)
{
GPIO_SetBits(GPIOB, GPIO_Pin_12); // DC=1;
SPI2_SendByte(sendData);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
}
// определение области для вывода
void ili9341c_SetWindow(uint16_t ystart, uint16_t xstart, uint16_t yend, uint16_t xend)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12); // DC=0;
SPI2_SendByte(LCD_PAGE_ADDR);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
GPIO_SetBits(GPIOB, GPIO_Pin_12); // DC=1;
SPI2_SendByte(xstart>>8);
SPI2_SendByte(xstart&0xFF);
SPI2_SendByte(xend>>8);
SPI2_SendByte(xend&0xFF);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
GPIO_ResetBits(GPIOB, GPIO_Pin_12); // DC=0;
SPI2_SendByte(LCD_COLUMN_ADDR);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
GPIO_SetBits(GPIOB, GPIO_Pin_12); // DC=1;
SPI2_SendByte(ystart>>8);
SPI2_SendByte(ystart&0xFF);
SPI2_SendByte(yend>>8);
SPI2_SendByte(yend&0xFF);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
}
// заполнение цветом прямоугольной области экрана
void ili9341c_FillRect(uint16_t ystart, uint16_t xstart, uint16_t ystop, uint16_t xstop, uint16_t color)
{
uint32_t n;
GPIO_ResetBits(GPIOB, GPIO_Pin_11); // CS=0;
ili9341c_SetWindow(ystart, xstart, ystop, xstop); // определим окно для заполнения
GPIO_ResetBits(GPIOB, GPIO_Pin_12); // DC=0;
SPI2_SendByte(LCD_GRAM);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
GPIO_SetBits(GPIOB, GPIO_Pin_12); // DC=1;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_Init(SPI2, &SPI_InitStructure);
for(n=0;n<(xstop-xstart+1)*(ystop-ystart+1);n++) { // заполняем цветом область 16ти битными посылками
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, color);
}
while (SPI_I2S_GetFlagStatus(SPI2,SPI_FLAG_BSY)!=RESET);
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_Init(SPI2, &SPI_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_11); // CS=1;
}
p.s. говоря байты - я подразумеваю что это могут быть и байты и слова в 2 байта ))
Дополнительно, само собой что CS тоже нужно менять после проверки BSY !! иначе у дисплеев тоже сносит крышу...
При работе с SD картой - все проще - там нет DC поэтому BSY можно не проверять, а работать одним только TXE, хотя это не верно ! например перед отключением CS карты желательно все таки проверить BSY, а то еще глюканет - но там спасает достаточно большое количество команд между отправкой последнего байта и отключением CS и как правило ни на что не влияет. Опять таки если вам нужно будет максимальное быстродействие от SD карты - то придется и там озадачиться...
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
В схеме от ST отлично видно все переходы статусов флагов по периодам, там же видно небольшие переходные периоды, в которые возможны фантомы, если их не учесть. Возможно в новы партиях ST исправили ситуацию и этих периодов более нет, но данная схема в документации не обновлялась (вырезал как есть из документации на stm32f103, взятой с портала ST).
Есть еще мой фантомный дисплейчик (возможно он не уникален), которому нужно что-то еще. В сети полно историй, да и сам сталкивался, когда все делаешь по правильной инструкции, а не работает. Потом выясняется, что у меня просто китайский клон, в котором есть ошибка, вот ее я и ловлю, или контроллер у меня из бракованной или недоработанной партии. Тут надо искать поправки на конкретный случай, собственно я и описал все свои тезисы.
Я же согласен, что правильно делать как Вы и описали, за что отдельное спасибо, но, согласно схеме ST, надо учитывать флаг TXE во всех случаях, из-за маленького периода, когда флаг BSY еще не установлен. И Если у Вас дисплеи работают на частотах выше 4МГц - это совсем не значит, что они у всех заработают на частотах, несоответствующих документации. В документации описаны гарантированные частоты, а, например, для серийного использования, недокументированные возможности использовать нельзя!
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
в том и дело что схема правильная, но она не показывает что есть SPI_DR и отдельно есть Shift Register..
вот и идет у всех путаница !!! - все думают что TXE и BSY это одинаковые флаги чуть разнесенные во времени ) и рассуждают о глюках во времени ))
а на деле ЭТО ФЛАГИ РАЗНЫХ РЕГИСТРОВ !! (SPI_DR и Shift)....
И показывают они разное !!! и никаких глюков во времени нет !!!
Кстати, на схеме показан случай при настройках фазы CPOL=1 CPHA=1 - а с дисплеями обычно применяют CPOL=0 CPHA=0 и там BSY возникает правильно ))
p.s. чую что скоро напишу новую статью для хабра
кстати, а фото дисплейчика есть ?!
Готов у вас купить этот дисплейчик ! или поменять на какой то другой !! (я собираю различное "странное" железо ! на нем удобно проверять конфигурации )
вот и идет у всех путаница !!! - все думают что TXE и BSY это одинаковые флаги чуть разнесенные во времени ) и рассуждают о глюках во времени ))
а на деле ЭТО ФЛАГИ РАЗНЫХ РЕГИСТРОВ !! (SPI_DR и Shift)....
И показывают они разное !!! и никаких глюков во времени нет !!!
Кстати, на схеме показан случай при настройках фазы CPOL=1 CPHA=1 - а с дисплеями обычно применяют CPOL=0 CPHA=0 и там BSY возникает правильно ))
p.s. чую что скоро напишу новую статью для хабра
кстати, а фото дисплейчика есть ?!
Готов у вас купить этот дисплейчик ! или поменять на какой то другой !! (я собираю различное "странное" железо ! на нем удобно проверять конфигурации )
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
Фото где-то было. Внешне обычный 5110 (вроде именно 51) на красной плате. Брал вроде на dx, но уже очень давно.
Продавать неохото...
Вот нашел фото, тестировал на нем вариант осциллографа, но экран очень мелкий и стал пытаться на других мониторах. Как раз подключен к ардуино, на котором работал почти без приключений, уже после того как перстал работать с discovery и я думал, что он сдох. Вообще у меня сложилось впечатление, что многие изделия на ATmel, как-то проще и надежнее получаются (видимо по тому, что слишком много тонкостей в настройках периферии в stm32). А на stm32 - usb устройства неплохо получаются, хотя я там тоже намучался только чтобы примеры от ST запустить
Продавать неохото...
Вот нашел фото, тестировал на нем вариант осциллографа, но экран очень мелкий и стал пытаться на других мониторах. Как раз подключен к ардуино, на котором работал почти без приключений, уже после того как перстал работать с discovery и я думал, что он сдох. Вообще у меня сложилось впечатление, что многие изделия на ATmel, как-то проще и надежнее получаются (видимо по тому, что слишком много тонкостей в настройках периферии в stm32). А на stm32 - usb устройства неплохо получаются, хотя я там тоже намучался только чтобы примеры от ST запустить
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
http://stm32f4-discovery.com/ Чего вы все паритесь с дисплеями, флешками и тд, посмотрите на этом сайте библиотеки норм под стмку именно серии F4, это не реклама, это избавление от ваших страданий, заюзал и у меня все запело как надо.
Re: STM32F4Discovery + SPI2 + DMA + SDCard + FatFs
А кто парится?
Под F4 оказалось все несколько проще, чем под F103, возможно именно потому, что примеров больше. Но все равно, долго выкидываешь все лишнее из примера, чтобы оставить только нужное.
Под F4 оказалось все несколько проще, чем под F103, возможно именно потому, что примеров больше. Но все равно, долго выкидываешь все лишнее из примера, чтобы оставить только нужное.
Вернуться в «Микроконтроллеры и автоматизация»
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя