как запустить RTT таймер на DUE
- Войдите на сайт для отправки комментариев
Чт, 17/12/2015 - 13:02
Добрый!
Помогите!, как запустить RTT таймер?
Условие: 1 раз в секунду запускать prc()
DueTimer не подходит.
Оказывается , она конфликтует с LiquidCrystal.
DueTimer и LiquidCrystal включаются, но при попытке напечатать на экране сообщение - программа зависает.
Если запускать функции пораздельности все работает. Вместе - нет.
Пример http://arduino.ru/forum/programmirovanie/zalipaet-rtt-vnutri-obrabotchik... тоже не работает. Таймер тикает, обработчик вызывается единожды.
Кто знает - разжуйте пример, пожалуйста!
А в чем конфликт заключается? Может просто пины переназначить?
применяю такой шилд http://www.dfrobot.com/wiki/index.php?title=Arduino_LCD_KeyPad_Shield_%28SKU:_DFR0009%29
пины не переназначить))
работают таймер и шилд.
Ошибка вот в чем: цикл loop крутится, прерыванию по таймеру обрабатываются. Но если попытаться вывести lcd.print("Hello") ; то программа останавливается, луп и прерывания не крутятся.
При этом , если в программе закоментировать все, что связано с таймером - lcd.print () работает верно
Есть подозрение, что обе библиотеки пользуются одинаковыми прерываниями/таймерами, что и приводит к конфликту.
хочу вместу ДуеТаймер запустить RTT таймер. Описания , как сделать - нет нигде...
разобрался сам.
Таймер в DUE
// These are the clock frequencies available to the timers /2,/8,/32,/128 // 84Mhz/2 = 42.000 MHz // 84Mhz/8 = 10.500 MHz // 84Mhz/32 = 2.625 MHz // 84Mhz/128 = 656.250 KHz // // 42Mhz/44.1Khz = 952.38 // 10.5Mhz/44.1Khz = 238.09 // 2.625Hmz/44.1Khz = 59.5 // 656Khz/44.1Khz = 14.88 // 131200 / 656000 = .2 (.2 seconds) // 84Mhz/44.1Khz = 1904 instructions per tick const int led_pin = 13; int state = false; int interruptCtr = 1; int S = 0; void setup() { pinMode(led_pin, OUTPUT); /* turn on the timer clock in the power management controller */ pmc_set_writeprotect(false); // disable write protection for pmc registers pmc_enable_periph_clk(ID_TC7); // enable peripheral clock TC7 /* we want wavesel 01 with RC */ TC_Configure(/* clock */TC2,/* channel */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4); TC_SetRC(TC2, 1, 131200); TC_Start(TC2, 1); // enable timer interrupts on the timer TC2->TC_CHANNEL[1].TC_IER=TC_IER_CPCS; // IER = interrupt enable register TC2->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS; // IDR = interrupt disable register /* Enable the interrupt in the nested vector interrupt controller */ /* TC4_IRQn where 4 is the timer number * timer channels (3) + the channel number (=(1*3)+1) for timer1 channel1 */ NVIC_EnableIRQ(TC7_IRQn); } void loop() { // do nothing timer interrupts will handle the blinking; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // INTERRUPT HANDLERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void TC7_Handler() { // We need to get the status to clear it and allow the interrupt to fire again TC_GetStatus(TC2, 1); state = !state; digitalWrite(led_pin, state); if( interruptCtr++ >= 6 ) { interruptCtr = 1; S = !S; // are we flashing S or O if( S ) // set time till next interrupt TC_SetRC(TC2, 1, 131200); // 131200 / 656000 = .2 seconds else TC_SetRC(TC2, 1, 656000); // 656000/ 656000 = 1 second } }Не могли бы вы объяснить строки
07// 42Mhz/44.1Khz = 952.3808// 10.5Mhz/44.1Khz = 238.0909// 2.625Hmz/44.1Khz = 59.510// 656Khz/44.1Khz = 14.88 // 131200 / 656000 = .2 (.2 secondsОткуда вы берете 44.1 kHz,при желании можете подсказать как настроить таймер на частоту 10kHz спасибо)
cerceli, предыдущий оратор просто взял готовый пример с ардуино.сс Лично меня тошнит от этих CMSIS'овских функций, предпочитаю прямую запись в порты. Вот вам прерывания 10 тыщ раз в секунду. В дефайне "freq" можно задать другую частоту в разумных пределах :)
#define freq 10000 // частота прерываний, Герц void setup() { pinMode (13,OUTPUT); REG_PMC_PCER0|=1<<27; //включить тактирование "TC0" REG_TC0_CMR0=1<<14;//CTC mode REG_TC0_RC0= 21E6/freq; // рассчёт частоты REG_TC0_CCR0=5; //Обнулить счётчик и запустить. REG_TC0_IER0=1<<4; // прерывание NVIC_EnableIRQ(TC0_IRQn); } void loop() {} void TC0_Handler(void){ if (REG_TC0_SR0&(1<<4)==0) {return;} REG_PIOB_ODSR^=1<<27; //дрыгать 13 ногой (как пример) }Согласен с Вашим мнением.Спасибо!)
cerceli, предыдущий оратор просто взял готовый пример с ардуино.сс Лично меня тошнит от этих CMSIS'овских функций, предпочитаю прямую запись в порты. Вот вам прерывания 10 тыщ раз в секунду. В дефайне "freq" можно задать другую частоту в разумных пределах :)
#define freq 10000 // частота прерываний, Герц void setup() { pinMode (13,OUTPUT); REG_PMC_PCER0|=1<<27; //включить тактирование "TC0" REG_TC0_CMR0=1<<14;//CTC mode REG_TC0_RC0= 21E6/freq; // рассчёт частоты REG_TC0_CCR0=5; //Обнулить счётчик и запустить. REG_TC0_IER0=1<<4; // прерывание NVIC_EnableIRQ(TC0_IRQn); } void loop() {} void TC0_Handler(void){ if (REG_TC0_SR0&(1<<4)==0) {return;} REG_PIOB_ODSR^=1<<27; //дрыгать 13 ногой (как пример) }Добрый день, продолжаю плутать в даташите)
В указанном вами примере в регистре REG_TC0_CMR0 вы установили бит "CTC mode", соответственно бит TCCLKS: выбор синхронизации при этом нулевой - TIMER_CLOCK1=MCK/2=84/2=42Mhz. Период тактового сигнала =1/42000000=0.0238мкс, при таком периоде для формирования интервала в 100 мкс необходимо 100/0.0238=4201 такт, т.е значение регистра TC0_RC0 должно быть равным 4200. Не ясен Ваш расчет частоты REG_TC0_RC0= 21E6/freq - то бишь 2100 , не могли бы Вы пояснить
cerceli, для формирования одного полного периода сигнала на выходе таймера требуется два такта таймера. Я просто не стал писать 42E6/2/freq, а сразу разделил :)
Спасибо,начал понимать чуть чуть как все работает. Голова конечно пухнет, но оно того стоит)
Добрый день, извините за назойливость, но спросить больше некого(.Планирую запускать АЦП каждые 100мкс через выход TIOA канала 0 таймера-счетчика, соответственно ADC_MR=1038FF83. Как я понял преобразования АЦП запускаются передним фронтом TIOA, для этого настроил TC0 на режим WAVE=1; WAVSEL=10->REG_TC0_CMR0|=0xC000;
Не моглибы вы подсказать как можно отследить период TIOA или периодичность старта АЦП? Код работает, но не дает покоя мысль о том, что периодичность 100 мкс не соблюдается.
Serial.begin(9600); REG_PMC_PCER0|=1<<27; REG_TC0_CMR0|=0xC000; REG_TC0_RA0=99; REG_TC0_RC0= 3999; REG_TC0_CCR0=5; pmc_enable_periph_clk(ID_ADC); ADC->ADC_CR |=1; ADC->ADC_MR= 0x1038ff00; ADC->ADC_CHER=0x80; ADC->ADC_MR |=0x10000000; ADC->ADC_MR |=0x83; } void loop() { int Uism_U=ADC->ADC_CDR[7]; Serial.println(Uism_U); }Что у вас за перекладывания туда сюда в 10, 12 и 13 строке? Запишите один раз и лучше побитно (для удобства чтения) что вы туда кладёте. Если не ошибся в счёте, то ваш итоговый mod-регистр такой: REG_ADC_MR = B10000001110001111111110000011 про 7ой бит сказано -Free Run Mode: Never wait for any trigger. Значит по идее АЦПшка строчит со всей своей дури. Проверить можно например прикрутив прерывание на конец конверсии (REG_ADC_IER), и дёргая там какой-нибудь порт, и частотомером узнать реальную скорость. С АЦП я не проводил экспериментов, так что советы чисто теоритические.
void setup() { pinMode (13,OUTPUT); pmc_enable_periph_clk(ID_ADC); ADC->ADC_CR |=1; ADC->ADC_MR= 0x1038ff03; //TRGEN=1;TRGSEL=ADC_TRIG1(TIOA Output of the Timer Counter Channel 0) ADC->ADC_CHDR=0xFFFFFFFF; ADC->ADC_CHER=0x80; ADC->ADC_IDR=~((1<<7)); REG_ADC_IER=1<<7; NVIC_EnableIRQ(ADC_IRQn); // Serial.begin(250000); REG_PMC_PCER0|=1<<27; REG_TC0_CMR0|=0x9A000; REG_TC0_RA0=100; REG_TC0_RC0= 4000; REG_TC0_CCR0=5; } void loop() { } void ADC_Handler(void){ if (ADC->ADC_ISR&(1<<7)==0) {return;} REG_PIOB_ODSR^=1<<27; } //Поставил режим wave и выставил RA, RC как только не игрался с ними частота 1.2 мгц (трещания порта). Не соответствует задуманному(cerceli, правильно. У вас косяк на косяке сидит. Не хотелось всё по битам проверять, но придётся. Начнём с таймера. 14 строка. TIOA -это порт таймера, даже вне зависимости примаплена ли к нему физическая нога его можно сделать как вход , как выход, и можно настроить его поведение при разных ситуациях. В ваших настройках вообще нет ничего, что регулирует поведение TIOA, далее 13-ым битом (WAVSEL=1) вы заставляете крутить таймер счётчик по кругу, но при этом ни RC ни RA вообще никак не задействованы. Я конечно могу написать как нужно расставить биты, но лучше бы вам самому до этого дойти, у вас явно потенциал для этого есть. Подсказка -регистр RA не потребуется, нужно переделать wavsel, что-б счёт был до RC, а TIOA настроить так, что б он туглился при совпадении RC. С АЦП я слабо знаком, поэтому всё теоритически. 5 строка -возможно ок. 6 строка -думаю не требуется. 7- ок, 8 строка -бессмысленная операция. 9 строка -наверное ок. 23 строка - не факт... Отступление: - в прерываниях ARM есть одно существенное отличие от прерываний AVR. Там если прога вошла в прерывание, то флаг прерывания в системном регистре прерываний автоматом снимается. А тут -не снимается. Тут нужно либо специально его как-то снять (я пока не пробовал этот путь), либо выполнить некое действие, снимающее этот флаг. Иначе выйдя из прерывания программа тотчас в него вернётся по флагу (что у вас видимо и происходит, раз с такой частотой строчит). В таймере это некое действие -прочесть регистр статуса. Вы похоже сделали для ацп по-аналогии, что в общем то логично. Но должно ли это работать для АЦП -не факт. Возможно нужно прочесть данные - либо ADC_CDR либо ADC_LCDR. Думаю разберётесь самостоятельно :)
Программа висела в прерывании, ситуация поменялась с добавлением строки чтения регистра данных ADC_CDR . В даташите сказано, что в режиме Waveform TIOA всегда сконфигурирован как выход, и TIOB является выходом, если он не выбран как внешний триггер. Настроил TCCLKS=TIMER_CLOCK1, WAVE=1, счёт до RC WAVSEL =10, ACPC=11(toggle) соответственно TC_CMR0= СС000. Меняя значение TC0_RC0 получил максимальную частоту 3,7кГц при RC0=100 , меньше сколько угодно, но больше почему то не выжимает, странно если учесть что он тактирует от TIMER_CLOCK1. Не могу понять с чем это связано.
void setup() { pinMode (13,OUTPUT); pmc_enable_periph_clk(ID_ADC); ADC->ADC_CR |=1; ADC->ADC_MR= 0x1038ff03; ADC->ADC_CHER=0x80; REG_ADC_IER=1<<7; NVIC_EnableIRQ(ADC_IRQn); // Serial.begin(250000); REG_PMC_PCER0|=1<<27; REG_TC0_CMR0|=0xCC000; REG_TC0_RC0= 100; REG_TC0_CCR0=5; } void loop() { } void ADC_Handler(void){ int Uism_U=ADC->ADC_CDR[7]; REG_PIOB_ODSR^=1<<27; }cerceli, таймер перестаёт оказывать влияние если АЦП не успевает. А АЦП вы как я понимаю максимально замедлили -стоят все биты PRESCAL в регистре ADC_MR
Все работает) Спасибо. Не моглибы Вы посоветовать литературу начинающему для понимания всех железных процессов?
cerceli, по DUE не встречал литературы, но можно что-то полезное найти по STM32, а они схожи. Я сам просто читаю даташит, и если что непонятно -гуглю :)
cerceli, предыдущий оратор просто взял готовый пример с ардуино.сс Лично меня тошнит от этих CMSIS'овских функций, предпочитаю прямую запись в порты. Вот вам прерывания 10 тыщ раз в секунду. В дефайне "freq" можно задать другую частоту в разумных пределах :)
#define freq 10000 // частота прерываний, Герц void setup() { pinMode (13,OUTPUT); REG_PMC_PCER0|=1<<27; //включить тактирование "TC0" REG_TC0_CMR0=1<<14;//CTC mode REG_TC0_RC0= 21E6/freq; // рассчёт частоты REG_TC0_CCR0=5; //Обнулить счётчик и запустить. REG_TC0_IER0=1<<4; // прерывание NVIC_EnableIRQ(TC0_IRQn); } void loop() {} void TC0_Handler(void){ if (REG_TC0_SR0&(1<<4)==0) {return;} REG_PIOB_ODSR^=1<<27; //дрыгать 13 ногой (как пример) }Slavapavlovsk, в данном скетче я не использовал ардуиновские функции pinMode/digitalWrite, а писал в порты напрямую. Если вы посмотрите на пинмаппинг Due, то увидите что 13 пин -это порт B27
А она свазана с портом?
Slavapavlovsk, ну из комментария же понятно, то это запуск таймера0
Так это просто совпадение?
Значить чтобы подрынкать 12 ногой мне достаточно сменить
на
REG_PIOD_ODSR^=1<<8
Такой вопрос можно ли в DUE сменить частоту шим по принцыпу изменения пределителя таймера ?
Такой вопрос можно ли в DUE сменить частоту шим по принцыпу изменения пределителя таймера ?
да
Ссылку дадите где почитать об этом? А то толком ничего не нашел.
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Corte...
Благодарю.! Еще вопрос читал что у нее три трех канальных таймера это как ? Это ж не 9 независимых канала ?
Это смотря что понимать под словом "независимых". Вы лучше скажите, что в итоге хотите получить.
Решил сделать частотник . Все форумы конечно ведут к stm32 но там Keil . И чё то мне думается что DUE вполне справится с этой задачей. По сути нужно 6 отдельных каналов шим. Или все же на stm32 смотреть ?
А какие проблемы? 6 каналов ШИМ и на обычной ардуине получить можно. А stm32 и из ардуиновской среды можно программировать.
Удобнее не "6 отдельных каналов" , а 3 пары комплиментарных. Такие есть и на СТМ8 и на СТМ32, и на Атмеге2560... Да много на каких МК есть. Наверно и на Дуе..
Вообще все упирается как я понял DEDTIME . А у stm32 он есть. Но можно в принципе его и аппаратно реализовать. Что скажите?
Или программно флаг какой нибуть подумать ждать опускать???
В DUE он УЖЕ аппаратно реализован :) В PWM-контроллере всё есть, -8 пар выходов, дид-таймы, входы защиты, и прочие полезные фичи. Но я бы вам не советовал делать на Due, лучше найти готовый проект на стм32 и повторить его, т.к. разбираться с полного ноля во внутренней кухне таймеров Due очень трудно, а для большинства так и просто невозможно ввиду ряда причин -отсутствия нормальных обучающих материалов, примеров, итд.
Что в место KEILA посоветуете ?
Ну, если мила среда Ардуино то - https://habr.com/post/395577/
А так там всего много, выбирай-не хочу. https://www.st.com/en/development-tools/stm32-ides.html
Ардуино конечно ближе но как я понял например stm32 дискавери на ней не прошить ?
Может лучше
Visual Studio ?
Ардуино конечно ближе но как я понял например stm32 дискавери на ней не прошить ?
В-первых, "СТМ32 Дискавери" - это не одна плата, а огромное семейство. И там есть и те. что можно шить в Ардуино-ИДЕ.
Во-вторых, нафига вам дорогая дискавери, когда с этим справится и банальная "BluePill" за 100 с небольшим рублей?
И в-третьих - помня старый опыт :) - с вашими-то способностями - на чем бы вы не делали. все равно это займет у вас года три и нифига не выйдет :) Нужен частотник - купите лучще готовый :)
Я бы порекомендовал MBED. По идеологии похожа на Ардуино, но более продвинута. Поддердживается куча ARM-CortexM процессоров включая почти весь зоопарк от STM. Из минусов (для Ардуинщиков) поддерживаются только ARMы и библиотеки от Ардуино не подходят никак. Но есть достаточно большой набор MBed-овских библиотек.
Для начала можно почитать здесь
https://habr.com/ru/post/420435/
https://habr.com/ru/company/efo/blog/308440/
Благодарю! Попробую .
пока остановился на arduino находил видео на буржуйском сайте где можно настраивать частоту шим, дискретность но он использует другой синтаксис. Где об этом можно почитать ?