Возникла небольшая проблема с портами мк, а точнее их расположением ...
Начну с начала, как я к этому пришел ... Решил сделать подарок девушке в виде светодиодного сердечка (идеей был вдохновлен на хабре). Начал кодить на отладочной плате (самопал), на которой стоит ATmega16 в DIP корпусе. И тут понеслась ... вроде сделал хорошие наброски кода, баловался с портом В, грациозно делал всякие вундервафли и мигалки с помощью сдвига регистра порта В, аля кусочек из цикла for:
Код:
PORTB=0x00000001; PORTB=PORTB<1;
Решил портировать все это на мегу8 и тут понял что не все так просто Если взглянутьна мегу8 в TQFP корпусе то видим что если ее визуально поделить на пополам (две половинки сердечка) вертикально то получим по 11 пинов на сторону
И так внимание вопрос ! Можно ли эти пины обьеденить в один так называемый 11 битный "порт" что б можно было левой и правой частью управлять как 8ми битным портом, т.е. к примеру LEFT=0b00000000001 и загорается первый (PD0) диод ?
Или быдлокодить и дергать пины через делей ? что щитаю не спортивным
Еще как вариант, сделать драйвер на таймере, в обработчике прерывания преобразуем переменные в порты, т.е. запихиваем нужные биты переменных в нужные биты портов, тем самым включая и выключая нужные светодиоды, а в основном коде играем только с двумя переменными, как с "реальными" портами.
Хм ... Идея Flasher'a довольно интересна. Можно по подробнее как биты переменной запихивать в биты порта ? Я думал както через массив, но потом понял что затея глупая. Можно про Ваш способ по подробней и если не сложно с примерами кода.
zero648 также буду рад увидеть решение с помощью вашего способа, а то если чесно я немного не допонял как это сделать с таймером.
Rondo, интересная у Вас запись шестнадцатеричного числа. Впрочем, и "сдвиг" такой же...
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Вот именно. Потому и определяйтесь: либо 0b00000000 - 0b11111111, либо 0x0 - 0xFF. Например, запись PORTB = 0x10000000 это совсем не установка 7-го бита порта.
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
ну не суть я быдлокодю в CVAVR (о чем кстати жалею) но продолжаю в нем, а про PORTB = 0x10000000 это ж 8 бит (т.е PORTB.7=1). Ну в кодвижене так и вроде работает) по поводу поста s_black - очень интересно, но я в асме полный ноль =\
Если ктото сможет пару примерчиков привести в Си буду благодарен
Спасибо всем за ответы, надеюсь вы "вдолбите" мне в голову эту фичу с виртуальными портами, а пока буду сам пробовать чтото понять, но надеюсь на примеры Си кода -_-
Это не 8 бит а 32. Если перевести в десятичную систему 0x10000000 = (1*16^7)+(0*16^6)+(0*16^5)+(0*16^4)+(0*16^3)+(0*16^2)+(0*16^1)+(0*16^0) = 268 435 456 (или 0b10000000000000000000000000000).
_________________ "Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
поставь табличную подмену текущих данных на требуемые (разновидность табличного декодера) - метод реализации любой из понятных в объёме слово->слово, только при выводе не забудь про "чтение->модификация с данными->модификация с маской(если у портов разное назначение выводов)->запись
Можно разделять исходную переменную битовыми операциями (& / |) по маскам, а потом распихивать выковырянное по портам.
Например, есть у нас шестнадцатибитная переменная VPORT - типа виртуальный порт. Пускай первый и третий ниббл надо запихать в PORTA, а второй и четвертый - в PORTB.
Странное дело... Тот, у кого есть девушка, обычно не знает, как сделать виртуальный порт. А у того, кто знает, обычно нет девушки... Так что Вы это... Аккуратнее.
_________________ Разница между теорией и практикой на практике гораздо больше, чем в теории.
Rondo, если нужно управлять пинами по отдельности, можно сделать примерно так.
Код:
// Массив соответствия виртуальных пинов unsigned char ptable[11,3]{ // Порт B Порт C Порт D {0b00010000, 0b00000000, 0b00000000}, // виртуальный пин 0 {0b00000000, 0b00100000, 0b00000000}, {0b00000000, 0b10000000, 0b00000000}, {0b00001000, 0b00000000, 0b00100000}, {0b00000000, 0b00000100, 0b00000000}, {0b00000100, 0b00000000, 0b00000000}, {0b00000000, 0b00000000, 0b00000000}, {0b00000000, 0b00000001, 0b00000000}, {0b00000000, 0b00000000, 0b00001000}, {0b00000000, 0b00000000, 0b00000010}, {0b10000000, 0b00000000, 0b00000000} // виртуальный пин 1 }
// Установка виртульного пина по его номеру // num от 0 до 10 (в данном случае) void setBit(unsigned char num) { PORTB|=ptable[num, 0]; PORTC|=ptable[num, 1]; PORTD|=ptable[num, 2]; }
Rondo, если есть кто может подружить этот код с СИ, то вот так примерно выглядит драйвер на таймере, индикация здесь у нас получается динамическая, частоту обновления можно изменить, если чё. В основном цикле MAIN загружаем младшие 8 бит и старшие три бита регистра, в соответствующие переменные для каждой линейки светодиодов, а драйвер нам их конвертирует как мы хотим, старшие пять битов старшего регистра нам побоку, Как вариант можно задать массив с кучей разных эффектов и тупо прогонять его просто через переменные, должно неплохо получиться.
.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний RESET: cli ldi r16, high(RAMEND) ; Main program start out SPH, r16 ; Set Stack Pointer to top of RAM ldi r16, low(RAMEND) ; out SPL, r16 ;
clr r16 out TCCR0, r16 ; Стоп Timer0 out TCNT0, r16 ; Сброс Timer/Counter0 ldi r16, 0b00000001 ; Используем вектор переполнения TIMER0 OVF out TIMSK, r16 ; sei
ldi YL, low(SRAM_START) ; Начало ОЗУ ldi YH, high(SRAM_START);
; При тактовой частоте МК 8 МГц, частота обновления около 30 Гц
ну Вы zero648 и наворотили... кстати, "динамика" даже при регенерации с частотой 50Гц уже не слишком приятно смотрится... можно конечно для световых эффектов и так "изголяться", но лучше уж табличка, а самый верный способ - правильно кристалл выбрать, тем более , что их сейчас в каждом семействе навалом ... ну, например здесь atmega8515, atmega126 - там простое рядное расположение выводов...
Ну натворил не натворил, скажем просто накидал для примера, по простому, чтобы читалось проще и понятней для начинающих. Я понимаю, что при частоте 50 Гц это может раздражать, но мы же не выводим информацию, скажем, через один порт на целую матрицу, где частоту для лучшего восприятия делать хотябы не менее 100 Гц, где даже мерцание может быть заметно, а в этом конкретном случае, каждый светодиод подключен к отдельному пину, поэтому, даже при 10 Гц ничего раздражать не должно, у нас просто обновляется состояние портов, тем более, что частоту обновления можно регулировать в том же обработчике прерывания. А выбирать кристалл у нас нет возможности, как я понял, иначе зачем тогда все эти конвертации понадобились автору темы, т.е. мое решение по условию задачи.
Бум лепить из того, что есть, тем более задача не такая уж и сложная, и такой камень пойдет. Собственно, Я обычно так и делаю, сначала развожу плату, как мне удобнее, а потом под железо пишу код, а не наоборот. Хоть немного моск напрячь, а когда просто, както скучно даже.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения