Проблема с таймерсчетчиком T3
- Войдите на сайт для отправки комментариев
Ср, 28/01/2015 - 11:47
Добрый день.
Задача
Требуется генератор с частотой 40кГц, и счетчик импульсов между двумя 40кГц стробами
Платформа Arduino Mega 2560
//************************************************************************
// начальные установки
//************************************************************************
//**********************Переменные***********************************
int ImpCount = 0;// Счетчик внешних событий
int oldCount = 0;// Количество предыдущих импульсов
// Pins
int OutPWM = 5;// pin выход
boolean ff1 = false;
void setup()
{
cli(); // Запрещаем все прерывания на время инициализации.
//********************Pins**********************************************
pinMode(OutPWM, OUTPUT);// выход
//********************Serial********************************************
Serial.begin(9600);
//********************InInterrupt***************************************
attachInterrupt(0, incounter, RISING);// Прерывание на порту 2
// RISING по нарастающему фронту
//********************TimerCounter***********************************
OCR3A=192;
OCR3B=192;
ICR3=200;
TCCR3A=0b01010000;
TCCR3B=0b00010001;
sei();// разрешаем прерывания
// Приветствие
Serial.println("UZ v 1.0");
}
//************************************************************************
// Обработка прерываний
//************************************************************************
//**********************Прерывание по внешнему сигналу***********
void incounter()
{
cli();
if ((analogRead(OutPWM)==1)and(ff1==false)){ff1=true;}
if ((analogRead(OutPWM)==0)and(ff1==true)){ImpCount++;}//переключение "┐" увеличиваем счетчик
if ((analogRead(OutPWM)==1)and(ff1==true))//переключение "┌"
{
if (oldCount!=ImpCount){Serial.println(ImpCount);}
ImpCount=0;
ff1=false;
}
sei();
}
void loop()
{
;
}
Собственно нет генерации 40кГц на выходе 5, хотя таймер работает (щелкает).
Не понимаю в чем ошибка, выходы сконфигурировал как надо. Помогите понять, где ошибка.
38, 39, 40 - вы считываете пин который определён как выход
void loop() { analogWrite( OutPWM , 128 ); }
volatile
boolean ff1 =false;Стандартная
analogRead() выполняется 110 мкс. В вашем обработчике прерываний она вызывается трижды. Т.е. частота прерываний при которой такой обработчик отработает не может быть больше 3кГц.А если учесть еще иSerial.println() и все остальное то реально это заработает на 1кГц не более.OCR3A - OCR3AH и OCR3AL , ICR3 - H и L , TIMSK3 - не настроен , а в нём разрешения прерываний
Спасибо за советы господа, но с фиксацией сигнала по прерыванию у меня все в порядке. Предположим обработчика вообще нет, только генератор
//************************************************************************ // начальные установки //************************************************************************ //**********************Переменные*********************************** // Pins int OutPWM = 5;// pin выход void setup() { cli(); // Запрещаем все прерывания на время инициализации. //********************Pins********************************************** pinMode(OutPWM, OUTPUT);// выход //********************Serial******************************************** Serial.begin(9600); //********************TimerCounter*********************************** OCR3A=192; OCR3B=192; ICR3=200; TCCR3A=0b01010000; TCCR3B=0b00010001; sei();// разрешаем прерывания // Приветствие Serial.println("UZ v 1.0"); } //************************************************************************ // Обработка прерываний //************************************************************************ void loop() { ; }у меня нет генерации 40кГц на выходе pin 5, в этом и вопрос.
TIMSK3 - не настроен
режим 0 не тот - WGM33 , WGM32 , WGM31 , WGM30 - нужен режим CTC , 4 или 12
Хорошо ребята объясню логику.
Расчет
Требуемая частота 40000 Гц
Частота МК 16000000 Гц
Предделитель таймера clk/1
Считаем какое число импульсов с частотой 16МГц уместятся в один импульс 40кГц.
16000000/40000=400.
Соответственно 400 импульсов 16Мгц = одному импульсу 40кГц = 25 микросекунд
Получаем
Потолок 400/2=200; ICR3=200.
Переключение 200-( (400/25)/2)=192 ; OCR1A=192.
режим работы, выбран 8. (PWM, Phase and Frequncy Corre).
Во избежание вопросов .
У меня не задан регистр TIMSK , да это так, не задан, я не использую прерывания таймера, они мне не нужны.
Вопрос в следующем .
Таймер работает TCNT3 щелкает в этом я убедился, но нет генерации на выводе pin 5
//************************************************************************ // начальные установки //************************************************************************ //**********************Переменные*********************************** // Pins int OutPWM = 5;// pin выход void setup() { cli(); // Запрещаем все прерывания на время инициализации. //********************Pins********************************************** pinMode(OutPWM, OUTPUT);// выход //********************Serial******************************************** Serial.begin(9600); //******************** TimerCounter_3 *********************************** TCCR3A = ( 1 << COM3A1 ) | ( 0 << COM3A0 ) | // Toggle OC3A on compare match ( 0 << COM3B1 ) | ( 0 << COM3B0 ) | ( 0 << COM3C1 ) | ( 0 << COM3C0 ) | ( 0 << WGM31 ) | ( 0 << WGM30 ); // WGM3=0100 - режим 4 по OCR3A TCCR3B = ( 0 << ICNC3 ) | ( 0 << ICES3 ) | ( 0 << WGM33 ) | ( 1 << WGM32 ) | // WGM3=0100 - режим 4 по OCR3A ( 0 << CS32 ) | ( 0 << CS31 ) | ( 1 << CS30 ); // предделитель = 1 OCR3AH = 0x00; // 40 kHz - 12500 nS / 62,5 nS = 200 = 0x00C8 OCR3AL = 0xC8; TIMSK3 = ( 0 << ICIE3 ) | ( 0 << OCIE3C ) | ( 0 << OCIE3B ) | ( 1 << OCIE3A ) | ( 0 << TOIE3 ); // OCR3A=192; // это для режима 4 // OCR3B=192; // зачем два канала ? // ICR3=200; // это для режима 12 // TCCR3A=0b01010000; // TCCR3B=0b00010001; sei();// разрешаем прерывания // Приветствие Serial.println("UZ v 1.0"); } //************************************************************************ // Обработка прерываний //************************************************************************ void loop() { ; }вооо, блин поздно увидел - что есть новое :)
"... У меня не задан регистр TIMSK , да это так, не задан, я не использую прерывания таймера, они мне не нужны. ..."
они нужны МК, чтобы менять состояние выходного пина
Ошибаетесь, не нужны 2 симуляции в AVR Studio и Proteus, это подтверждают.
40 kHz - период 25 микросек, а длительность импульсов HIGH - сколько нужно ?
на рисунке вы изобразили режим ШИМ с коррекцией фазы - в этом режиме управлять частотой одно средство - предделитель.
в режиме CTC частоту можно установить любую
время высокого уровня 1 микросекунда
"... У меня не задан регистр TIMSK , да это так, не задан, я не использую прерывания таймера, они мне не нужны. ..."
они нужны МК, чтобы менять состояние выходного пина
да, тут моя не права.... извините - ДЕРЗИЛ :)
Для скептиков код на ассемблере для ATMega2560
#16 - вы миня напугали :( , я так не умею....
в режиме 8 используется только ICR3A , OCR3A - там ни при чём...
и как решили с частотой ? в режиме 8 можно получить 62,5 или 31,25 kHz - если предделитель позволит, неохота лезть в ДШ, но точно 40 - не получится :(
Уважаемый SU-27-16, в режиме 8 у меня все прекрасно работает, а в дотащит слазить не помешало бы для освежения.
Заостряю внимание, что таймер у меня работает и так как надо, но вот вывод, почему то не отрабатывает.
предполагаю, что Arduino инициализирует их по своему и моя инициализация конфликтует.
Сталкивался с этим, при собственной обработки прерываний по serial порту.
а так ?
volatile boolean flipFlop = 0; //******************** TimerCounter_3 *********************************** TCCR3A = ( 1 << COM3A1 ) | ( 0 << COM3A0 ) | ( 0 << COM3B1 ) | ( 0 << COM3B0 ) | ( 0 << COM3C1 ) | ( 0 << COM3C0 ) | ( 0 << WGM31 ) | ( 0 << WGM30 ); TCCR3B = ( 0 << ICNC3 ) | ( 0 << ICES3 ) | ( 0 << WGM33 ) | ( 1 << WGM32 ) | ( 0 << CS32 ) | ( 0 << CS31 ) | ( 1 << CS30 ); OCR3AH = 0x00; OCR3AL = 0x10; // на 1 микросекунду TIMSK3 = ( 0 << ICIE3 ) | ( 0 << OCIE3C ) | ( 0 << OCIE3B ) | ( 1 << OCIE3A ) | ( 0 << TOIE3 ); } //************************************************************************ ISR( TIMER3_COMPA_vect ) { if ( ! flipFlop ) { OCR3AH = 0x01; // на 24 микросекунды OCR3AL = 0x80; // на 24 микросекунды } else { OCR3AH = 0x00; // на 1 микросекунду OCR3AL = 0x10; // на 1 микросекунду } } //************************************************************************Залил ваш пример с небольшими поправками
volatile boolean flipFlop = 0; int OutPWM = 5;// pin выход ШИМ void setup() { pinMode(OutPWM, OUTPUT);// выход cli(); // Запрещаем все прерывания на время инициализации. //******************** TimerCounter_3 *********************************** TCCR3A = ( 1 << COM3A1 ) | ( 0 << COM3A0 ) | ( 0 << COM3B1 ) | ( 0 << COM3B0 ) | ( 0 << COM3C1 ) | ( 0 << COM3C0 ) | ( 0 << WGM31 ) | ( 0 << WGM30 ); TCCR3B = ( 0 << ICNC3 ) | ( 0 << ICES3 ) | ( 0 << WGM33 ) | ( 1 << WGM32 ) | ( 0 << CS32 ) | ( 0 << CS31 ) | ( 1 << CS30 ); OCR3AH = 0x00; OCR3AL = 0x10; // на 1 микросекунду TIMSK3 = ( 0 << ICIE3 ) | ( 0 << OCIE3C ) | ( 0 << OCIE3B ) | ( 1 << OCIE3A ) | ( 0 << TOIE3 ); sei();// разрешаем прерывания } //************************************************************************ ISR( TIMER3_COMPA_vect ) { if ( ! flipFlop ) { OCR3AH = 0x01; // на 24 микросекунды OCR3AL = 0x80; // на 24 микросекунды } else { OCR3AH = 0x00; // на 1 микросекунду OCR3AL = 0x10; // на 1 микросекунду } } //************************************************************************ void loop() { ; }Генерации на 5-ом пину нет. Я уже думал у меня порт не рабочий, просто подергал 5 выводом, работает. Вопрос остался открытым :(
:( а подёргать каналы 3B, 3C и счётчики 1, 4, 5 ?
Подергаю, но уже завтра
вернее TCCR3A=0b11000000; - без канала B
//******************** TimerCounter_3 *********************************** TCCR3A = ( 1 << COM3A1 ) | ( 1 << COM3A0 ) | ( 0 << COM3B1 ) | ( 0 << COM3B0 ) | ( 0 << COM3C1 ) | ( 0 << COM3C0 ) | ( 0 << WGM31 ) | ( 0 << WGM30 ); TCCR3B = ( 0 << ICNC3 ) | ( 0 << ICES3 ) | ( 1 << WGM33 ) | ( 0 << WGM32 ) | ( 0 << CS32 ) | ( 0 << CS31 ) | ( 1 << CS30 ); OCR3AH = 0x00; OCR3AL = 0xC0; ICR3H = 0x00; ICR3L = 0xC8; // TIMSK3 = ( 0 << ICIE3 ) | // ( 0 << OCIE3C ) | ( 0 << OCIE3B ) | ( 0 << OCIE3A ) | // ( 0 << TOIE3 ); } //************************************************************************Нужен конал B
Так как я использую 2 вывода OC3A и OC3B, в примере упростил (без OC3B)
А данный режим не срабатывает по совпадению с OCR3B,
Щелкает только OC3A, а нужно, чтобы синхронно оба OC3A и OC3B.
Опять говорю, что с выбором режима все в порядке, он работает и дергает ножками, но только в симуляции
у миня нет Меги :( , т.е. это на железе вы не пробовали ?
//******************** TimerCounter_3 *********************************** TCCR3A = ( 1 << COM3A1 ) | ( 1 << COM3A0 ) | ( 1 << COM3B1 ) | ( 1 << COM3B0 ) | ( 0 << COM3C1 ) | ( 0 << COM3C0 ) | ( 0 << WGM31 ) | ( 0 << WGM30 ); TCCR3B = ( 0 << ICNC3 ) | ( 0 << ICES3 ) | ( 1 << WGM33 ) | ( 0 << WGM32 ) | ( 0 << CS32 ) | ( 0 << CS31 ) | ( 1 << CS30 ); OCR3AH = 0x00; OCR3AL = 0xC0; OCR3BH = 0x00; OCR3BL = 0xC0; ICR3H = 0x00; ICR3L = 0xC8; } //************************************************************************извините за занудство, моя учится пока :(
а зачем два пина на выход с одинаковой функциональностью ?
Мне нужны 2 синхронных генератора. Раздваивать сигнал нет смысла, это лишние компоненты на схеме. А тут я получу их аппаратно
Я так и знал - http://cxem.net/arduino/arduino49.php
Какие стандартные библиотеки могут мешать генератору и как их отключить?????
Ну что есть Arduin-щики которые помогут мне реализовать 8 режим таймер счетчика 3?