Проблема с таймерсчетчиком T3

Anatolich
Offline
Зарегистрирован: 27.01.2015

Добрый день.

Задача

Требуется генератор с  частотой 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, хотя таймер работает (щелкает).

Не понимаю в чем ошибка, выходы сконфигурировал как надо. Помогите понять, где ошибка.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

38, 39, 40 - вы считываете пин который определён как выход

void loop() { analogWrite( OutPWM , 128 ); }

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

volatile boolean ff1 = false;

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

Стандартная analogRead() выполняется 110 мкс. В вашем обработчике прерываний она вызывается трижды. Т.е. частота прерываний при которой такой обработчик отработает не может быть больше 3кГц. А если учесть еще и Serial.println() и все остальное то реально это заработает на 1кГц не более.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

OCR3A - OCR3AH и OCR3AL , ICR3 - H и L , TIMSK3 - не настроен ,  а в нём разрешения прерываний

Anatolich
Offline
Зарегистрирован: 27.01.2015

Спасибо за советы господа, но с фиксацией сигнала по прерыванию у меня все в порядке. Предположим обработчика вообще нет, только генератор

//************************************************************************
//                      начальные установки
//************************************************************************
//**********************Переменные***********************************
// 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, в этом и вопрос.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

TIMSK3 - не настроен

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

режим 0 не тот - WGM33 , WGM32 , WGM31 , WGM30 - нужен режим CTC , 4 или 12

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
In Clear Timer on Compare or CTC mode (WGMn3:0 = 4 or 12), the OCRnA or ICRn Register
are used to manipulate the counter resolution. In CTC mode the counter is cleared to zero when
the counter value (TCNTn) matches either the OCRnA (WGMn3:0 = 4) or the ICRn (WGMn3:0 =
12). The OCRnA or ICRn define the top value for the counter, hence also its resolution. This
mode allows greater control of the compare match output frequency. It also simplifies the operation
of counting external events.
Anatolich
Offline
Зарегистрирован: 27.01.2015

Хорошо ребята объясню логику. 

Расчет

Требуемая частота 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

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
//************************************************************************
//                      начальные установки
//************************************************************************
//**********************Переменные***********************************
// 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()
{
  ;             
}

вооо, блин поздно увидел - что есть новое :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"... У меня не задан регистр TIMSK , да это так, не задан, я не использую прерывания таймера, они мне не нужны. ..."

они нужны МК, чтобы менять состояние выходного пина

Anatolich
Offline
Зарегистрирован: 27.01.2015

Ошибаетесь, не нужны 2 симуляции в AVR Studio и Proteus, это подтверждают.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

40 kHz - период 25 микросек, а длительность импульсов HIGH - сколько нужно ?

на рисунке вы изобразили режим ШИМ с коррекцией фазы - в этом режиме управлять частотой одно средство - предделитель.

в режиме CTC частоту можно установить любую

Anatolich
Offline
Зарегистрирован: 27.01.2015

время высокого уровня 1 микросекунда

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

SU-27-16 пишет:

"... У меня не задан регистр TIMSK , да это так, не задан, я не использую прерывания таймера, они мне не нужны. ..."

они нужны МК, чтобы менять состояние выходного пина

да, тут моя не права.... извините - ДЕРЗИЛ :)

Anatolich
Offline
Зарегистрирован: 27.01.2015

Для скептиков код на ассемблере для ATMega2560

.include "m2560def.inc";// ATMega2560
.def tmp=r16;
// Установка текущего адреса в 0
.org 0x00                  
	rjmp start;
start:
	// инициализация
	SBI DDRE,3; вывод таймера T3 на выход
	SBI DDRE,4; вывод таймера T3 на выход
//****Записываем 192 в регистр сравнения**************
	LDI tmp,0x00;
	STS OCR3AH,tmp;
	LDI tmp,0xC0;
	STS OCR3AL,tmp;
	LDI tmp,0x00;
	STS OCR3BH,tmp;
	LDI tmp,0xC0;
	STS OCR3BL,tmp;
//****Записываем 200 в Ригистр захвата, задаем TOP***
	LDI tmp,0x00;
	STS ICR3H,tmp;
	LDI tmp,0xC8;
	STS ICR3L,tmp;
// настраиваем режим таймера и предделитель
	LDI tmp,0b01010000;
	STS TCCR3A,tmp;
	LDI tmp,0b00010001;
	STS TCCR3b,tmp;
loop:
	NOP;
	RJMP loop;

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

#16 - вы миня напугали :( , я так не умею....

в режиме 8 используется только ICR3A , OCR3A - там ни при чём...

и как решили с частотой ? в режиме 8 можно получить 62,5 или 31,25 kHz - если предделитель позволит, неохота лезть в ДШ, но точно 40 - не получится :(

Anatolich
Offline
Зарегистрирован: 27.01.2015

Уважаемый SU-27-16, в режиме 8 у меня все прекрасно работает, а в дотащит слазить не помешало бы для освежения.

Заостряю внимание, что таймер у меня работает и так как надо, но вот вывод, почему то не отрабатывает.

 предполагаю, что Arduino инициализирует их по своему и моя инициализация конфликтует.

Сталкивался с этим, при собственной обработки прерываний по serial порту.

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

а так ?



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 микросекунду
    }
}
//************************************************************************

 

Anatolich
Offline
Зарегистрирован: 27.01.2015

Залил ваш пример с небольшими поправками 

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 выводом, работает. Вопрос остался открытым :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

:( а подёргать каналы 3B, 3C и счётчики 1, 4, 5 ?

Anatolich
Offline
Зарегистрирован: 27.01.2015

Подергаю, но уже завтра

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
Phase and Frequency Correct PWM Mode
The phase and frequency correct Pulse Width Modulation, or phase and frequency correct PWM
mode (WGMn3:0 = 8 or 9)..........................(COMnx1:0 = 2) или (COMnx1:0 = 3)
а у вас (COMnx1:0 = 1)
 
Set OCnA/OCnB/OCnC on compare match when up-counting
Clear OCnA/OCnB/OCnC on compare match when downcounting - значит надо (COMnx1:0 = 3) ?
TCCR3A=0b11010000;
нет ?
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 вернее TCCR3A=0b11000000; - без канала B

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
//******************** 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 );
}
//************************************************************************

 

Anatolich
Offline
Зарегистрирован: 27.01.2015

Нужен конал B

Так как я использую 2 вывода OC3A и OC3B, в примере упростил (без OC3B)

А данный режим не срабатывает по совпадению с OCR3B,

Щелкает только OC3A, а нужно, чтобы синхронно оба  OC3A и OC3B.

Опять говорю, что с выбором режима все в порядке, он работает и дергает ножками, но только в симуляции

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

у миня нет Меги :( , т.е. это на железе вы не пробовали ?

//******************** 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;
}
//************************************************************************

извините за занудство, моя учится пока :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

а зачем два пина на выход с одинаковой функциональностью ?

Anatolich
Offline
Зарегистрирован: 27.01.2015

Мне нужны 2 синхронных генератора. Раздваивать сигнал нет смысла, это лишние компоненты на схеме. А тут я получу их аппаратно 

Anatolich
Offline
Зарегистрирован: 27.01.2015

Я так и знал -  http://cxem.net/arduino/arduino49.php

Какие стандартные библиотеки могут мешать генератору и как их отключить?????

Anatolich
Offline
Зарегистрирован: 27.01.2015

Ну что есть Arduin-щики которые помогут мне реализовать 8 режим таймер счетчика 3?