|
Компьютеры Уголок для решения бытовых компьютерных проблем. |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
10.10.2013, 09:16 | #26 |
да, похоже что ошибся с объемом кода.
Возможно действительно по разному компилирует. Поставил avr studio 6 (в связи с тем, что на основном ПК она поломалась) на виртуалку, и там мучаюсь. пошел другим путем - смотрю в дебаггере шаги. Взял из программы кусок кода, и немного укоротил - сделал чисто дешифратор: #include <avr/io.h> int main(void) { DDRA = 0xFF; PORTA = 0b00000000; DDRD = 0x00; PORTD = 0b00000000; for (; { if ((PIND0==1)&&(PIND1==0)&&(PIND2==0)) PORTA = 0b00000100; else if ((PIND0==1)&&(PIND1==1)&&(PIND2==0)) PORTA = 0b00110100; else if ((PIND0==0)&&(PIND1==1)&&(PIND2==0)) PORTA = 0b00100100; else if ((PIND0==0)&&(PIND1==1)&&(PIND2==1)) PORTA = 0b00000010; else if ((PIND0==0)&&(PIND1==0)&&(PIND2==1)) PORTA = 0b00000010; else if ((PIND0==1)&&(PIND1==0)&&(PIND2==1)) PORTA = 0b00111100; else PORTA = 0b00000001; } } По шагам, первые 4 (назначение портов) дебаггер отрабатывает, а потом сразу прыгает в строку else PORTA = 0b00000001; не отрабатывая никакие другие. и оттуда его ничем не выудить... ошибок, предупреждений нет.
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
10.10.2013, 11:39 | #27 |
значит не отрабатывают PIND0. попробуй прочитать пины по другому.
в еще лучше сделать это через switch. не помню как в студии, в ирае это объявлено как #define PIND0 0 естественно никогда единице равняться не будет. вот. так как-то. if ((PIND & 1 ==1) &&(PIND & 2==0) && (PIND &4 ==0)) Последний раз редактировалось Kino; 10.10.2013 в 12:21. |
|
18.10.2013, 18:55 | #28 |
Адрес: Вишгород
Возраст: 53
Сообщений: 2,052
Машина: ржавый корч плюс второй ржавый корч
Длина: 32860мкм
Диаметр: 26мм
|
Ничего, я пять копеек вставлю?
Полгодика uC не ковырял, но вот так удобно: #define cw_pressed !(PIND & 0b00000100) #define ccw_pressed !(PIND & 0b00001000) Потом что-то типа: ISR(INT0_vect){ cli(); _delay_ms(1); ClrBit(PORTD,PS); if(cw_pressed) t = ((t << 7) | (t >> 1)); if(t & 1) SetBit(PORTD,DIR1); else ClrBit(PORTD,DIR1); if(t & 2) SetBit(PORTD,DIR2); else ClrBit(PORTD,DIR2); _delay_ms(1); SetBit(PORTD,PS); sei(); } Только при куче датчиков может прерываний не хватить, но схемотехнически, через диоды, можно все кнопки на одно внешнее прерывание посадить. |
20.10.2013, 17:49 | #29 |
5 копеек - это хорошо, но мое понимание еще не дошло до данного кода...
проще говоря - я из этого ничего не понял. Т.к. мое изучение програмирования МК и вообще С++ ограничивается на данный момент только вот этим одним устройством. Но за код все равно спасибо - найду на работе час-полтора свободного времени - попробую разобраться с данной записью
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
20.10.2013, 19:32 | #30 |
Адрес: Вишгород
Возраст: 53
Сообщений: 2,052
Машина: ржавый корч плюс второй ржавый корч
Длина: 32860мкм
Диаметр: 26мм
|
Я тогда пока накидаю недостающих для понимания строк и картинку.
Также добавлю, что у меня биполярный шаговик. #define PS PD6 #define DIR1 PD4 #define DIR2 PD5 #define SetBit(Port,bit) Port |= _BV(bit) #define ClrBit(Port,bit) Port &= ~_BV(bit) #define Bit(bit) (1 << (bit)) volatile unsigned char t; void init() { cli(); DDRD=0b01110000; PORTD=0b00001110; ClrBit(MCUCR,ISC01); ClrBit(MCUCR,ISC00); ClrBit(MCUCR,ISC11); ClrBit(MCUCR,ISC10); SetBit(GICR,INT0); SetBit(GICR,INT1); set_sleep_mode(SLEEP_MODE_IDLE); t = 0b11001100; sei(); } int main(void) { init(); while(1); return 0; } К картинке необходимо добавить, что я использовал МС управления ШД, который при подаче единиц на DIR1 и DIR2 устанавливает одну полярность на обмотках 1 и 2 соответственно, а при "нулях" - противоположную. PS управляет режимом с пониженным потреблением - обеспечивает удержание ротора в паузах. |
29.10.2013, 17:36 | #31 |
Начинаю все с начала, в связи с некоторыми изменениями в логике устройства (введение АЦП)
первым делом разбиваю всю программу на подпрограммы, и смотрю как работает. Первая программа - дешифратор задатчика (порт B), для наглядности выводит информацию в унитарном виде на порту D (данные на порту В - третий столбец таблицы, диод на порту D - первый столбец таблицы) прочерки означают незадаваемое положение, кресты - что при указанном состоянии прочих ног, состояние данной не учитывается. #define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> int main(void) { PORTA=0b11111111; DDRA=0b00000000; PORTB=0b11111111; DDRB=0b00000000; PORTC=0b00000000; DDRC=0b11111111; PORTD=0b00000000; DDRD=0b11111111; PORTD=0b11111111; _delay_ms(2000); PORTD=0b00000000; while(1) { //Задатчик; //Таблица соответствия состояния энкодера / задатчика положения / индикации положения; // № | PA4 PA5 PA6 | PB0 PB1 PB2 PB3 | PD2-6; // --------------------------------------------------; // 1 | 0 1 1 | 1 1 x 1 | 00010; // 2 | 0 0 1 | 0 1 0 1 | 11010; // 3 | 1 0 1 | 0 1 1 1 | 10010; // 4 | 1 0 0 | x x x 0 | 00001; // 5 | 1 1 0 | - - - - | 00001; // 6 | 0 1 0 | 0 0 x 1 | 11110; // 7 | 0 1 0 | 1 0 x 1 | 00110; com: if (PORTB3==0) { PORTD=0b00001000; } else if(PORTB3==1 && PORTB0==1 && PORTB1==1) { PORTD=0b00000001; } else if(PORTB3==1 && PORTB0==1 && PORTB1==0) { PORTD=0b01000000; } else if(PORTB3==1 && PORTB0==0 && PORTB1==0) { PORTD=0b00100000; } else if(PORTB3==1 && PORTB0==0 && PORTB1==1 && PORTB2==0) { PORTD=0b00000010; } else if(PORTB3==1 && PORTB0==0 && PORTB1==1 && PORTB2==1) { PORTD=0b00000100; } else { goto com; } } } При проверке дебаггером ошибок и замечаний нет, но когда провести пошаговыую проверку, тоон просматривает назначение портов, и замирает. до тела программы не доходит. При проверке в эмуляторе (протеус), ругается на то, что в hex-файле найдена какая-то ошибка. ps: to Глобус 1 - к сожалению с твоим кодом не разобрался 2 - двигатель у меня не шаговый, а коллекторный. pps: может кто посоветует более адекватное ПО для написания, отладки и компиляции программы?
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
29.10.2013, 19:09 | #32 | |
Адрес: Днепропетровск
Сообщений: 11,717
Машина: Tesla model S 85, Таврия 1.3 инж.
Длина: 65820мкм
Диаметр: 33мм
|
Цитата:
Есть еще Кодевижн, но мне больше нравится ICC, там работающий проект можно создать буквально за несколько кликов мышкой. Ну и конечно IAR, но это для профессионалов, можно позже на него переползти. Последний раз редактировалось Yurasvs; 29.10.2013 в 20:35. |
|
29.10.2013, 21:30 | #33 |
Блин. Надо найти время и запилить вам этот проект. Осталось узнать как.
Вы на функции программу не перевели, у Вас остался goto. Это не принципиально, но и не функция. Немного теории (совсем чуть-чуть). Регистры портов в авр делятся на три типа, направление, выход и вход, называються соответственно DDRx, PORTx и PINx. Т.е. чтобы выдать на порт значение используем PORT, чтобы считать - используем PIN. Давайте так. Создайте функцию. Типа char GetEncoder(void); И в ней, вместо этого, вызывайте её: m: if (PORTB3==0) { PORTD=0b00001000; } else if(PORTB3==1 && PORTB0==1 && PORTB1==1) { PORTD=0b00000001; } else if(PORTB3==1 && PORTB0==1 && PORTB1==0) { PORTD=0b01000000; } else if(PORTB3==1 && PORTB0==0 && PORTB1==0) { PORTD=0b00100000; } else if(PORTB3==1 && PORTB0==0 && PORTB1==1 && PORTB2==0) { PORTD=0b00000010; } else if(PORTB3==1 && PORTB0==0 && PORTB1==1 && PORTB2==1) { PORTD=0b00000100; } else { goto com; } } } char GetEncoder(void) { if (PINB & 0x80 == 0) { PORTD=0b00001000; return 1; // выход с флагом 1, что сработал по "if (PINB & 0x80 == 0) " } // иначе там единица, продолжаем switch (PINB & 0x0F) { case 0x0B: PORTD=0b00000001; break; case 0x09: PORTD=0b01000000; break; case 0x08: PORTD=0b00100000; break; case 0x0A: PORTD=0b00000010; break; case 0x0E: PORTD=0b00000100; break; default: // если ничего не совпало - возвращаем 2. return 2; break; } в цикле while(1) { char x; x = GetEncoder(); if (x == 1) знач вернулся вернулся по "if (PINB & 0x80 == 0) " или так while (GetEncoder()) == 2) {} // т.е. вызываем GetEncoder, пока не вернется что-то отличное от двойки. } // скобка конца while() |
|
30.10.2013, 11:26 | #34 |
Адрес: Вишгород
Возраст: 53
Сообщений: 2,052
Машина: ржавый корч плюс второй ржавый корч
Длина: 32860мкм
Диаметр: 26мм
|
Pilot, а что в таличке состояний означают "x" и "-"?
|
30.10.2013, 13:48 | #35 |
прочерки означают незадаваемое положение (задатчиком его нельзя выбрать, но в энкодере оно есть)
кресты - что при указанном состоянии прочих ног, состояние данной не учитывается.
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
30.10.2013, 14:43 | #36 |
Pilot
Отмечучь и я, чисто в рекомендательном плане. Уберите goto в коде поста №31, оно там ни к чему вообще, while(1) и так выполнится с первой строчки, если не сработает ни одно условие, при этом желательно в конце while поставить небольшую задержку (~100мс), если планируете использовать какие-то дополнительные процедуры. И я б, честно, подобные строки if(PORTB3==1 && PORTB0==1 && PORTB1==1) заменил бы на if (PORTB==0b00001011) Почему? Да потому что оператор if выполнится всего один раз вместо 5 Ну или для полноты понимания, при помощи define создайте варианты необходимых условий. Вы хоть код понимать будете ну и помочь будет легче вновь читающим. К примеру #define VAR0 0b00001011 if (PORTB==VAR0)... или if (PORTB & VAR0)... что полностью заменяет if(PORTB3==1 && PORTB0==1 && PORTB1==1) и облегчает чтение. Этим разгрузите код и вероятно облегчите жизнь дебугеру. Конечно, если так можно, а пятой точкой ощущаю, что можно наврняка. Kino, к стати, правильно подсказывает, насчет отдельной процедуры, но по опыту работы с контроллерами, я б нестал использовать такие тяжелые формы как case, от этого легче не станет, а код усложнит и займет на порядок больше тактов, описанный выше мною вариант более применим к контроллерам, со статическмими условиями регулятора.
__________________
Последний раз редактировалось Said; 30.10.2013 в 14:54. |
|
30.10.2013, 14:54 | #37 |
вот здесь вроде немного понятно:
char GetEncoder(void) while (GetEncoder()) == 2) { if (PINB & 0x80 == 0) { PORTD=0b00001000; return 1; // выход с флагом 1, что сработал по "if (PINB & 0x80 == 0) " // иначе там единица, продолжаем } // я так понимаю, что если 8-ая нога порта В равна 0, то на выходе порта D будет 00001000, в противном случае идем дальше. switch (PINB & 0x0F) { case 0x0B: PORTD=0b00000001; break; case 0x09: PORTD=0b01000000; break; case 0x08: PORTD=0b00100000; break; case 0x0A: PORTD=0b00000010; break; case 0x0E: PORTD=0b00000100; break; default: return 2; break; // если ничего не совпало - возвращаем 2. } // Здесь, как я понял, определение выражения на 4х ногах порта В (PINB & 0x0F) - (в двоичной =00001111), тех, на которых кнопки задатчика // соответствие входа выхода вроде бы такое: // 1011 - 00000001 // 1001 - 01000000 // 1000 - 00100000 // 1010 - 00000010 // 1110 - 00000100 } // До тех пор, пока будет возвращатся 2, будет выполнятся оператор while. в противном случае опреатор прекращается, я имею на порту D нужный сигнал и могу выполнять следующую процедуру. Правильно понял?
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi Последний раз редактировалось Pilot; 30.10.2013 в 15:00. |
|
30.10.2013, 15:03 | #38 |
Условие if (PINB & 0x80 == 0) как по мне не корректно. В данном случае всегда будет ложь, т.к. 0x80 не равно 0
Для успокоения совести напишите: if ((PINB & 0x80) == 0) или просто if !(PINB & 0x80)
__________________
|
|
30.10.2013, 16:20 | #39 |
т.е. ты предлагаешь сделать следующим образом:
#define com1 0b00001011 #define com2 0b00001010 #define com3 0b00001110 #define com4 0b00000000 #define com6 0b00001000 #define com7 0b00001001 char GetEncoder(void) while (GetEncoder())==2) if PORTB==com1 {PORTD=0b00000001} else if PORTB==com2 {PORTD=0b00000010} else if PORTB==com3 {PORTD=0b00000100} else if PORTB==com4 {PORTD=0b00001000} else if PORTB==com6 {PORTD=0b00100000} else if PORTB==com7 {PORTD=0b01000000} else {return 2}
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
30.10.2013, 16:49 | #40 |
Но в таком виде код не пройдет компиляцию, ибо ошибок тьма.
И, если GetEncoder разовая функция, то ее нет смысла оформлять отдельной процедурой. В остальном направление мысли верно. Ну вот как-то так: #define com1 0b00001011 #define com2 0b00001010 #define com3 0b00001110 #define com4 0b00000000 #define com6 0b00001000 #define com7 0b00001001 char GetEncoder(void) { if (PORTB==com1) PORTD=0b00000001; else if PORTB==com2 PORTD=0b00000010; else if (PORTB==com3) PORTD=0b00000100; else if (PORTB==com4) PORTD=0b00001000; else if (PORTB==com6) PORTD=0b00100000; else if (PORTB==com7) PORTD=0b01000000; else return 2; return 0; } int main(void) // главная рутина { //.........какой-то код............ while (GetEncoder()==0) _delay_ms(100); //или //while (GetEncoder()>0) _delay_ms(100); //зависит от желаемого результата //.........какой-то код............ }
__________________
Последний раз редактировалось Said; 30.10.2013 в 17:21. |
|
31.10.2013, 09:11 | #41 |
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
31.10.2013, 09:29 | #42 |
Так у Вас все есть, вот четко по алгоритму и действуйте. Просто код старайтесь дедать максимально простым и учитывайте, что необходимы задержки при отработке команд до чтения состояния, причем величина задержек прямопропорциональна инертности исполнительных элементов.
__________________
|
|
31.10.2013, 09:37 | #43 | |
Цитата:
И остальные так-же. #define com1 0b00001011 #define com2 0b00001010 #define com3 0b00001110 #define com4 0b00000000 #define com6 0b00001000 #define com7 0b00001001 char GetComander(void) { if (PORTB==com1) com=0b00000001; else if PORTB==com2 com=0b00000010; else if (PORTB==com3) com=0b00000100; else if (PORTB==com4) com=0b00001000; else if (PORTB==com6) com=0b00100000; else if (PORTB==com7) com=0b00100000; else return 2; return 0; } While (GetComander()==2)_delay_ms(100); // если какое-то условие верно, то на выходе получим соответствующее значение, а функция GetComander будет равна 0. Ну и соответственно, пойдет дальнейшее выполнение программы. // если никакое условие не совпадет, то функция GetComander будет равна 2 и повторится через 0,1с. Теперь вторая часть дешифратора, в которой не может быть неоднозначного положения, т.е. если возникает неопознанное значение, то программа должна "выпасть" в ошибку: #define enc1 0bx110xxxx #define enc2 0bx100xxxx #define enc3 0bx101xxxx #define enc4 0bx001xxxx #define enc5 0bx011xxxx #define enc6 0bx010xxxx // где "х" - может быть любым значением (используется отдельно от дешифратора, char GetEncoder(void) { if (PORTA & 0b01110000 ==enc1) enc=0b00000001; else if (PORTA & 0b01110000 == enc2) enc=0b00000010; else if (PORTA & 0b01110000 == enc3) enc=0b00000100; else if (PORTA & 0b01110000 == enc4) enc=0b00001000; else if (PORTA & 0b01110000 == enc5) enc=0b00100000; else if (PORTA & 0b01110000 == enc6) enc=0b00100000; else return 2; return 0; } if (GetEncoder()==2) ERROR \\ переход к подпрограмме ошибки else \\ продолжаем выполнять основную программу
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi Последний раз редактировалось Pilot; 31.10.2013 в 14:22. |
||
31.10.2013, 14:27 | #44 | |
Цитата:
Проблема в том, что я не изучал ранее языки программирования (окромя паскаля в 9м классе). И вот собственно мне стал вопрос изготовления блока управления. На нем я и решил поучиться столь интересному занятию. Конечно, как для первой программы у меня возникло - программа на операторе IF/ELSE написана вроде как правильно, замечаний в компиляторе нет, но она не работает в контроллере. Вот и обратился за помощью (и заодно - получу новые знания , надеюсь)
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
||
31.10.2013, 17:40 | #45 |
Ну, судя по представленному Вами алгоритму, вам, кроме if/else, врядли потребуются более изощренные компоненты языка.....
__________________
|
|
31.10.2013, 18:28 | #46 |
только он у меня нихрена не заработал... к сожаленью
Хотя 2 человека, которые пишут на С++, но не программируют контроллеры, сказали, что код правильный
__________________
Надейся на лучшее, расчитывай на худшее Люблю Таврооргию. Такого пох№зма и подъ№балова нигде не встретишь! (c) Lusi |
|
31.10.2013, 18:44 | #47 |
Значит Вы просто где-то промахиваетесь либо с начальной конфигурацией контроллера либо в схеме.
__________________
|
|
31.10.2013, 20:32 | #48 |
Адрес: Днепропетровск
Сообщений: 11,717
Машина: Tesla model S 85, Таврия 1.3 инж.
Длина: 65820мкм
Диаметр: 33мм
|
Фузы правильно зашили?
|
31.10.2013, 21:01 | #49 |
не фьюзах дело. настройки где-то кривые. он пишет под avrstudio + winavr.
|
|
04.11.2013, 14:24 | #50 |
Сорри что вклиниваюсь в интеллектуальную беседу, а, извиняюсь, - более простые программы писали?
Светодиодиком получалось моргать? К сожалению - из топика не вижу ни полную схему, ни программу. Но пробовали собирать на макете, и вместо датчиков использовать кнопки, а вместо исполнительных инструментов те же светодиоды? Проблему дребезга контактов концевиков решили? Все входы и выходы проинициализировали правильно? Ничего у вас в "воздухе" не осталось висеть?
__________________
Правительство на другой планете живет… родной. (с) Кин-дза-дза! |
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|
|