|
Непонятна логика программы, Не могу найти ошибку. Подскажите. |
|
|
|
Feb 13 2008, 20:12
|

Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297

|
Пишу программу на С для AVR. Cуть - плавный пуск. Проблемный кусок: Цитата int n=0;
// External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { // Place your code here n=n+1;
if (0<n<11) { TCNT0=0x83; TCCR0=0x03; }
if (10<n<21) { TCNT0=0x91; TCCR0=0x03; }
if (20<n<31) {
TCNT0=0x9D; TCCR0=0x03;
}
} Объявил глобальную переменную. Присвоил ей нулевое значение. При каждом внешнем прерывании переменная инкрементируется. В зависимости от количества прерываний запускается таймер с разной константой. То есть первых 10 прерываний - константа будет 0x83 Следующий 10 - 0x91 и т.д. Но на асемблере получилось не так, как планировалось. Программа проверяет каждое условие и всё равно выполняет все подряд операторы. Например в начале, когда n=1, она проверяет не меньше ли оно 10. Оно меньше. Значит выполняются операторы. Потом идёт вторая проверка. Тут условие не выполняется, но всё равно операторы выполняются.Программа на асемблере: Цитата ; 44 // Place your code here ; 45 n=n+1; MOVW R30,R4 ADIW R30,1 MOVW R4,R30 ; 46 second=0; CLR R6 CLR R7 ; 47 ; 48 if (0<n<11) { MOVW R30,R4 LDI R26,LOW(0) LDI R27,HIGH(0) CALL __LTW12 CPI R30,LOW(0xB) BRSH _0x3 ; 49 TCNT0=0x83; LDI R30,LOW(131) OUT 0x32,R30 ; 50 TCCR0=0x03; LDI R30,LOW(3) OUT 0x33,R30 ; 51 } ; 52 ; 53 if (10<n<21) { _0x3: MOVW R30,R4 LDI R26,LOW(10) LDI R27,HIGH(10) CALL __LTW12 CPI R30,LOW(0x15) BRSH _0x4 ; 54 TCNT0=0x91; LDI R30,LOW(145) OUT 0x32,R30 ; 55 TCCR0=0x03; LDI R30,LOW(3) OUT 0x33,R30
...................................
__LTW12: CP R26,R30 CPC R27,R31 LDI R30,1 BRLT __LTW12T CLR R30 __LTW12T: RET То что подчеркнул красным проблемные места. Получается R30 всегда либо 1, ли бо 0. Подскажите, в чём ошибка.
Сообщение отредактировал Владимир_КПИ - Feb 13 2008, 20:21
|
|
|
|
|
Feb 13 2008, 21:15
|

Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297

|
Спасибо. Исправил. Сейчас проверю работу на практике. Всё отлично работает. Программа своё отрабатывает. Единственное, что плавный пуск делается за 10 шагов. Нужно сделать чаще, чтобы для зрения не было замерно. Чтобы был именно планым, а не рывками. Но если добавлю ещё операторов if будет не совсем хорошо - при каждом прерывании делать множество проверок. Нельзя ли как-то оптимизировать код? Видео
Сообщение отредактировал Владимир_КПИ - Feb 13 2008, 21:23
|
|
|
|
|
Feb 13 2008, 22:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Feb 13 2008, 23:32)  Проблема в том, что это написано не на "C"  . Да ладно Вам, вполне жизненная конструкция, и кстати очень даже на C  Например так: unsigned char a; a = 0; if (1>a>0) ...... a = 1; if (1>a>0) ...... Шучу...
|
|
|
|
|
Feb 14 2008, 00:20
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(=AK= @ Feb 14 2008, 02:49)  Дык, чую,что совсем незачем принципиально так строить алгоритм - там что-то системного подхода в упор не видать  . А co switch он такого в обнимку с волшебником натворит  . Ладно пример со switch: Код switch( n++ / 10 ) { case 0: TCNT0=0x83; break; case 1: TCNT0=0x91; break; case 2: TCNT0=0x9D; break; case ....... ....... break;
default: ; } TCCR0=0x03;
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 14 2008, 02:56
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Более эффективный способ проверок, требуется только одно сравнение для каждого поддиапазона. Код if( n < 11 ) TCNT0=0x83; else if( n < 21 ) TCNT0=0x91; else if( n < 31 ) TCNT0=0x9D; если хочется ещё быстрее - придётся за это заплатить размером памяти кода. Например так: Код __flash char table[] = { 131, 132, ..... 145 /*... и так далее */ }; // а вместо кучи if одна строка TCNT0= table[n]; разумеется, нужно позаботиться о случаях когда n меньше 0 (можно объявить как unsigned) и когда n становится больше максимального индекса в массиве table.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Feb 14 2008, 06:19
|

Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297

|
Цитата __flash char table[] = { 131, 132, ..... 145 /*... и так далее */ }; // а вместо кучи if одна строка TCNT0= table[n]; Вот это по-моему лучший вариант для моего случая. Объявлю массив со 100 значениями. При каждом прерывании будет инкрементироваться n. За 2 секунды - 100 раз по 1%. Будет и плавнее. Цитата когда n становится больше максимального индекса в массиве table Да, думал над этим. Сейчас что-нибудь придумаю.
|
|
|
|
|
Feb 14 2008, 10:14
|

Частый гость
 
Группа: Свой
Сообщений: 99
Регистрация: 27-10-07
Из: СПб
Пользователь №: 31 797

|
Цитата(Владимир_КПИ @ Feb 14 2008, 12:57)  Есть массив:
int time[100]={0xFB04, 0xF8F2, .....}
Как из элемента массива отделить байты?
Чтобы потом сделать так:
TCNT1H=0xFB; //TCNT1H=high(time[0]) TCNT1L=0x04; //TCNT1L=low(time[0])
Коментарии условные. TCNT1H = (time[n] & 0xFF00) >> 8; TCNT1L = time[n] & 0xFF; ... и открыть ветку "изучаем С интерактивно"
Сообщение отредактировал Liseev - Feb 14 2008, 10:15
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|