STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

Re: STM32 новичку в ARM что к чему

Сообщение menzoda »

Во-первых, почему обработка именно в фоне? Она настолько сложная? Почему бы её не поместить в прерывание? Это упростит задачу.

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

В-третьих, если все же оставлять обработку в фоне, то опять не обязательно использовать два прерывания. Можно оставить только одно из них, например у АЦП, оно будет устанавливать флаг готовности, который ты будешь проверять в фоне. Когда АЦП будет готов читай из него данные, обрабатывай и пиши в ЦАП. Можно, опять же, сделать наоборот, всё зависит особенностей задачи.

В-четвертых, если ты решил оставить обработку в фоне, то использовать глобальные переменные нехорошо (чаще всего). Например, тебе нужно в фоне дожидаться готовности значения АЦП и потом забирать его. Сделай для АЦП отдельный модуль (файл) вот с такой реализацией:

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

// adc.h

// Инициализирует драйвер АЦП и запускает преобразование.
void adc_init(void);

// Возвращает истинное значение, если АЦП готов.
bool adc_is_ready(void);

// Возвращает последнее оцифрованное значение, сбрасывает флаг готовности.
u16_t adc_get_value(void);


// adc.c
static u16_t adc_value;
static bool_t adc_ready;

// Обрабатывает прерывания АЦП.
static void adc_isr(void)
{
    // TODO: Копируем значение в adc_value.
    adc_ready = true;
}

void adc_init(void)
{
    // TODO: Инициализация периферии.
    // TODO: Запускаем АЦП.
    
    adc_value = 0;
    adc_ready = false;
}

bool adc_is_ready(void)
{
    return adc_ready;
}

u16_t adc_get_value(void)
{
    adc_ready = false;
    return adc_value;
}
В данном случае, если я ничего не упустил, то запрещение прерываний не нужно. Для ЦАП сделай такой же отдельный модуль:

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

// dac.h

// Инициализирует драйвер ЦАП.
void dac_init(void);

// Возвращает истинное значение, если ЦАП готов к записи.
bool dac_is_ready(void);

// Устанавливает значение ЦАП.
void dac_set_value(u16_t value);


// dac.c
static bool_t dac_ready;

// Обрабатывает прерывания ЦАП.
static void dac_isr(void)
{
    // Преобразование ЦАП завершено, ЦАП готов принять следующее значение.
    dac_ready = true;
}

void dac_init(void)
{
    // TODO: Инициализация периферии.
    
    dac_ready = true;
}

bool dac_is_ready(void)
{
    return dac_ready;
}

void dac_set_value(u16_t value)
{
    // TODO: Запретить прерывания ЦАП.
    dac_ready = false;
    // TODO: Записываем значение value в ЦАП и ждем окончание преобразования.
    // TODO: Разрешить прерывания ЦАП.
}
Я не знаю как устроен ЦАП в STM, возможно он по-другому работает, тогда переделай как нужно. Кроме того, я тут использовал запрет прерываний, но может они и не нужны, нужно точно знать как работает ЦАП, ну и задачу в целом, в общем сам решай. Напоследок, использование всего этого в фоне:

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

void main(void)
{
    while(1)
    {
        while(!adc_is_ready());
        value = adc_read();
        // TODO: Обработка value.
        while(!dac_is_ready());
        dac_set_value(value);
    }
}
Вся эта писанина только один из немногих вариантов.
Реклама
Аватара пользователя
Грендайзер
Мучитель микросхем
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Re: STM32 новичку в ARM что к чему

Сообщение Грендайзер »

menzoda, спасибо за развёрнутый ответ (впрочем как всегда :)) ). Правда есть некоторые моменты, которые мне всё ещё не понятно:
1)
Можно оставить только одно из них, например у АЦП, оно будет устанавливать флаг готовности, который ты будешь проверять в фоне
Вот тут то и запарка - флаг я поднимаю в обработчике прерываний, а опускать его в фоне мне компилятор не даёт (работаю в atmelstudio микросхема - ATSAM4SD32C).
2) Не совсем понял с ф-цией adc_is_ready. После функции adc_init флаг adc_ready опускается. Где он должен подняться? В прерывании?
Во-первых, почему обработка именно в фоне? Она настолько сложная?

