Перейти к содержанию
    

Постоянные изменения OCR0.

Есть потребность непрерывно перезаписывать в Меге 16 OCRO. Можно ли это делать? Дело в том, что на практике запись идёт с ошибками.

 

// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{  
  if ((!PINB.3) && (!flag_s_eep))
  {
flag_s=1;	 // Разрешение записи
PORTD.5=0;	// Индикация записи - включить СД
  } 


  if(!flag_start)
  {
flag_start=1;
TCNT1=0;
TCNT0=0;
OCR0=1;
t_zub=0;
return;
  }

 if(!flag_zub1)	// Поиск 1-го зуба
 {
  t_zub0=t_zub;
  t_zub=TCNT1;
  TCNT1=0;
  if((t_zub > (t_zub0 + (t_zub0>>1))) && (t_zub0))
  {
flag_zub1=1;
t_zub4=0;
OCR0=5;
  }
  else TCNT0=0;
  return;
 }

  switch (OCR0)
 {
  case 1:
  t_zub1=TCNT1;
  t_zub0=t_zub;
  t_zub=t_zub1-t_zub29;

  if(t_zub < (t_zub0 + (t_zub0>>1))) 
  {
//PORTD.5=0; // Индикация потери синхронизации
  }
  //else PORTD.5=1;

  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=1;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=2;
  break;

  case 2:
  t_zub2=TCNT1;
  t_zub=t_zub2-t_zub1;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=2;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=3;
  break;

  case 3:
  t_zub3=TCNT1;
  t_zub=t_zub3-t_zub2;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=3;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=4;
  break;

  case 4:
  t_zub4=TCNT1;
  t_zub=t_zub4-t_zub3;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=4;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=5;
  break;

  case 5:
  t_zub5=TCNT1;
  TCNT1=0;
  t_zub=t_zub5-t_zub4;
  if((t_zub5)&&(t_zub4))	 // При t_zub4=0 нет данных
  {						  // о времени полуоборота
n=7500000/t_zub5;										   
if(n > 600) flag_pusk=1;  // Запуск двигателя произведён.
flag_pper=1;
  }
  if((i_zub < i_zub_max) && (flag_s) && (t_zub4))
  {
t_zub_i[i_zub++]=5;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=6;
  break;   

  case 6:
  t_zub6=TCNT1;
  t_zub=t_zub6;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=6;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=7;
  break;

  case 7:
  t_zub7=TCNT1;
  t_zub=t_zub7-t_zub6;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=7;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=8;
  break;

  case 8:
  t_zub8=TCNT1;
  t_zub=t_zub8-t_zub7;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=8;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=9;
  break;

  case 9:
  t_zub9=TCNT1;
  t_zub=t_zub9-t_zub8;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=9;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=10;
  break;

  case 10:
  t_zub10=TCNT1;
  t_zub=t_zub10-t_zub9;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=10;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=11;
  break;


  case 11:
  t_zub11=TCNT1;
  t_zub=t_zub11-t_zub10;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=11;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=12;
  break;

  case 12:
  t_zub12=TCNT1;
  t_zub=t_zub12-t_zub11;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=12;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=13;
  break;

  case 13:
  t_zub13=TCNT1;
  t_zub=t_zub13-t_zub12;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=13;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=14;
  break;

  case 14:
  t_zub14=TCNT1;
  t_zub=t_zub14-t_zub13;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=14;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=15;
  break;

  case 15:
  t_zub15=TCNT1;
  t_zub=t_zub15-t_zub14;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=15;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=16;
  break;

  case 16:
  t_zub16=TCNT1;
  t_zub=t_zub16-t_zub15;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=16;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=17;
  break; 

  case 17:
  t_zub17=TCNT1;
  t_zub=t_zub17-t_zub16;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=17;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=18;
  break;

  case 18:
  t_zub18=TCNT1;
  t_zub=t_zub18-t_zub17;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=18;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=19;
  break;

  case 19:
  t_zub19=TCNT1;
  t_zub=t_zub19-t_zub18;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=19;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=20;
  break;

  case 20:
  t_zub20=TCNT1;
  TCNT1=0;
  t_zub=t_zub20-t_zub19;
  if(t_zub20) n=7500000/t_zub20;
  if(n > 600) flag_pusk=1;	// Запуск двигателя произведён.
  flag_pper=1;   
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=20;
t_zub_i[i_zub++]=t_zub;		
  }
  OCR0=21;
  break;   

  case 21:
  t_zub21=TCNT1;
  t_zub=t_zub21;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=21;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=22;
  break;

  case 22:
  t_zub22=TCNT1;
  t_zub=t_zub22-t_zub21;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=22;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=23;
  break;

  case 23:
  t_zub23=TCNT1;
  t_zub=t_zub23-t_zub22;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=23;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=24;
  break;

  case 24:
  t_zub24=TCNT1;
  t_zub=t_zub24-t_zub23;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=24;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=25;
  break;

  case 25:
  t_zub25=TCNT1;
  t_zub=t_zub25-t_zub24;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=25;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=26;
  break;

  case 26:
  t_zub26=TCNT1;
  t_zub=t_zub26-t_zub25;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=26;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=27;
  break;

  case 27:
  t_zub27=TCNT1;
  t_zub=t_zub27-t_zub26;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=27;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=28;
  break;

  case 28:
  t_zub28=TCNT1;
  t_zub=t_zub28-t_zub27;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=28;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=29;
  break;

  case 29:
  t_zub29=TCNT1;
  t_zub=t_zub29-t_zub28;
  if((i_zub < i_zub_max) && (flag_s))
  {
t_zub_i[i_zub++]=29;
t_zub_i[i_zub++]=t_zub;	
  }
  OCR0=1;
  TCNT0=0;
  break;					   

 }	  //Скобка switch

}

 

