|
Постоянные изменения OCR0., Некорректная запись в этот регистр. |
|
|
|
Oct 28 2010, 17:39
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Есть потребность непрерывно перезаписывать в Меге 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 включительно, затем опять начинаться с единицы. Но в реальности этого гарантированно нет. Почему?
Сообщение отредактировал Александр К. - Oct 28 2010, 18:37
|
|
|
|
|
Oct 28 2010, 18:36
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Цитата(_Pasha @ Oct 28 2010, 22:10)  А ничего, что у Вас изменение сабжа сильно джиттерные получаются? Как побороть? Цитата(_Pasha) И где i_zub = 0; - не видать что-то. Есть такое: char i_zub=0; Цитата(_Pasha) И по временам подробнее плз - успевает ли оно ваще. Вполне успевает.
|
|
|
|
|
Oct 28 2010, 18:56
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Александр К. @ 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.
|
|
|
|
|
Oct 28 2010, 19:15
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Цитата(_Pasha @ Oct 28 2010, 22:56)  2. Тем более непонятно, какая часть прерывания ее должна перевзводить обратно, после фрагмента case 29: .... Эта: Код case 29: ... OCR0=1; TCNT0=0; ... На п.1. Какая разница? Если можно, поясните. Цитата(SasaVitebsk @ Oct 28 2010, 22:56)  ...Обновлять надо по TOV. Это как? И где завершается период - при начале следующего? Может, в этом проблема?
Сообщение отредактировал Александр К. - Oct 28 2010, 19:16
|
|
|
|
|
Oct 28 2010, 19:25
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Александр К. @ Oct 28 2010, 22:15)  На п.1. Какая разница? Если можно, поясните. switch() может последовательно перебирать все значения от 1 до 29 (а может и нет - зависит от компилера), тогда бОльшие числа будут писАться позднее. А таймер тем временем тикает... Но - если успевает, о чем мы говорим? По поводу i_zub - ну не вижу я где он заново обнуляется
|
|
|
|
|
Oct 28 2010, 19:30
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Цитата(_Pasha @ Oct 28 2010, 23:25)  ...По поводу i_zub - ну не вижу я где он заново обнуляется  i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется.
|
|
|
|
|
Oct 28 2010, 20:41
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Александр К. @ Oct 28 2010, 22:30)  i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется. Там получается, что прерывания повторяются несколько раз. А индекс все - же обнулите где-то в блоке Код if(!flag_start) { flag_start=1; TCNT1=0; TCNT0=0; OCR0=1; t_zub=0; return; } Картина улучшится - дальше поговорим.
|
|
|
|
|
Oct 29 2010, 04:29
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

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

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Цитата(_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 нет? Кстати, перепаять один провод - не проблема.
|
|
|
|
|
Oct 29 2010, 06:11
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Александр К. @ Oct 28 2010, 22:15)  Это как? И где завершается период - при начале следующего? Может, в этом проблема? Например OC25 I W20 OC25 I W15 OC20 I .... Где I - прерывание, W - запись значения в OCR, OC - текущая отработка. То есть у вас идёт запаздывание. Что вы читаете из OCR я не знаю - не пробовал. Но возможно у вас во всей этой логике и кроется ошибка. Обычно вывод осуществляется по таблице. Иными словами вы же и так знаете, что туда пишите. Так зачем ненужная обратная связь? Расчитывайте исходя из значений, что пишете.
|
|
|
|
|
Oct 29 2010, 10:51
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Спасибо. Попробую изменить код.
|
|
|
|
|
Nov 6 2010, 11:52
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 12-11-06
Из: Волгоград
Пользователь №: 22 235

|
Я нашёл, где косяк. CodeVisionAVR не может выполнить такой код: Код while((i_zub < i_zub_max) && (flag_s)) { t_zub_i[i_zub++]=0x1234; } Разумеется, сообщений об ошибках нет. Т.е. индекс массива не может быть задан как переменная? Или элементы массива по одиночке нельзя переопределять? Как это можно обойти?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|