Нет, мне интересна теоретическая сторона вопроса. В книгах по программированию контроллеров (не только ARM) дано много примеров кодов для моргания светодиодами, передачей данных по uart/spi/i2c, работой с ацп/цап и т.д. но вот о взаимодействии периферии, о том как увязывать разные исполняемые потоки, о структурной организации программ - ни слова :(
Реклама
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

Re: STM32 новичку в ARM что к чему

Сообщение menzoda »

Грендайзер писал(а):Вот тут то и запарка - флаг я поднимаю в обработчике прерываний, а опускать его в фоне мне компилятор не даёт (работаю в atmelstudio микросхема - ATSAM4SD32C).
В смысле? Почему не дает? Не понял.
Грендайзер писал(а):2) Не совсем понял с ф-цией adc_is_ready. После функции adc_init флаг adc_ready опускается. Где он должен подняться? В прерывании?
Да, в обработчике прерывания adc_isr, там же написано. После инициализации он сброшен, так как АЦП еще ничего не сделал. Как АЦП закончит оцифровку, возникнет соответствующие прерывание. В обработчике прерывания получаем оцифрованное значение и устанавливаем флаг - оно теперь готово для чтения из фона. В фоне мы видим установленный флаг и вызываем функцию adc_get_value, чтобы получить то самое оцифрованное значение. При вызове этой функции флаг готовности сбрасывается, мы ведь прочитали это значение, всё, надо ждать нового.
Грендайзер писал(а):Нет, мне интересна теоретическая сторона вопроса. В книгах по программированию контроллеров (не только ARM) дано много примеров кодов для моргания светодиодами, передачей данных по uart/spi/i2c, работой с ацп/цап и т.д. но вот о взаимодействии периферии, о том как увязывать разные исполняемые потоки, о структурной организации программ - ни слова
Ааа, ну тогда пожалуйста, тренировка так тренировка. Оставляй самый сложный вариант с двумя прерываниями, сделай для АЦП и ЦАП по отдельному модулю по образу и подобию моих примеров выше.

Еще хочу уточнить насчет работы ЦАП, чтобы можно было точнее подсказывать. Он работает как я и думаю? Записываешь в него какое-то значение, а потом ждешь, когда он "сообразит" это значение в виде аналогового уровня на выходе? Если так, то есть ли у него прерывание, которое сигнализирует о завершении этого процесса?

Кстати, если ты обратил внимание, то во всех этих примерах не нужно каждый раз заново "взводить" АЦП, ни из прерывания, ни из фона, ни откуда. При настройке разрешаешь прерывание по окончанию процесса оцифровки, настраиваешь АЦП на автоматическую работу, пускаешь АЦП, профит. АЦП теперь сам крутиться: оцифровывает, вызывает прерывание, оцифровывает, вызывает прерывание, и так бесконечно, ну пока вручную не остановишь. Однако, можно сделать и "ручное" управление, например: настраиваешь АЦП на однократную оцифровку; пускаешь; после того, как получил значение, в функции adc_get_value запускаешь его заново. Ручной вариант предпочтительнее, если обработка каждого измерения занимает много больше времени, чем оцифровка: чтобы АЦП лишний раз не дергался, пока мы обрабатываем еще то, предыдущее оцифрованное значение.
Аватара пользователя
Грендайзер
Мучитель микросхем
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Re: STM32 новичку в ARM что к чему

Сообщение Грендайзер »

В смысле? Почему не дает? Не понял.
В прямом... программа не работает... Я вот туточки об ентом упоминал. Смысл в следующем: если я в прерывании устанавливал переменную, то после её проверки в фоне её сбросить не удавалось. Программа уходила в какой то бесконечный цикл, либо выполняла операторы не относящиеся к данному флагу (блее того, в ассемблерном коде данный флаг вообще оптимизировался). Данная проблема решалась с помощью запрета прерывания в обработчике перед выходом из обработчика прерывания, и затем включением его после сброса флага в фоне т.е.

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

