Страница 23 из 111
Добавлено: Пн фев 08, 2010 15:27:43
РобоКОТ
Ну никаких нот фаундов в *.lss не видно- может и все нормально. Узнаю, похоже, только когда плату изготовят и прошью ее

Добавлено: Ср фев 10, 2010 18:44:06
neon-f
подскажите, чтоб вывод перевести в z состояние(неопределенное состояние) его нужно просто назначить входом, или есть какой другой способ?
мне нужно на один из портов контролера выводить в произвольном порядке комбинации из 0, 1, z. как это лучше сделать???
Добавлено: Ср фев 10, 2010 20:10:32
ARV
neon-f писал(а):подскажите, чтоб вывод перевести в z состояние(неопределенное состояние) его нужно просто назначить входом, или есть какой другой способ?
мне нужно на один из портов контролера выводить в произвольном порядке комбинации из 0, 1, z. как это лучше сделать???
для всех МК семейства AVR надо настроить порт на вход и отключить встроенную подтяжку, т.е. DDRx = 0; PORTx = 0. как это лучше делать - сложно сказать. когда мне приспичило подключить 15 светодиодов к attiny13 я сделал массив пар чисел, выводя которые в DDRВ и PORTB можно было включить тот или иной светодиод.
Добавлено: Ср фев 10, 2010 23:57:14
neon-f
Как перевести порт целиком, или отдельный вывод в 1, 0, или в z я разобрался. Мне нужно выводить на порт комбинации из 0, 1, z в произвольном порядке. например 1100zzzz, z11z0zz1, 01z00zzz. Неужели нужно перед каждой сменой информации переконфигурировать порт на вход\выход, вкл\выкл подтягивающие резисторы.....
Добавлено: Чт фев 11, 2010 08:41:18
ARV
neon-f писал(а):Как перевести порт целиком, или отдельный вывод в 1, 0, или в z я разобрался. Мне нужно выводить на порт комбинации из 0, 1, z в произвольном порядке. например 1100zzzz, z11z0zz1, 01z00zzz. Неужели нужно перед каждой сменой информации переконфигурировать порт на вход\выход, вкл\выкл подтягивающие резисторы.....
вы бы еще воскликнули "неужели перед каждым измерением надо АЦП запускать и ждать его готовности?"

да, всякий раз надо переконфигурировать порт, меняя значения в обоих регистрах. в некоторых случаях хватит и изменения только одного, но это исключение, т.к. число таких вариантов не исчерпывающее.
Код: Выделить всё
typedef struct{
char ddr;
char port;
} led_cfg_type; // тип для описателя портов
// массив описателей для включения каждого светодиода отдельно
led_cfg_type leds[] = {
{0x80, 0x40}, // для включения 1-го светодиода
{0x40, 0x10}, // для включения 2-го
{0x10, 0x10} // для включения третьего
// и так далее
}
// включение указанного светодиода
void led_on(char led_num){
PORTD = leds[ led_num ].port;
DDRD = leds[ led_num ].ddr;
}
примерно вот так я делал
Запись в память программ.
Добавлено: Чт фев 11, 2010 17:27:58
uchar
Требуется записать несколько байт в память программ (с чтением разобрался, работает). Для начала просто решил стереть что-нить в памяти данных - не получается.. Покурив документацию, понял, что код, который пишет/стирает что-то в памяти данных, должен находиться в области NRWW (необязательно в секции загрузчика).
Т.е., на асме нужно было написать что-то вроде .org 0x1000-128 и далее код функции, которая будет работать с памятью данных, а как это написать на Си в WinAVR?
Добавлено: Пт фев 12, 2010 21:21:09
DOSOFF
Народ помогите.
Седня ток сел за мегу (ночь безсонная была).
Светодиодами мигал (всеми 7-ю), а вот как создать цикл ожидающий нажатие кнопки? (кнопка например, на PB0)
Сижу под WinAVR
Извиняйте уж, если это было уже, перечитывать все страницы топика неосилил...
Re: Запись в память программ.
Добавлено: Пт фев 12, 2010 22:01:39
ARV
uchar писал(а):Т.е., на асме нужно было написать что-то вроде .org 0x1000-128 и далее код функции, которая будет работать с памятью данных, а как это написать на Си в WinAVR?
задайте атрибут BOOTLOADER_SECTION для вашей функции, вот и все.
Код: Выделить всё
void BOOTLOADER_SECTION my_flash_write_func(void);
Добавлено: Сб фев 13, 2010 01:43:27
DOSOFF
vМой вопрос снят. Путем нетрезвого мышления и нестандартного подхода, победил.
Блин, интересное это дело

