Здравствуйте друзья. Вот и прошли выходные дни, кто то может расстроиться и сказать как то быстро они прошли ничего не успел, кто то наоборот подумать прошли и славу богу что прошли. Это как про тему оптимист пессимист и стакан. У каждого своё на уме всем не угодишь!!! Так вот к чему это я , проснувшись сегодня поняв. осмыслив то что что прошло уже не вернёшь, а всё новое только впереди я решил сюда написать как с вашей помощью я решил задачи собственно темы этого форума. Работа с портами в функциях. Порт как аргумент для функции
функция из исходника многоуважаемого uk8amk для установки пина порта
где : AddressPort адрес порта например ((char*)0x38);//PORTB SRAM adress +0x20 NumberPin номер пина порта 0-7 Value значение в какое состояние переключить пин порта 0 или 1 пример вызова: volatile char *port; port = ((char*)0x32); //PORTD SRAM adress + 0x20 PortSetPin(port, 0, 1);
функция для определения текущего состояния пина, это уже я сам постарался возвращает 1 если пин установлен (1) или 0 если пин не установлен (0)
int TestPinTrue(volatile char *AddressPin, char NumberPin) { if(*AddressPin &(1<<NumberPin)) return 1; // проверяем есть ли 1 на PINB.7 else return 0; }
где: AddressPin адрес PINB ((char*)0x36); //PINB SRAM adress + 0x20 NumberPin номер пина у которого проверяем состояние 0-7 пример вызова: volatile char *port; volatile char *pin; port = ((char*)0x32); //PORTD SRAM adress + 0x20 pin = ((char*)0x36); //PINB SRAM adress + 0x20
if(TestPinTrue(pin,7)==1) PortSetPin(port, 0, 1); else PortSetPin(port, 0, 0); В этом примере проверяется состояние PINB.7 если на PINB.7==1 тогда и на выходе PORD.0=1 иначе PINB.7==0 тогда и на выходе PORD.0=0
Спасибо всем благородно, великодушно кто принимал участие в решении этой интереснейшей задачи. Итог, решение написал подробно так как встречал не раз на форумах такую ситуацию когда идёт обсуждение какого то вопроса хоть на 10стр. отдельные слова фразы предложения я на последней стр написано : ааааааа спасибо я всё понял, тему можно закрывать Мне кажется что надо писать в таких ситуациях, так сказать подводить итог какая была задача и как что ты понял как её реализовал!!! потому что это может быть интересно не только тебе но и другим ! не надо быть эгоистом!!!
if CHECKBIT( PINA, 7 ) sbi(PORTB, 0); else cbi(PORTB, 0);
Нее мне это не подходит. Задумка то и была в том чтоб отказаться от PINA и PORTB и использовать переменные как указатель на них чтоб потом использовать по аналогии с #define. при такой конструкции volatile char *port; port = ((char*)0x32); //PORTD SRAM adress + 0x20 PortSetPin(port, 0, 1);
мы можем программно поменять значение переменной port и вся программа будет использовать уже другой порт.
В таком случае программно нужно переключать не только регистр порта, а также DDR и PIN регистры, если вы хотите сделать этот приём универсальным. Сомнительное решение. Я понимаю, если портов было бы 20 штук, но для двух портов зачем это делать? Может проще явно работу с ними прописывать?
Да, кстати, я не проверял, но такая вещь тоже компилируется:
Код:
char port = PORTB; char pin = PINA; char b = 7;
ifCHECKBIT( pin, b )sbi(port, 1); elsecbi(port, 1);
В листинге ассемблера получается целая портянка для реализации этого кода, она по длине в 10 раз больше предыдущего варианта.
В листинге ассемблера получается целая портянка для реализации этого кода, она по длине в 10 раз больше предыдущего варианта.
ещёб конечно портянка не появилась бы между функцией написанной на С и макросом на АСМ
попробовал я ваш макрос любезнейший uni добавил се в исходник: #define CHECKBIT(x,y) ((x) & (1<<(y))) // чтение пина #define sbi(port, b) (port) |= (1 << (b)) // установка пина #define cbi(port, b) (port) &= ~(1 << (b))// сброс пина
и код для проверки: volatile char *pinBT = ((char*)0x36);//PINB SRAM adress + 0x20; if CHECKBIT( pinBT, 7 ) { // перепробовав разные варианты не компилится (( для проверки это }
пробовал и так: volatile char *pinBT = ((char*)0x36);//PINB SRAM adress + 0x20; if(CHECKBIT( pinBT, 7 )) // перепробовав разные варианты некомпилится (( пля проверки и это тоже }
не компилиться ошибка компилятора CodeVision 2.05.0 : declaration syntax error на строке: if CHECKBIT( pinBT, 7 ) { // и так тоже самая ошибка if(CHECKBIT( pinBT, 7 )) }
эту строку компилятор вообще отказался принять категорически!!!
Цитата:
char pin = PINB;
поэтому я её поменял на: volatile char *pinBT = ((char*)0x36);//PINB SRAM adress + 0x20; эту скушал молча
У меня нет макросов на ассемблере (это вообще выглядит по-другому). Мои определения называются препроцессорными определениями, они входят в стандарт языка C. Надо делать вот так:
ifCHECKBIT( * pin, b )cbi( * port, b ); elsesbi( * port, b );
delay_ms(1);
}
Использовать PORTA и PINA напрямую по всей видимости нельзя и у меня вообще-то пример был записан неправильно скорее всего. Доступ к регистрам через разыменование указателя в CodeVision возможен, хотя я бы не стал использовать такой способ, т.к. численные значения плохо поддаются отлову ошибок. Для того и придумывали идентификаторы, чтобы уйти от прямого указания цифр в коде. И да, в отличие о функции, макрос на C сразу вставляется в текст программы, поэтому здесь его использовать в таком виде не имеет смысла, т.к. он развёртывается в большой кусок кода на ассемблере. При частом обращении флеш мк быстро закончится.
unsigned char *pin = ( unsigned char * ) ( 0x19 + 0x20 ); char b = 1; if CHECKBIT( *pin, b ) { }
пишет ошибка на строке if CHECKBIT( * pin, b ) Error:......: declaration syntax error и так тоже не компилет: unsigned char *pin = ( unsigned char * ) ( 0x19 + 0x20 ); char b = 1; if (CHECKBIT( *pin, b )) { }
unsigned char *pin = ( unsigned char * ) ( 0x19 + 0x20 ); char b = 1; if CHECKBIT( pin, b ) { }
unsigned char *pin = ( unsigned char * ) ( 0x19 + 0x20 ); char b = 1; if (CHECKBIT( pin, b )) { }
всегда ругается : ошибка на строке if CHECKBIT( * pin, b ) в разных её вариантах!
Error:......: declaration syntax error
Цитата:
Использовать PORTA и PINA напрямую по всей видимости нельзя
Да в том и дело что можно и щас так оно и реализованно у меня что используются они явно
Цитата:
Может проще явно работу с ними прописывать?
так щас оно и есть! это можно но не желательно.
суть дела в чём:
сам себя цитирую
Цитата:
Задача функции такая. Есть у меня две функции одинаковые они полностью отличаются только они как раз что используют разные PIN и PORT. первая использует PIND.5 PIND.0 PINB.3 и PORTD.0 вторая использует PIND.0 PIND.5 PINB.4 и PORTD.5
одинаковые PINы используются в разных местах кода. Так вот для начала я хочу эти две функции объединить в одну, оптимизировать а нужные PINы и PORTы передавать ей в качестве параметров при вызове. или вот думаю можно так реализовать смену PINов в самой функции по команде через параметр void TestPort(int command) { port; // здесь мы объявили переменные для порта и пина, но какой ставить тип переменных ? pin;
if(command==1) { port = PORTB; // здесь мы присваиваем переменным номер порта и пина в зависимости от команды pin = PINB.5; }
if(pin)port=0; // работаем с переменными пора и пина else port=1;
}
вот так тоже делать пришла идея но как?
Вообще это устройство у меня стоит в авто уже года три назад я его сам собрал. его назначение это управление стёклами (стеклоподъёмник) и закрывает он их автоматически при постановке на сигнализацию. У меня там две функции есть одна управляет закрытием водительского окна , другая закрытием пассажирского окна, они одинаковые различаются только работой с разными пинами и портом. Поюзав это собственно ручно собранное замечательное устройство не один год и убедившись в его замечательной надёжности и нужности я решил сделать ему upgrade добавить дополнительно новые функции полезные и подключить его к блютузу. В частности планируется задействовать в алгоритме ещё и открывание окон (щас только закрыванием онных оно отвечает). Не писать же ещё две такие же функции на открывание поэтому я и решил написать одну функцию и в параметрах при вызове указывать ей какое окно открывать или закрывать. Вот в чём задумка!!! Я понимаю некоторые могут подумать и сказать типа пиши четыре функции одинаковых и иди пей пиво светлое, тёмное кому как нравиться на вкус и цвет товарищей нет. Яб мог конечно так сделать еслиб был пивным алкоголиком но я не из них! Мне кажется это логически неправильно так делать. Да и ресурсы у контроллера не безграничные!!! щас стоит ATTINY2313 новую реализацию планирую реализовать на ATMEGA8 а то чёт ног у 2313 не хватает мне чуть чуть
У меня CodeVision 2.05.0, как видно про снимку экрана, в Proteus всё работает. CHECKBIT() не обязательно брать в скобки, т.к. определение само содержит эти скобки. Когда я говорил о прямом использовании идентификаторов регистров ввода/вывода, то имел в виду такую конструкцию:
unsignedchar * port = ( unsignedchar * ) ( & PORTA ); unsignedchar * pin = ( unsignedchar * ) ( & PINA ); char b = 1;
CHECKBIT( * pin, b ) ? (cbi( * port, b )) : (sbi( * port, b ));
delay_ms(1);
}
У меня сначала почему-то не получилось такой вариант скомпилировать, но теперь это работает, т.е. лучше вместо цифр 0x20 + 0x19 использовать адрес & PINA. По сути это одно и то же, но второй вариант более понятен. На картинке ниже я прошагал до момента инициализации переменных pin и port, как видно, они имеют ожидаемые значения.
Заголовок сообщения: Re: Работа с портами в функциях. Порт как аргемент для функц
Добавлено: Вт окт 22, 2013 12:18:56
Первый раз сказал Мяу!
Зарегистрирован: Вс сен 25, 2011 09:40:47 Сообщений: 36
Рейтинг сообщения:0
ZiperRUS писал(а):
первая использует PIND.5 PIND.0 PINB.3 и PORTD.0 вторая использует PIND.0 PIND.5 PINB.4 и PORTD.5
одинаковые PINы используются в разных местах кода. Так вот для начала я хочу эти две функции объединить в одну, оптимизировать а нужные PINы и PORTы передавать ей в качестве параметров при вызове. или вот думаю можно так реалировать смену PINов в самой функции по команде через параметр, вот как то так:
void TestPort(int command) { port; // здесь мы объявили переменные для порта и пина, но какой ставить тип переменных ? pin;
if(command==1) { port = PORTB; // здесь мы присваиваем переменным номер порта и пина в зависимости от команды pin = PINB.5; }
if(pin)port=0; // работаем с переменными пора и пина else port=1;
Про макросы много где есть. И у нас тоже, если кто не видел. Но макросы это не функция и код генерируемый компилятором будет отличаться от способа с указателями.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Уважаемые программисты! Досталась недоделанная прошивка (AnMega16, CodeVisionAVR). Как правильно прописать, чтобы при включении питания устанавливались эти условия:
ZiperRUS, во-первых, цитировать предыдущее сообщение полностью - не по правилам этого форума. Смотрите, а то получите оплеуху от модераторов. Во-вторых, если просто вставить код приведённый variaevg в то место куда вы указали - компилятор скажет вам куда идти что он думает о таком стиле написания кода. Или мы говорим на разных языках.
variaevg, код надо вставлять в самое начало функции main, или в то место где закончилась инициализация всего что надо для приведённого вами фрагмента кода. Как-то так. Точнее знать только вам.
Код:
voidmain(void) { // инициализация
// вставлять сюда
// прочая инициализация // основной цикл }
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Большое спасибо всем неравнодушным! Наберусь нахальства об еще одной просьбе:
В программе такая запись (фрагмент).
При переходе входа in_cc с 1 в 0, на выходе out_buz формируется положительный импульс длительностью 5 сек. Формируется однократно. Подскажите пожалуйста, как сделать чтобы импульс был при каждом переходе с 1 в 0? В процессе работы эта ситуация возникает неоднократно.
Заголовок сообщения: Re: Работа с портами в функциях. Порт как аргемент для функц
Добавлено: Чт авг 10, 2023 13:11:45
Открыл глаза
Карма: 3
Рейтинг сообщений: 0
Зарегистрирован: Вт сен 27, 2011 07:28:44 Сообщений: 59 Откуда: Москва
Рейтинг сообщения:0
Народ, а как сделать на gcc?
Код:
voidbuzz_n_blink(uint16_t duration, uint8_t quantity, uint16_t pause, uint8_t pin) { // аргументы: длительность, количество, пауза (2-я длительность), нога for (uint8_t i=0; i < quantity; i++) // количество оборотов цикла опеределено в quantity { PORTA |=(1<<pin); // поднимаем ногу loopdelay(duration); // вызываем задержку PORTA &=~(1<<pin); // опускаем ногу if (pause >= 1) loopdelay(pause); // если аргумент pause больше или равен единице, то запускаем второй таймер } }
В pin подставляется PORTAn. Но работает как-то не так все это... Еще мне хотелось бы добавить работу с PORTB, я вижу это так, но ничего не работает:
Код:
voidbuzz_n_blink(uint16_t duration, uint8_t quantity, uint16_t pause, uint8_t pin) { // аргументы: длительность, количество, пауза (2-я длительность), нога for (uint8_t i=0; i < quantity; i++) // количество оборотов цикла опеределено в quantity { if (pin == PORTB) PORTB |=(1<<pin); else PORTA |=(1<<pin); // поднимаем ногу loopdelay(duration); // вызываем задержку if (pin == PORTB) PORTB &=~(1<<pin); else PORTA &=~(1<<pin); // опускаем ногу if (pause >= 1) loopdelay(pause); // если аргумент pause больше или равен единице, то запускаем второй таймер } }
_________________ ИзвЕните от слова - веник, ИзвИните от слова - вина.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения