Микроконтроллеры STM32 - тонкости работы, отладочные платы

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением.
Поверьте, компилятор лучше программиста знает как по массиву ходить. Впрочем, это легко проверяется. Ссылка на Compiler Explorer.
Пишем алгоритм обхода массива двумя способами.
СпойлерИзображение
изображение_2024-03-09_123816329.png
(37.58 КБ) 1045 скачиваний

И видим, что начхал компилятор на счётчик цикла и сгенерировал одинаковый бит в бит код для обоих вариантов.
СпойлерИзображение
изображение_2024-03-09_124234554.png
(48.95 КБ) 1014 скачиваний
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 429
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553264#p4553264"]но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением.
Поверьте, компилятор лучше программиста знает как по массиву ходить. Впрочем, это легко проверяется.[/uquote]
Это хорошо, что x86/x64 компилеры последние 25 лет не стояли на месте. Но что там под РУКУ? Топик же не про x86/x64. Что там с тулчейнами под РУКУ?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

x86 выбран только чтобы показать результат выполнения кода в Compiler Explorer. Для ARM компиляторы ни разу не отстают.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Добрый день! Это больше похоже на плюсы, сейчас попробую разобратся, совсем сложно пока для меня, но я стараюсь)
У меня все работает, кроме цветов. Вот фон один и тот же сзади 411 на дисплей выводит доски а с переди 476 кляксы вывел какие то. И что интересно вообще не понятно почему так может быть. Дисплеи одного класса(((Изображение

У меня белый это черный, черный это белый а красный синий ппц(((

В дисплее включал инверсию - не то(
Скорее всего дело в передаче выходит

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

void Send_DAT16(uint16_t dat){ 
        CS_LOY;  //ChipSelect loy
   DC_H;  //DC H      
   SPI1->CR1 |= SPI_CR1_CRCL;
   while (!(SPI1->SR & SPI_SR_TXE)){};
   SPI1->DR = dat;
   while (!(SPI1->SR & SPI_SR_TXE)){};
   while ((SPI1->SR & SPI_SR_BSY)){};
         CS_H;//ChipSelect Up
}


Я попробовал по анологии но не помогло)

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

*((__IO uint16_t *)&SPI1->DR) = dat;

а так похожи цвета, но все равно где то близко

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

void Send_DAT16(uint16_t dat){ 
 uint8_t  bytes[2];
bytes[0] = dat >> 8;     // high byte (0x12)
bytes[1] = dat & 0x00FF; // low byte (0x34)
Send_DAT(bytes[0]);
Send_DAT(bytes[1]);
}


Пробовал цвет разбирать на ргб и менять местами, лажа какая то(((


Методом научного тыка добилсяя того что INVON + BGR режимы дисплея плюс перестановка битов при отправке дают нужные цвета
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

TEPEM, не знаю надо ли это для вашего индикатора, но если нужно переставить местами два байта в uint16_t, то в Cortecx-M4 можно вот так сделать.

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

SPI1->DR = __REV16(dat);
Это одна ассемблерная команда.
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 429
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

TEPEM, не знаю надо ли это для вашего индикатора, но если нужно переставить местами два байта в uint16_t, то в Cortecx-M4 можно вот так сделать.

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

SPI1->DR = __REV16(dat);
Это одна ассемблерная команда.

Это несколько ассемблерных команд. Следует уточнять, что это именно своп байтов в каждом полуслове REV16 - одна атомарная команда. /душнила: офф
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

Это несколько ассемблерных команд.
Это одна команда, меняющая местами байты.
Изображение
изображение_2024-03-09_191108502.png
(13.56 КБ) 1197 скачиваний

Следует уточнять, что это именно своп байтов в каждом полуслове REV16 - одна атомарная команда.
Применительно к записи в SPI->DR это не имеет значения, он 16-битный. Поэтому, одной ассемблерной командой достигается задача перестановки двух байт, которая, похоже, нужна для правильного задания цвета.
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 429
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553522#p4553522"]Это несколько ассемблерных команд.
Это одна команда, меняющая местами байты.
Изображение
изображение_2024-03-09_191108502.png
[/uquote]
В таких случаях лучше показывать страничку из букваря, ибо там доступно несколько команд для обмена байт в слове.
СпойлерИзображение

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553522#p4553522"]Следует уточнять, что это именно своп байтов в каждом полуслове REV16 - одна атомарная команда.
Применительно к записи в SPI->DR это не имеет значения, он 16-битный. Поэтому, одной ассемблерной командой достигается задача перестановки двух байт, которая, похоже, нужна для правильного задания цвета.[/uquote]
Ну написано следующее:

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

SPI1->DR = __REV16(dat);

И написано буквально "это одна команда". Поэтому я и задушнил, чтобы новичку было понятно: одна команда это та самая __REV16(), которая свопает 2 байта в слове. Ну и касаемо темы - предположение может быть верным, что endianess у LCD другая. Либо человек не разобрался с букварём на LCD, где описаны режимы и форматы упаковки данных в изображении.

Ещё раз: я не спорю про команду, я просто оставил уточняющую ремарку.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Добрый вечер господа.
Я очень пытаюсь разобрать код предложенный уважаемым Владиславом)
Можно я по порядку поспрашиваю где с гуглом у меня ее получается понять.
Вот цикл фор с таким условием

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

for(auto &x : InitAtray)

Авто это просто слсоб взять указатель без создания перемнной? А InitArray это что? А какое условие у цикла этого? Какую роль тут выполняет двоеточие? Это точно си?)
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

Вот цикл фор с таким условием

Вот в этом сообщении этот цикл написан на обычном С.

Авто это просто слсоб взять указатель без создания перемнной?
Нет, auto это указание компилятору самому определить тип переменной x. У него для этого есть вся информация - тип элемента массива InitArray. Единственное, я ему подсказал с помощью &, что пусть лучше x будет ссылкой. Ссылка и указатель, если что, это разное.

А InitArray это что?
Это массив из структур TInitRec. Он определён в самом конце и содержит последовательность команд индикатору.

А какое условие у цикла этого?
Тут нет явного условия. Этот цикл на русском языке звучит так "Взять сcылку последовательно на все элементы массива". В теле цикла описано что с каждым элементом через эту ссылку сделать.

Какую роль тут выполняет двоеточие?
Это синтаксис оператора цикла такой.

Это точно си?)
Это точно не С :) Но, насколько я помню, вы в IAR лабаете, а там С++ по умолчанию включен. Можно всё то же самое на обычном С написать, но блин, это будет так пошло с макросами, фу...
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение IfoR »

Это C++ стандарта x11 и младше. Там есть такие формы циклов и много другого, чего нужно серьёзно изучать. InitAtray - это экземпляр контейнера (std::initializer_list, std::vector, std::list или вообще самописный), от которого можно взять итератор по методу begin() или вовсе какой-либо массив. Двоеточие - просто синтаксис. Здесь цикл последовательно шагает по каждому элементу контейнера от begin() до end() и берёт на каждом шаге его ссылку в x, которая существует только в теле цикла. auto - автоматический вывод типа элемента. Этот цикл эквивалентен С++98 коду, например, так:

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

CONTAINER::iterator it = InitAtray.begin();
while (it != InitAtray.end()) {
  TYPE &x = *(it++);

  /*
   cделать что-то с x
  */
}


VladislavS, ах да, ты-ж уже объяснил. Ну может будет не лишним. :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

Только InitAtray это обычный массив.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Linuxoid91 »

Доброго дня. Изменяю глобальную переменную в прерывании. Но основной код ее не видит, пока не сделаю printf. Но к сожалению, этот способ слишком медленный. Как грамотно менять глобальные переменные в прерывании? Cube IDE 1.12
Уош
Опытный кот
Сообщения: 700
Зарегистрирован: Вс мар 23, 2025 14:56:55

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Уош »

Непонятно совершенно. Что значит, не видит? выдаёт ошибку? или в отладчике исчезает? как объявлена переменная, где?
Приведите код, не прогнозируйте варианты ошибки самостоятельно, тем самым выбирая, какую информацию предоставлять, и не рассчитывайте на телепатию: не всем очевидно, что и как Вы сделали.
Аватара пользователя
smacorp
Друг Кота
Сообщения: 3471
Зарегистрирован: Вт окт 22, 2013 04:37:23
Откуда: Казань

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение smacorp »

Linuxoid91, объявляйте переменную как volatile, и всё обязано нормально работать.
Платы для HLDI - установки лазерной засветки фоторезиста.
Фоторезист Ordyl Alpha 350
Жидкое олово для лужения плат (видео) - самое лучшее и только у меня.
Паяльные маски XV501T-4 и KSM-S6189 (5 цветов).
Заказ печатных плат - pcbsmac@gmail.com
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Linuxoid91 »

Пишу код для воспроизведения файла с SD карты. МК STM32F411. Формат wav, 8 bit, 24 kHz, mono.
Переменные:
СпойлерVolatile возле Empflug установил по совету нейросети. Но это не помогло. Программа содержит два буфера, один из которых пишется, а другой воспроизводится.

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

uint8_t wavbuf0[512];
uint8_t wavbuf1[512];
uint16_t NmbrByte;   //Number of byte to Audio Play
uint8_t Numbuf;      //Number of played buffer
volatile uint8_t Empflug;   //Flug is Empry Buffer
uint32_t sizefile;
uint16_t i,j,k,n,tag;


Программа прерывания по таймеру. Находится в файле main.c. Изначально был в файле stm32f4xx_it.c, но в попытках понять почему не работает, в том числе произвел миграцию кода в файл main.c.:
СпойлерС частотой 24 кГц выплевывает очередной байт из буферов на ШИМ. По окончанию буфера меняет переменные Empflug и Numbuf, требуемые для корректного чтения. Команда printf - искомый костыль, чтоб переменные были видны в функции main. А вообще, он у меня перенаправлен в UART, чтоб выводить отладочную информацию. До этого, к слову, printf был в функции int main, однако там он давал лютые тормоза. Помещение их в прерывание убрало тормоза.

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

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){

   if (htim->Instance == TIM2){
      if(Numbuf==0) __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf0[NmbrByte]);
      if(Numbuf==1) __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf1[NmbrByte]);
        NmbrByte++;
        if(NmbrByte>511){
           Empflug=1;
           NmbrByte=0;
           Numbuf++;
           //if (Numbuf>1)Numbuf=0;
           Numbuf = Numbuf & 0x01;
           printf(" %d",Empflug);
           printf(" %d;",Numbuf);
        }
   }
}

Ну и собственно, код int main. Занимается монтированием, чтением, и этим вот всем. Куча отладочного вывода, ибо путь был долог и тернист. В отдельную функцию пока не вывел.
СпойлерНа незначительные вещи вроде отсеивания метаданных и какой-то обработки неполного буфера в конце файла решил забить. Благо, не аудиофильский аппарат собираю, а всего лишь светозвуковые устройства для наполнения страйкбольной игры.

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

HAL_Delay(100);


printf("Start is Mount\n");
fres = f_mount(&FatFs, "", 1);
if (fres == FR_OK) {
       printf("Mount is OK\n");
   } else {
       printf("Error code %d\n", fres);
   }
char path[30] = "00-01-radio-mayak.wav";
fres = f_open(&file, (char*)path, FA_READ);
if (fres == FR_OK) {
      printf("Open file: %s\n",path);
      printf(" \n");
      fres = f_stat((char*)path, &fno);
      if (fres == FR_OK) {
         sizefile = fno.fsize;
          n=sizefile/512;
          tag=sizefile%512;
          if(sizefile<1536){n=3;tag=0;}
          printf("Size of file %s: %lu bytes\n", path, sizefile);
          printf("512B blocks is %d full and tag %d Bytes\n",n,tag);
          fres = f_read(&file, wavbuf0, 512, &bytes_read);
          printf("512B read\n");
          Numbuf=0;
          fres = f_read(&file, wavbuf1, 512, &bytes_read);
          Empflug=0;
          n=n-1;
          HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
          printf("PWM started\n");
          NmbrByte=0;
          HAL_TIM_Base_Start_IT(&htim2);
          printf("%d\n",n);
          for(i=0;i<n;i++){
             while(Empflug==0);
             if(Empflug==1){
                if(Numbuf==0) fres = f_read(&file, wavbuf1, 512, &bytes_read);
                if(Numbuf==1) fres = f_read(&file, wavbuf0, 512, &bytes_read);
                Empflug=0;
            }

          }
              }
      HAL_TIM_Base_Stop_IT(&htim2);
        f_close(&file);
        printf("End the file\n");
    } else {

        printf("Error Open File Code: %d\n", fres);
    }

В целом, успех достигнут. Но главный вопрос с переменными остался - изменяются в прерываниях - основной код не видит. Но printf помогает. Остались мелкие фризы. Возможно, из-за длинных проводов от МК до SD карты. Используется 1-битный режим SDHC. Битрейт воспроизводимых файлов 192 кбит/с. В качестве переходника используется мертвый DFPlayer. Он тоже работал по 1-битному интерфейсу. По неизвестным причинам, несмотря на одинаковое количество используемых компонентов и текстолита, SDHC модули стоят в 5..7 раз дороже SPI :shock:
Аватара пользователя
smacorp
Друг Кота
Сообщения: 3471
Зарегистрирован: Вт окт 22, 2013 04:37:23
Откуда: Казань

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение smacorp »

Писать программы нейросетями - зло.

Изменять в обработчиках прерывания НЕvolatile переменные - двойное зло. Неудивительно, что возникли проблемы.

И отдельное зло - ожидая помощи, не отвечать на вопросы:

Уош писал(а):Что значит, не видит? выдаёт ошибку? или в отладчике исчезает?
Платы для HLDI - установки лазерной засветки фоторезиста.
Фоторезист Ordyl Alpha 350
Жидкое олово для лужения плат (видео) - самое лучшее и только у меня.
Паяльные маски XV501T-4 и KSM-S6189 (5 цветов).
Заказ печатных плат - pcbsmac@gmail.com
Уош
Опытный кот
Сообщения: 700
Зарегистрирован: Вс мар 23, 2025 14:56:55

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Уош »

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

if(Numbuf==0) __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf0[NmbrByte]);
if(Numbuf==1) __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf1[NmbrByte]);