while (1)
   {
       if(flag)
       { 
            func(value); // тут что то делаем
            flag = 0; // сбрасываем флаг
        }
   }
   return 0;
}
void ADC_Handler( void )
{    
   
   value = ADC_read(); // читаем всё что можно прочесть
   flag = 1; // устанавливаем флаг
   ADC_start(); // снова запускаем АЦП
   return;
}


так вот такая штука не работает. А вот так

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

while (1)
   {
       if(flag)
       { 
            func(value); // тут что то делаем
            flag = 0; // сбрасываем флаг
            ADC_interrupt_on(); // разрешаем прерывание от АЦП
            ADC_start(); // запускаем АЦП
        }
   }
   return 0;
}
void ADC_Handler( void )
{    
   ADC_interrupt_off(); // запрещаем прерывание от АЦП
   value = ADC_read(); // читаем всё что можно прочесть
   flag = 1; // устанавливаем флаг
  // ADC_start(); // эту строчку исключаем
   return;
}
Как я понял происходит это по следующей причине: флаг был изменён в обработчике прерывания. В фоне может сложиться неприятная ситуация когда в процессе работы с переменной value процессор снова уйдёт в прерывание и данные окажутся потерянными... Знаете, я вот подумал, а ведь дело и не в флаге наверное. Что будет, если скажем прерывание наступит после того как я сброшу флаг, но до того как я обработаю value. На electronix.ru я писал, что скорость работы ядра 120МГц (хотя конечно ниже из-за того, что флеш память за ним не поспевает). А тактовая скорость ЦАП/АЦП 20МГц (при том, что надо по 20 тактов на отсчет). И я думал что ядро успеет всё обработать между прерываниями. Возможно компилятор/оптимизатор так не думает...
Еще хочу уточнить насчет работы ЦАП
Да, Вы совершенно правы. Как только тот преобразует - он выдаёт прерывание.
Кстати, если ты обратил внимание, то во всех этих примерах не нужно каждый раз заново "взводить" АЦП
Да, тут Вы то же правы. Правда как я понял из даташита (конечно я может и не увидел) но сам по себе он крутиться не станет. Его постоянно нужно пинать... правда пинать его может внешний запускающий сигнал, внутренние таймеры и ещё что то... т.е. постоянно его самому возводить не обязательно...
Последний раз редактировалось Грендайзер Ср янв 27, 2016 22:18:26, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

Re: STM32 новичку в ARM что к чему

Сообщение menzoda »

Грендайзер писал(а):Смысл в следующем: если я в прерывании устанавливал переменную, то после её проверки в фоне её сбросить не удавалось. Программа уходила в какой то бесконечный цикл, либо выполняла операторы не относящиеся к данному флагу (более того, в ассемблерном коде данный флаг вообще оптимизировался).
Скорее всего из-за того, что флаг не был объявлен как volatile. Сделайте как я показал, без глобальных флагов, а с помощью отдельного модуля работы с АЦП, там такой проблемы не будет. Если что, то можете определить adc_ready как volatile bool, чтобы уж наверняка.
Грендайзер писал(а):Как только тот преобразует - он выдаёт прерывание.
Ну тогда отлично, мой пример с ЦАП подходит.
Грендайзер писал(а):Правда как я понял из даташита (конечно я может и не увидел) но сам по себе он крутиться не станет. Его постоянно нужно пинать...
Очень сомневаюсь, все АЦП во всех МК сделаны по одному образу и подобию, и все они могут работать в автономном режиме. За исключением разве что совсем уникальных экземпляров к коим Atmel и ARM вряд ли относятся.

Посмотрел даташит, там этот режим называется Freerun.
Реклама
Аватара пользователя
Грендайзер
Мучитель микросхем
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Re: STM32 новичку в ARM что к чему

Сообщение Грендайзер »

Большое спасибо. Завтра поэкспериментирую! :beer:
Реклама
Аватара пользователя
Грендайзер
Мучитель микросхем
Сообщения: 479
Зарегистрирован: Вт июн 02, 2009 22:38:40
Откуда: Город-герой Москва

Re: STM32 новичку в ARM что к чему

