Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Постоянные изменения OCR0.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Александр К.
Есть потребность непрерывно перезаписывать в Меге 16 OCRO. Можно ли это делать? Дело в том, что на практике запись идёт с ошибками.

CODE
// 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 включительно, затем опять начинаться с единицы. Но в реальности этого гарантированно нет. Почему?
_Pasha
А ничего, что у Вас изменение сабжа сильно джиттерные получаются?
И где i_zub = 0; - не видать что-то.

ЗЫ: говнокод в тэги codebox а не code smile.gif - так он читабельнее.
И по временам подробнее плз - успевает ли оно ваще.
Александр К.
Цитата(_Pasha @ Oct 28 2010, 22:10) *
А ничего, что у Вас изменение сабжа сильно джиттерные получаются?

Как побороть?
Цитата(_Pasha)
И где i_zub = 0; - не видать что-то.

Есть такое: char i_zub=0;
Цитата(_Pasha)
И по временам подробнее плз - успевает ли оно ваще.

Вполне успевает.
_Pasha
Цитата(Александр К. @ Oct 28 2010, 21:36) *
Как побороть?

Есть такое: 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.
SasaVitebsk
При записи в OCR регистр, значение обновляется после завершения периода. Не смотрел текст, так как очень большой. Но принципиально, всё должно работать. Обновлять надо по TOV.
Александр К.
Цитата(_Pasha @ Oct 28 2010, 22:56) *
2. Тем более непонятно, какая часть прерывания ее должна перевзводить обратно, после фрагмента case 29: ....

Эта:
Код
case 29:
   ...
   OCR0=1;
   TCNT0=0;
   ...

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

Цитата(SasaVitebsk @ Oct 28 2010, 22:56) *
...Обновлять надо по TOV.

Это как?
И где завершается период - при начале следующего? Может, в этом проблема?
_Pasha
Цитата(Александр К. @ Oct 28 2010, 22:15) *
На п.1. Какая разница? Если можно, поясните.

switch() может последовательно перебирать все значения от 1 до 29 (а может и нет - зависит от компилера), тогда бОльшие числа будут писАться позднее.
А таймер тем временем тикает...
Но - если успевает, о чем мы говорим?
По поводу i_zub - ну не вижу я где он заново обнуляется smile3046.gif
Александр К.
Цитата(_Pasha @ Oct 28 2010, 23:25) *
...По поводу i_zub - ну не вижу я где он заново обнуляется smile3046.gif

i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется.
_Pasha
Цитата(Александр К. @ Oct 28 2010, 22:30) *
i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется.

Там получается, что прерывания повторяются несколько раз. А индекс все - же обнулите где-то в блоке
Код
  if(!flag_start)
   {
    flag_start=1;
    TCNT1=0;
    TCNT0=0;
    OCR0=1;
    t_zub=0;
    return;
   }

Картина улучшится - дальше поговорим.
Александр К.
Цитата(_Pasha @ Oct 29 2010, 00:41) *
Там получается, что прерывания повторяются несколько раз.

Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт.
Цитата(_Pasha)
А индекс все - же обнулите где-то в блоке. Картина улучшится - дальше поговорим.

Индекс у меня - глобальная переменная - он используется и в другом месте. К нему претензий нет.
Может, взять Mega 164? Там вроде два регистра сравнения, будет две функции прерывания - поочерёдно. Дорого только ...
_Pasha
Цитата(Александр К. @ Oct 29 2010, 07:29) *
Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт.

Тогда это извращение, скажу Вам по секрету.
Внешний сигнал может иметь дребезг, вообще, какое его качество?
Я бы сделал так, исходя из того, что все на Т0 ужЕ заведено: ставить таймер в 0xff и делать прерывания по переполнению, а все остальные манипуляции делать со статическими переменными, вместо TCNT0 и OCR0. Затем - в конце прерывания - снова в 0xff.
Александр К.
Цитата(_Pasha @ Oct 29 2010, 09:37) *
Тогда это извращение, скажу Вам по секрету.

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

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

Вы хотите сказать, что TCNT0 получится перезаписывать каждый такт, а OCR0 нет?
Кстати, перепаять один провод - не проблема.
SasaVitebsk
Цитата(Александр К. @ Oct 28 2010, 22:15) *
Это как?
И где завершается период - при начале следующего? Может, в этом проблема?

Например

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

Разумеется, сообщений об ошибках нет.
Т.е. индекс массива не может быть задан как переменная? Или элементы массива по одиночке нельзя переопределять?

Как это можно обойти?
Сергей Борщ
Цитата(Александр К. @ Nov 6 2010, 13:52) *
CodeVisionAVR не может выполнить такой код:
Исключительно информативно. А что означает в вашем понятии "не может выполнить код"?
Александр К.
Если массив определить вот так: unsigned int t_zub_i[], то в него ничего не пишется (или пишется непонятно что), хотя и ошибок при компиляции никаких не показывается. Обошёл просто: unsigned int t_zub_i[96]. Т.е. при явном задании числа элементов массива всё заработало.
MrYuran
Цитата(Александр К. @ Nov 9 2010, 13:07) *
Если массив определить вот так: unsigned int t_zub_i[], то в него ничего не пишется (или пишется непонятно что)

Скорее, пишется непонятно куда, т.к. массив задан нулевой длины
Ну и соответственно там, непонятно где, произвольно изменяется непонятно чем.
Александр К.
По описанию CodeVision это вроде допускается - не указывать длинну. Сам должен подсчитать smile.gif .
MrYuran
Цитата(Александр К. @ Nov 9 2010, 16:10) *
Сам должен подсчитать smile.gif .

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

Нехилый у него должен быть интеллект, чтобы сосчитать
Да и вообще, надо придерживаться стандартов, а не уповать на какие-то левые "фичи"
Палыч
Цитата(Александр К. @ Nov 9 2010, 16:10) *
Сам должен подсчитать.
IMHO, сам подсчитает, если есть начальная инициализация:
Код
unsigned int t_zub_i[]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
В остальных случаях, размер массива определить должны Вы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.