Re: Запись в память программ.
Добавлено: Сб фев 13, 2010 01:49:24
uchar
ARV писал(а):uchar писал(а):Т.е., на асме нужно было написать что-то вроде .org 0x1000-128 и далее код функции, которая будет работать с памятью данных, а как это написать на Си в WinAVR?
задайте атрибут BOOTLOADER_SECTION для вашей функции, вот и все.
Код: Выделить всё
void BOOTLOADER_SECTION my_flash_write_func(void);
При компиляции выдает ошибку - пишет, что секция .bootloader заходит в секцию .data

Может, надо чего в мэйкфайле прописать?
Добавлено: Сб фев 13, 2010 09:39:28
ARV
да, надо задать размер секции и адрес ее начала - см. фьюзы МК
Добавлено: Сб фев 13, 2010 20:52:08
neon-f
Подскажите кто знает, что не так пишу. нужно чтоб при замыкании любой ноги порта С на землю, на порте D появлялось и оставалось то что есть на В ???
int main(void) // начало
{
DDRB = 0X00; // ПОРТ B НАЗНАЧЕН ВХОДОМ
PORTB = 0xff; // ВКЛЮЧЕНЫ ПОДТЯГИВАЮЩИЕ РЕЗИСТОРЫ ПОРТА B
DDRD = 0xff; // ПОРТ D НАЗНАЧЕН ВЫХОДОМ
DDRC = 0X00; // ПОРТ C НАЗНАЧЕН ВХОДОМ
PORTC = 0xff; // ВКЛЮЧЕНЫ ПОДТЯГИВАЮЩИЕ РЕЗИСТОРЫ ПОРТА C
start:
if (PINC = 0xff) goto start; else PORTD = PINB;
goto start;
} // конец
Добавлено: Сб фев 13, 2010 21:31:39
ARV
neon-f писал(а):Подскажите кто знает, что не так пишу. нужно чтоб при замыкании любой ноги порта С на землю, на порте D появлялось и оставалось то что есть на В ???
int main(void) // начало
{
DDRB = 0X00; // ПОРТ B НАЗНАЧЕН ВХОДОМ
PORTB = 0xff; // ВКЛЮЧЕНЫ ПОДТЯГИВАЮЩИЕ РЕЗИСТОРЫ ПОРТА B
DDRD = 0xff; // ПОРТ D НАЗНАЧЕН ВЫХОДОМ
DDRC = 0X00; // ПОРТ C НАЗНАЧЕН ВХОДОМ
PORTC = 0xff; // ВКЛЮЧЕНЫ ПОДТЯГИВАЮЩИЕ РЕЗИСТОРЫ ПОРТА C
start:
if (PINC = 0xff) goto start; else PORTD = PINB;
goto start;
} // конец
вы привели пример того, как не надо писать на Си

скажем так, программа в худших традициях бейсика....
вот так записывается на Си то, что вы хотели.
а в чем, собственно, проблема?
Добавлено: Сб фев 13, 2010 23:19:21
neon-f
проблема в том что не работает. даже с вашим кодом.
Вроде одна строчка, все понятно, а в протеусе не работает.
вот эту строку я читаю так
if(PINC != 0xFF) PORTD = PINB;
ЕСЛИ ПОРТ С НЕ РАВЕН FF, ТО ВЫВЕСТИ НА ПОРТ D ДАННЫЕ С ПОРТА В
Правильно?
а по поводу бейсика - вы правы. это единственно на чем я пробовал кодить, и то 17 лет назад