Сообщение Грендайзер »

menzoda, сделал всё как Вы сказали - всё прекрасно работает :beer: :))) Правда так до конца и не понял чем моё решение в лоб отлично от Вашего :dont_know: Наверно нужно Си подучить и ещё что нибудь умное почитать. Вообщем продолжу эксперименты.Ещё раз большое спасибо! :)
M@T_F@Q
Родился
Сообщения: 5
Зарегистрирован: Пн июл 23, 2007 21:22:15
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение M@T_F@Q »

Добрый день товарищи.... Вот решил взяться за ум... и тут же столкнулся с проблемой.. Скачал последнюю версию STM32CubeMX, скачал KEIL5 (WINDOWS8... пробовал KEIL4 - не хочет работать на WINDOWS8). Смотрел много примеров где правят ручками.... также смотрел где вообще ничего не правят ручками... Собственно вопрос - Почему STM32CubeMX не хочет компилировать проект?

Также сделал скрины настроек.

Заранее спасибо.

Изображение Изображение Изображение Изображение Изображение
LLlypuk
Родился
Сообщения: 1
Зарегистрирован: Сб янв 30, 2016 23:33:13

Re: STM32 новичку в ARM что к чему

Сообщение LLlypuk »

Здравствуйте, помогите пожалуйста разобраться. Два дня читаю про АРМ7 и понимаю чем дальше в лес тем больше дров. Я некогда не программировал но вот жизнь заставила. Проблема в перепрошивке а точнее в прошивке микроконтролера NXP lpc2364fbd100. подскажите с чего начать а точнее чем можно перепрошить этот контроллер. Вот этим я смогу прошить stm32f103c8t6 или надо ещё к нему jtag покупать? если не сложно то поподробнее
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Re: STM32 новичку в ARM что к чему

Сообщение a5021 »

Известно, что при старте МК можно программно уточнить кое-какие нюансы, непосредственно предшествовавшие старту. В том смысле, что выяснить был ли старт вызван подачей питания, или случилась перезагрузка с кнопки или от ватчдога и т.п. Информация об этом может находится в регистре RCC_CSR (здесь и дальше я говорю о STM32F030) в виде битов, где каждый бит ответствует за то или иное событие, произошедшее накануне старта. Большинство из этих событий/битов имеют понятное описание в мануале и просты для понимания. Однако, это не относится (c моей точки зрения), как минимум, к двум флажкам -- "Bit 31 LPWRRSTF: Low-power reset flag Set by hardware when a Low-power management reset occurs." и "Bit 23 V18PWRRSTF: Reset flag of the 1.8 V domain. Set by hardware when a POR/PDR of the 1.8 V domain occurred." Убей гром, но я не могу найти ни внятного описания обоих, ни понять смысла, какую ситуацию они должны отображать. Если 31-ый бит меня не беспокоит, то 23-ий я вижу всякий раз, когда перегружаюсь выходя из Standby. Если это POR/PDR, то для этого есть "Bit 27 PORRSTF: POR/PDR reset flag". При чем тут 1.8в домен, если он в стендбае погашен совсем? Самое главное, я не могу въехать, свидетельствует ли установка этого бита об аварийной ситуации или, напротив, оно означает, что 1.8в домен теперь "как новенький" после успешного резета.
Аватара пользователя
Alexey_N
Сверлит текстолит когтями
Сообщения: 1273
Зарегистрирован: Вт фев 01, 2011 17:56:40
Откуда: г. Жуковка, Брянская обл.

Re: STM32 новичку в ARM что к чему

Сообщение Alexey_N »

Вопрос новичка: как работают приоритеты прерываний в Cortex-M3? Настроил кнопку на PB0->EXTI0, приоритет 2 задал. Внутри обработчика настраиваю SysTick для задержки с приоритетом 0, но обработчик таймера внутри exti0_handler не вызывается, почему то...
Индукционный нагреватель - 20% (наладка). TIG сварка - 10% (детальки)
ВЧ генератор 150МГц - 80% (наладка). Мостовой ИИП - 40% (подкл. ОС).
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: STM32 новичку в ARM что к чему