Вы не знаете про else или всё настолько сложно, что за время выполнения первого __HAL_TIM_SET_COMPARE Numbuf может измениться? Я промолчу про сравнение с 1 и 0, но... может, стоит изучить программирование на чём-то более простом?
Как бы это я написал, после прочтения "Си за 21 день":

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

if(!Numbuf) __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf0[NmbrByte])
else __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,wavbuf1[NmbrByte]);

после прочтения второй книжки:

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

__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1, Numbuf?wavbuf1[NmbrByte]:wavbuf0[NmbrByte]); // а здесь комментарий бы написал

Через год избавился бы от сравнения вообще...

К чему я это всё: надо писать комментарии, чтобы не только мы могли понять, что Вы делаете, но и Вы сами через неделю, это раз, а два, нельзя браться за какую-либо работу, не прочитав ни одной книжки.

На вопрос ответить не могу, мне больно видеть такие условия, они путают, отвлекают и компилятор даже с отключенной оптимизацией всё нафиг поудаляет, он ведь всё-таки тоже любит, когда всё хорошо.

Добавлено after 17 minutes 43 seconds:
Re: Микроконтроллеры STM32 - тонкости работы, отладочные платы

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

 
Numbuf++;
//if (Numbuf>1)Numbuf=0;
Numbuf = Numbuf & 0x01;