Добавлено: Вс фев 14, 2010 15:12:05
DimAlt
Вроде так работает, зы у меня тож бейсик
Код: Выделить всё
while(1){
if ( (PINC&MASKPIN) != MASKPIN ){
_delay_us(100);//типа антидребезг
if ( (PINC&MASKPIN) != MASKPIN ) PORTD = PINB;
}
}
Хотя в этом конкретном случае лучше сделать так
if ( (PINC&_BV(0)) == 0 ) //опрос одной линии РС0
...
Добавлено: Вс фев 14, 2010 15:47:10
neon-f
Ваш вариант работает. Но почему мой не работает. Не могу успокоится пока не разберусь. Вроде все верно, все элементарно - а не работает. Может кто подскажет где ошибка.
Добавлено: Вс фев 14, 2010 15:59:23
DimAlt
neon-f писал(а):Ваш вариант работает. Но почему мой не работает. Не могу успокоится пока не разберусь. Вроде все верно, все элементарно - а не работает. Может кто подскажет где ошибка.
У мега8 нет РС7 поэтому чтение PINC возвращает 0x7F, а не 0xFF.
if(PINC != 0x7F) PORTD = PINB;
Добавлено: Вс фев 14, 2010 21:06:14
neon-f
ну слава богу, а то я покой потерял. Получается вот где я запутался. Те пины которых нет физически равны 0. НО есть и еще одна мина. на этом порте находится еще и вывод RESET , и он всегда равен 1.
Еще такой вопрос. как прочитать число снятое с разных портов . Например мне нужно переменной Х присвоить значение с DO,D1,A1,A0,D2,D3,D4,D5, (именно в таком порядке)
Добавлено: Вс фев 14, 2010 22:08:17
DimAlt
Решение в лоб
Код: Выделить всё
x=0;
if (PIND & _BV(0)) x=_BV(0);
if (PIND & _BV(1)) x|=_BV(1);
if (PINA & _BV(1)) x|=_BV(2);
if (PINA & _BV(0)) x|=_BV(3);
if (PIND & _BV(2)) x|=_BV(4);
if (PIND & _BV(3)) x|=_BV(5);
if (PIND & _BV(4)) x|=_BV(6);
if (PIND & _BV(5)) x|=_BV(7);
а мож еще как можно сделать, вот на бредил :)) (не проверял!)
Код: Выделить всё
x=0;
p=PIND;
x=p&(_BV(0)|_BV(1));
x|=( p&(_BV(2)|_BV(3)|_BV(4)|_BV(5)) )<<2;
if (PINA & _BV(1)) x|=_BV(2);
if (PINA & _BV(0)) x|=_BV(3);
Добавлено: Вс фев 14, 2010 22:18:11
ARV
это называется не прочесть, а сформировать число из двух разных значений. вариантов тут 2: красивый внешне и простой для понимания, но громоздкий и малоэффективный для написания, и менее понятный и менее простой, но очень эффективный.
первый способ состоит в описании типа-структуры с битовыми полями, а затем в манипуляции с этими битами структуры.
Код: Выделить всё
typedef struct{
uint8_t B0 : 1;
uint8_t B1 : 1;
// и так далее до
uint8_t B7 : 1;
} bit_struct;
bit_struct port_d, port_a, result;
port_a = *(bit_struct*)&PINA;
port_d = *(bit_struct*)&PIND;
result.B0 = port_d.B0;
result.B1 = port_d.B1;
result.B2 = port_a.B0;
// и так далее все прочие биты в нужном порядке
напрямую присваивать структуре числовое значение нельзя, отсюда изврат с преобразованием в указатель и обратно. избежать этого можно при помощи union...
второй способ заключается в том, что вы вручную перетасовываете биты при помощи сдвигов и масок:
Код: Выделить всё
uint8_t port_a, port_d, result;
port_a = PINA;
port_d = PIND;
result = (port_d & 0x03) | (port_d << 2); // расставили биты из порта В
result |=((port_a & 0x01) << 3) | ((port_a & 0x02) << 1); // поставили биты из другого порта
какой из вариантов вам больше по душе - решать вам