Сообщение Satyr »

Там отдельно натачивается и свой приоритет, и приоритет прерываний, которые могут быть вызваны при обработке твоего - не забудь это натачить.
Ну и по привычке в обрабочтки прерываний не отключать глобально обработку прерываний ядром -))
Аватара пользователя
Alexey_N
Сверлит текстолит когтями
Сообщения: 1273
Зарегистрирован: Вт фев 01, 2011 17:56:40
Откуда: г. Жуковка, Брянская обл.

Re: STM32 новичку в ARM что к чему

Сообщение Alexey_N »

Satyr писал(а):Там отдельно натачивается и свой приоритет, и приоритет прерываний, которые могут быть вызваны при обработке твоего
А где это? Приоритет Fault Interrupts (первые 16 векторов) задается только, как я понял, в группе регистров SHPR1, SHPR2, SHPR3, а External Interrupts (остальные) в группе регистров IPR0-IPR67 NVIC. И там и там устанавливается старший ниббл в значение от 0 до 15.
Индукционный нагреватель - 20% (наладка). TIG сварка - 10% (детальки)
ВЧ генератор 150МГц - 80% (наладка). Мостовой ИИП - 40% (подкл. ОС).
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Re: STM32 новичку в ARM что к чему

Сообщение a5021 »

Никто не в курсе, можно ли ватчдогам (IWDG и WWDG) менять параметры после того, как они уже запущены? Остановить нельзя, а вот поменять значения прескалера или счетчика можно?
Аватара пользователя
baghear
Опытный кот
Сообщения: 791
Зарегистрирован: Вт июн 17, 2014 00:34:26

Re: STM32 новичку в ARM что к чему

Сообщение baghear »

Добрый день, подскажите пожалуйста почему в комментарии пишется, что адрес равен 0х0800041С
http://prntscr.com/9zxd6p
Alex_Golubev
Встал на лапы
Сообщения: 87
Зарегистрирован: Вс ноя 15, 2015 05:54:13

Re: STM32 новичку в ARM что к чему

Сообщение Alex_Golubev »

Подскажите. Можно настроить таймер в stm32 на работу с внешним управляющим входом, разрешающим или останавливающим счет?
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32 новичку в ARM что к чему

Сообщение HHIMERA »

Можно... смотрите референс и примеры от СТМ...
"Я не даю готовых решений, я заставляю думать!"(С)
Аватара пользователя
Alexey_N
Сверлит текстолит когтями
Сообщения: 1273
Зарегистрирован: Вт фев 01, 2011 17:56:40
Откуда: г. Жуковка, Брянская обл.

Re: STM32 новичку в ARM что к чему

Сообщение Alexey_N »

Все еще пытаюсь разобраться с проблемой, выяснил, что после настройки systick внутри обработчика exti0 в регистре SCB_ICSR устанавливается соответствующий бит постановки прерывания systick в очередь, биты ожидающего прерывания VECTPENDING также устанавливаются в значение 15, что соответствует таймеру, но сам обработчик не вызывается ...
Индукционный нагреватель - 20% (наладка). TIG сварка - 10% (детальки)
ВЧ генератор 150МГц - 80% (наладка). Мостовой ИИП - 40% (подкл. ОС).
fff_br
Родился
Сообщения: 13
Зарегистрирован: Вт окт 04, 2011 09:51:33

Re: STM32 новичку в ARM что к чему

Сообщение fff_br »

Подскажите, как сделать сохранение значения указателя на переменную в массив char[] ?

т.е. есть массив char str[10];
и переменная uint8_t s;

в массив str нужно записать значение(адрес переменной s) указателя, чтобы потом в программе взять этот адрес из массива и изменить значение переменной s.

P.S. IAR, STM32
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Re: STM32 новичку в ARM что к чему

Сообщение a5021 »

Несколько сложно понять ваши объяснения, но если я их понял правильно, то вам требуется нечто наподобие функции itoa(), которая существует в различных вариантах языка Си, но которой нет в IAR-е. Вопрос этот пользователи IAR-а задавали уже неоднократно и в интернетах можно найти самописные реализации этой функции.
Ответить

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