ещё раз спасибо. Аппетит приходит во время еды). Когда понял что можно творить с помощью таймеров и счётчиков совсем покой потерял. Этож какие возможности !!! А он только вскользь прошёлся по режимам счётчиков. Попробую курс до конца досмотреть мож где ещё будет на эту тему
Попробуйте почитать книжки - их полно, в т.ч. и в Интернете. Ох уж это высшее образование по фильмам...
Есть отличный ресурс gaw.ru. Там очень много по теме. Ну а лучшее - это даташит и апноуты на сайте микрочипа.
Я наверное не острый. Но самостоятельно не получается работать с таймерами. Как работает понял. Но как самому все записать темный лес. И нигде нет подробного материала. Видно это удел избранных владеть этой информацией), кстати вопрос почему в даташите на схеме у ТС1 , обозначены два порта с которых он может принимать сигналы. T1, ICP1, но в дальнейшем описании описывается работа только с Т1(может ли он одновременно считать импульсы с 2х портов)??? И можно ли использовать этот таймер как таймер, если он работает в режиме счетчика. Понимаю что вопросы для профи возможно дикие. Но не нашел самостоятельно ответов. Как не крути нужен живой сенсей рядом, которого можно подастовать вопросами)
МК какой? Таймер - это блок. В этом блоке счетчик. У этого счетчика есть предделитель. Предделитель тактируется от осциллятора мк. Каждый таймера может тактироваться от любого разряда предделителя, но сброс предделителя общий. Про ICP1 здесь хорошо описано http://microsin.net/programming/AVR/atmega-ct1-pulse-counting.html Что не понятно - спрашивай.
Спасибо! Atmega328. Повременю пока с вопросами, иначе задолбаю раньше чем пойму) попробую пописать в симуляторе, чтоб были наработки с которыми можно обращаться. Это как блинк на 13 пине у новичка, только на другом уровне. На народ стрим есть разжовывалка про стм32, тоже интересная весч. Хоть разорвись, или таймеры счётчики осваивать или стм изучать
https://arduinomaster.ru/program/simulyator-arduino-tinkercad-circuits/ прямую ссылку не помню так как с телефона пишу. Но там можно разобраться. Кто-то говорил что этот симулятор поддерживает прямое обращение к портам. Вот и попробую заодно. Сейчас правда планы на атмел студио перейти. На первый взгляд в чем то удобнее ардуино иде.
Пока искал ссылку наткнулся на Virtual Breadboard. Надо будет поюзать что за зверь www.virtualbreadboard.com/DocView.html?doc=Downloads/Downloads
продолжаю терзать даташит))). появляются смутные подозрения что на таймерах можно соорудить шим, который можно запустить абсолютно параллельно, задачам в основном цикле. интересно блин до жути. как Америку отрываю! Собственно вот и вопросы). если возможно только подскажите на правильном ли я пути или еще недогоняю. и какой материал нужно курить чтобы не разбрасываться временем. в общем скажем существуе дозиметр с 2 секциями датчиков. Сигналы с них принимать обычными внешними прерываниями пины 2,3 (если не забыл, давно уже не писал программки, а читать заново лениво), как имеющими самый высокий приоритет. затем на опрос компаратора раз 100 в секунду. выставить напряжение, как напряжение питания, если правильно понял даташит ADMUX |= (0 << REFS1)|(1 << REFS0) . само напряжение брать с делителя датчика. если напряжение меньше , запустить накачку датчика Шим сигналом. при срабатывании больше чем настроено в компараторе то отключить генерацию Шим (кстати или я неправильно подсчитал но больше 32000 гц не получить с шима?). а в основном цикле заниматься только рассчетами и выводом на экранчик. это возможно реализовать? или я неправильно понимаю суть , особенно работу АЦП?
Я тебе сейчас ещё одну хитрую штуку покажу. Код (C++): ADC_Init(); // Инициализация АЦП T0_Mode_CTC; // Режим таймера - сброс при переполнении T0_Set_OCR0A; // Записываем значение в регистр сравнения TIMSK0 = Bit(OCIE0A); // Разрешаем прерывание от регистра сравнения T0_Start_64; // Запускаем таймер ADC_Start_Conversion(ADC3); // контрольный выстрел АЦП (в функции определен вход мультиплексора) Здесь настраиваем работу АЦП от таймера T0. Всё, что нам остаётся сделать, в прерывании считать значение АЦП Код (C++): ISR(ADC_vect) { Buf[in++] = ADC_Get_Data(); } Функция инициализации АЦП Код (C++): void ADC_Init(void) { DIDR0 = (1<<ADC1D) | (1<<ADC2D) | (1<<ADC3D); ADMUX = (1<<REFS1) | (0<<REFS0); // Внутренний ИОН 1.1в ADCSRB = (1<<ADLAR) | (1<<ADTS1) | (1<<ADTS0); // Работаем только со старшими 8-ю битами, запуск от таймера T0 ADCSRA = (1<<ADEN) | (1<<ADIE) | (1<<ADATE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Прескалер = 8 } Функция взятия значения из АЦП Код (C++): uint8_t ADC_Get_Data (void) { return ADCH; } Ручной запуск АЦП Код (C++): void ADC_Start_Conversion (uint8_t Analog_input) { ADMUX |= Analog_input; // выбираем вход ADCSRA |= Bit(ADSC); // запускаем преобразование } Дефайны Код (C++): //... Таймер 0 #define T0_Start_64 TCCR0B = Prescaler_64; ClearPrescaler // Пуск таймера с очисткой делителя #define T0_Start_256 TCCR0B = Prescaler_256; ClearPrescaler #define T0_Start_1024 TCCR0B = Prescaler_1024; ClearPrescaler #define T0_Stop TCCR0B &= (~(Bit(CS00) | Bit(CS01) | Bit(CS02))) // Останов таймера (делитель = 0) #define T0_Clear TCNT0 = 0 #define T0_Mode_Normal TCCR0A = 0x00 #define T0_Mode_CTC TCCR0A = Bit(WGM01) #define T0_Set_OCR0A OCR0A = 7//(F_CPU/(64 * Freq_dis) - 1) Т.Е. нам надо что-то оцифровывать в фоне с высокой стабильностью. Мы не запариваемся - таймер (в данном случае T0) всё делает вместо нас. Нам остаётся только уйти на прерывание и забрать значения из кольцевого буфера тогда, когда сможем. На стабильность работы АЦП это никак не влияет. Код для 24/44/84 аттини и легко переписывается под любой другой МК (инициализация АЦП и прерывание от него будут слегка отличатся). Все пины помеченные как PCINT способны вызывать прерывания. Работа с ними требует чуть побольше кода. Все прерывания в АВР имеют одинаковый приоритет (кроме сброса). Если возникает прерывание в момент, когда МК находится в обработчике текущего прерывания, оно становится в очередь. Если ещё одно - также в очередь. Если за один такт придет более одного прерывания - первым выполнится прерывание с меньшим адресом. На 16 МГц? Как считал?
спасибо за ответ! таки да по моему можно и 62500 гц выжать TCCR0B=TCCR0B&0b11111000|0x01. пойду курить как скважность регулировать. УРААА!!!! работает!!!! радости как первый раз светодиодом помигал.)))) Код (C++): void setup() { TCCR0B=TCCR0B&0b11111000|0x01; analogWrite(5, 100); } void loop() { } теперь думаю как его включать отключать когда накачка ненужна.
Раз заговорили о таймерах, то вставлю свои "пять копеек". Максимальная частота, которую можно получить аппаратно (т.е. без всяких digitalWrite() или PORTx = xxxxx), равна половине тактовой частоты процессора. Например для Ардуин на базе ATmega328P -- это 8 МГц. Но при этом с ШИМ'ом будут определённые трудности. Дело в том что начиная с определённой частоты (62,5 кГц), чем выше эта самая частота, тем меньше простора для регулирования скважности. При частоте 8 МГц скважность будет 50% и её ни как не поменять. При частоте 4 МГц скважность может быть: 25%, 50% или 75%. И так далее. Всё из-за того, что уменьшается диапазон счётчика таймера. Например для нулевого таймера штатно диапазон счёта от 0 до 255, но можно сделать от 0 до 1. Чем ниже диапазон, тем выше частота, но тем меньше возможностей влиять на ширину импульса. Ну и последнее ШИМ с высокой частотой доступен только на пинах 3,5,10, при этом на парных пинах (11,6,9) аппаратный ШИМ уже не получить (т.к. регистр OCRxA занят определением диапазона счёта).
Как-то эти две фразы не вяжутся друг с другом. Если приоритет одинаковый, то первым должно обработаться прерывание, возникшее раньше. А, если всё-таки, первым обработается прерывание с меньшим адресом, то это и называется прерыванием с более высоким приоритетом. Другое дело, что в AVR при обработке любого прерывания производится глобальный запрет обработки остальных прерываний. Поэтому новые прерывания не могут быть обработаны пока этот запрет не будет снят (а он может быть снят принудительно в обработчике). Такого же поведения можно добиться и в других видах процессоров, если при обработке прерываний глобально запрещать остальные. Но при этом всё-таки соглашусь, что приоритетность прерываний на аппаратном уровне реализована минимально упрощённо.
Все Ваши задумки можно реализовать на прерываниях. Точнее на одном прерывании от ADC. Настраиваете ADC в режим постоянного семплирования, а в обработчике ADC_vect реализовываете функционал проверки уровня и при необходимости запускаете или останавливаете аппаратный ШИМ. При этом в основной программе можете делать другую работу. Но ранее сообщал, что время отклика такой системы будет выше, чем у специализированных микрух. Штатно ADC может работать на частоте 200 кГц (хотя можно и выше с понижением качества). На одно преобразование ему нужно 13,5 тактов, т.е. частота семплирования будет ~14кГц. Или другими словами замер будет делаться раз в 70 мксек. До какого уровня успеет зарядиться конденсатор за 70 мксек? Можно использовать не ADC, а аналоговый компаратор. У него время отклика будет меньше (честно говоря с компаратором ещё дела не имел поэтому точных цифр привести не могу). Но всё равно с учётом вызова обработчика прерывания и выполнения кода задержка реакции может быть в районе 2 мксек. Так что напряжение на выходе будет не очень стабильным и временами превышать максимальное.