Фрагмент массива t_zub_i : 001D 0A0A 0022 C44F 0003 01AD 0003 01A7 0004 01A0 0005 0359...

В этом массиве нечётные "слова" должны увеличиваться на единицу до 29 включительно, затем опять начинаться с единицы. Но в реальности этого гарантированно нет. Почему?

Изменено пользователем Александр К.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ничего, что у Вас изменение сабжа сильно джиттерные получаются?

И где i_zub = 0; - не видать что-то.

 

ЗЫ: говнокод в тэги codebox а не code :) - так он читабельнее.

И по временам подробнее плз - успевает ли оно ваще.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ничего, что у Вас изменение сабжа сильно джиттерные получаются?

Как побороть?

И где i_zub = 0; - не видать что-то.

Есть такое: char i_zub=0;

И по временам подробнее плз - успевает ли оно ваще.

Вполне успевает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как побороть?

 

Есть такое: char i_zub=0;

 

Вполне успевает.

 

1. Вынести обращения к OCR0 за switch:

char j; j = OCR0; if(++j > 29) j = 1; OCR0=j; switch(j)...

2. Тем более непонятно, какая часть прерывания ее должна перевзводить обратно, после фрагмента case 29: ....

3. Если прерывания не накладываются, значит см п.2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При записи в OCR регистр, значение обновляется после завершения периода. Не смотрел текст, так как очень большой. Но принципиально, всё должно работать. Обновлять надо по TOV.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2. Тем более непонятно, какая часть прерывания ее должна перевзводить обратно, после фрагмента case 29: ....

Эта:

case 29:
   ...
   OCR0=1;
   TCNT0=0;
   ...

На п.1. Какая разница? Если можно, поясните.

 

...Обновлять надо по TOV.

Это как?

И где завершается период - при начале следующего? Может, в этом проблема?

Изменено пользователем Александр К.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На п.1. Какая разница? Если можно, поясните.

switch() может последовательно перебирать все значения от 1 до 29 (а может и нет - зависит от компилера), тогда бОльшие числа будут писАться позднее.

А таймер тем временем тикает...

Но - если успевает, о чем мы говорим?

По поводу i_zub - ну не вижу я где он заново обнуляется :smile3046:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...По поводу i_zub - ну не вижу я где он заново обнуляется :smile3046:

i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется.

Там получается, что прерывания повторяются несколько раз. А индекс все - же обнулите где-то в блоке

  if(!flag_start)
   {
    flag_start=1;
    TCNT1=0;
    TCNT0=0;
    OCR0=1;
    t_zub=0;
    return;
   }

Картина улучшится - дальше поговорим.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там получается, что прерывания повторяются несколько раз.

Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт.

А индекс все - же обнулите где-то в блоке. Картина улучшится - дальше поговорим.

Индекс у меня - глобальная переменная - он используется и в другом месте. К нему претензий нет.

Может, взять Mega 164? Там вроде два регистра сравнения, будет две функции прерывания - поочерёдно. Дорого только ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт.

Тогда это извращение, скажу Вам по секрету.

Внешний сигнал может иметь дребезг, вообще, какое его качество?

Я бы сделал так, исходя из того, что все на Т0 ужЕ заведено: ставить таймер в 0xff и делать прерывания по переполнению, а все остальные манипуляции делать со статическими переменными, вместо TCNT0 и OCR0. Затем - в конце прерывания - снова в 0xff.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда это извращение, скажу Вам по секрету.

В чём извращение? Прерывание на каждый такт нужны временно, в дальнейшем прерывания планируются на такты 1,5,10,11,19,20,25,26,29.

Иначе завёл бы сигнал на INT0.

Внешний сигнал может иметь дребезг, вообще, какое его качество?

Качество сигнала очень хорошее + стоит компаратор с гистерезисом.

Я бы сделал так, исходя из того, что все на Т0 ужЕ заведено: ставить таймер в 0xff и делать прерывания по переполнению, а все остальные манипуляции делать со статическими переменными, вместо TCNT0 и OCR0. Затем - в конце прерывания - снова в 0xff.

Вы хотите сказать, что TCNT0 получится перезаписывать каждый такт, а OCR0 нет?

Кстати, перепаять один провод - не проблема.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это как?

И где завершается период - при начале следующего? Может, в этом проблема?

Например

 

OC25 I W20 OC25 I W15 OC20 I ....

Где I - прерывание, W - запись значения в OCR, OC - текущая отработка.

 

То есть у вас идёт запаздывание. Что вы читаете из OCR я не знаю - не пробовал. Но возможно у вас во всей этой логике и кроется ошибка. Обычно вывод осуществляется по таблице. Иными словами вы же и так знаете, что туда пишите. Так зачем ненужная обратная связь? Расчитывайте исходя из значений, что пишете.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я нашёл, где косяк. CodeVisionAVR не может выполнить такой код:

 

while((i_zub < i_zub_max) && (flag_s))
         {
          t_zub_i[i_zub++]=0x1234;
         }

Разумеется, сообщений об ошибках нет.

Т.е. индекс массива не может быть задан как переменная? Или элементы массива по одиночке нельзя переопределять?

 

Как это можно обойти?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...