У Вас всего два буфера, а Numbuf не резиновая.
Может, хотели так?:

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

 
Numbuf ^= 1;
прочитайте про таблицу истинности XOR https://habr.com/ru/companies/vdsina/articles/538298/
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение jcxz »

Изменять в обработчиках прерывания НЕvolatile переменные - двойное зло.
Вызывать printf() внутри ISR - не меньшее зло. Тем более, если этот самый printf() вызывается ещё и в фоне.
На незначительные вещи вроде отсеивания метаданных и какой-то обработки неполного буфера в конце файла решил забить. Благо, не аудиофильский аппарат собираю, а всего лишь светозвуковые устройства для наполнения страйкбольной игры.
Бедные страйкболисты! Остаётся только посочувствовать тем, кому придётся пользоваться этим г*нокодом. :facepalm:
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Linuxoid91 »

Писать программы нейросетями - зло.

Изменять в обработчиках прерывания НЕvolatile переменные - двойное зло. Неудивительно, что возникли проблемы.

И отдельное зло - ожидая помощи, не отвечать на вопросы:

Уош писал(а):Что значит, не видит? выдаёт ошибку? или в отладчике исчезает?


Основная проблема - переменная, измененная в прерывании, всегда будет ноль, когда к ней обращается основная программа. Но если после изменения сделать printf с ее участием, программа увидит корректное значение.

С Volatile вчера не помогло. Но может сегодня поможет? Бывает у Cube IDE такой загон, иногда он bin файл не перезаписывает или собирает по предыдущему коду, а я этого не заметил, приговорил Volatile, и продолжил отлаживать костыль printf...
Да, так и вышло - Cube настолько "умный", что пока не внесешь значительные изменения в код, он может не пересобраться. Не раз с утра такое замечал - куб запустил, код собрал, а бинарник остался вчерашний :cry: Сегодня я обе нужные переменные пометил как volatile, и закомментил printf, и внезапно, переменная стала корректно запрашиваться основным кодом. Может, есть специальная кнопка, которая гарантированно при компиляции кода его заново перечитает? Я собираю с помощью молотка, на котором написано "Build"

Нейросетью удобно решать мелкие глупые вопросы, которые просто так не гуглятся, а спрашивать у народа - только народ пугать :shock:
Ответить

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