Александр К. 0 28 октября, 2010 Опубликовано 28 октября, 2010 (изменено) · Жалоба Есть потребность непрерывно перезаписывать в Меге 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 включительно, затем опять начинаться с единицы. Но в реальности этого гарантированно нет. Почему? Изменено 28 октября, 2010 пользователем Александр К. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба А ничего, что у Вас изменение сабжа сильно джиттерные получаются? И где i_zub = 0; - не видать что-то. ЗЫ: говнокод в тэги codebox а не code :) - так он читабельнее. И по временам подробнее плз - успевает ли оно ваще. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба А ничего, что у Вас изменение сабжа сильно джиттерные получаются? Как побороть? И где i_zub = 0; - не видать что-то. Есть такое: char i_zub=0; И по временам подробнее плз - успевает ли оно ваще. Вполне успевает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба Как побороть? Есть такое: 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба При записи в OCR регистр, значение обновляется после завершения периода. Не смотрел текст, так как очень большой. Но принципиально, всё должно работать. Обновлять надо по TOV. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 28 октября, 2010 Опубликовано 28 октября, 2010 (изменено) · Жалоба 2. Тем более непонятно, какая часть прерывания ее должна перевзводить обратно, после фрагмента case 29: .... Эта: case 29: ... OCR0=1; TCNT0=0; ... На п.1. Какая разница? Если можно, поясните. ...Обновлять надо по TOV. Это как? И где завершается период - при начале следующего? Может, в этом проблема? Изменено 28 октября, 2010 пользователем Александр К. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба На п.1. Какая разница? Если можно, поясните. switch() может последовательно перебирать все значения от 1 до 29 (а может и нет - зависит от компилера), тогда бОльшие числа будут писАться позднее. А таймер тем временем тикает... Но - если успевает, о чем мы говорим? По поводу i_zub - ну не вижу я где он заново обнуляется :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба ...По поводу i_zub - ну не вижу я где он заново обнуляется :smile3046: i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 октября, 2010 Опубликовано 28 октября, 2010 · Жалоба i_zub проходит один цикл изменения от 0 до заданного и больше не обнуляется. Там получается, что прерывания повторяются несколько раз. А индекс все - же обнулите где-то в блоке if(!flag_start) { flag_start=1; TCNT1=0; TCNT0=0; OCR0=1; t_zub=0; return; } Картина улучшится - дальше поговорим. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 29 октября, 2010 Опубликовано 29 октября, 2010 · Жалоба Там получается, что прерывания повторяются несколько раз. Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт. А индекс все - же обнулите где-то в блоке. Картина улучшится - дальше поговорим. Индекс у меня - глобальная переменная - он используется и в другом месте. К нему претензий нет. Может, взять Mega 164? Там вроде два регистра сравнения, будет две функции прерывания - поочерёдно. Дорого только ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 29 октября, 2010 Опубликовано 29 октября, 2010 · Жалоба Таймер тактируется внешним сигналом - примерно каждые 2мс. Прерывание - на каждый такт. Тогда это извращение, скажу Вам по секрету. Внешний сигнал может иметь дребезг, вообще, какое его качество? Я бы сделал так, исходя из того, что все на Т0 ужЕ заведено: ставить таймер в 0xff и делать прерывания по переполнению, а все остальные манипуляции делать со статическими переменными, вместо TCNT0 и OCR0. Затем - в конце прерывания - снова в 0xff. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 29 октября, 2010 Опубликовано 29 октября, 2010 · Жалоба Тогда это извращение, скажу Вам по секрету. В чём извращение? Прерывание на каждый такт нужны временно, в дальнейшем прерывания планируются на такты 1,5,10,11,19,20,25,26,29. Иначе завёл бы сигнал на INT0. Внешний сигнал может иметь дребезг, вообще, какое его качество? Качество сигнала очень хорошее + стоит компаратор с гистерезисом. Я бы сделал так, исходя из того, что все на Т0 ужЕ заведено: ставить таймер в 0xff и делать прерывания по переполнению, а все остальные манипуляции делать со статическими переменными, вместо TCNT0 и OCR0. Затем - в конце прерывания - снова в 0xff. Вы хотите сказать, что TCNT0 получится перезаписывать каждый такт, а OCR0 нет? Кстати, перепаять один провод - не проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 29 октября, 2010 Опубликовано 29 октября, 2010 · Жалоба Это как? И где завершается период - при начале следующего? Может, в этом проблема? Например OC25 I W20 OC25 I W15 OC20 I .... Где I - прерывание, W - запись значения в OCR, OC - текущая отработка. То есть у вас идёт запаздывание. Что вы читаете из OCR я не знаю - не пробовал. Но возможно у вас во всей этой логике и кроется ошибка. Обычно вывод осуществляется по таблице. Иными словами вы же и так знаете, что туда пишите. Так зачем ненужная обратная связь? Расчитывайте исходя из значений, что пишете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 29 октября, 2010 Опубликовано 29 октября, 2010 · Жалоба Спасибо. Попробую изменить код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 6 ноября, 2010 Опубликовано 6 ноября, 2010 · Жалоба Я нашёл, где косяк. CodeVisionAVR не может выполнить такой код: while((i_zub < i_zub_max) && (flag_s)) { t_zub_i[i_zub++]=0x1234; } Разумеется, сообщений об ошибках нет. Т.е. индекс массива не может быть задан как переменная? Или элементы массива по одиночке нельзя переопределять? Как это можно обойти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться