Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: #define - как применить правильно ?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Shurmas
прошу совета.

Мне нужно управлять (подавать "1" или "0") 6-ю приборами с 6 ног мега16.

Хочу чтоб в верху программы были дефайны типа

#define PRIBOR(1) (тут порт и номер ноги к которой подключен)
и так 6 строчек. Но не могу понять что там писать ? Ведь нужна возможность писать и разные порты. И как потом в программе управлять DDR - хотя бы раз чтоб сделать соотв. ножки выходами ?
если я в дефайнах пропишу PORTx.x то как управлять DDRx ? или только 12 дефайнами решается ?

Компилер IAR или WinAVR но можно и под другой.

в идеале нужно чтоб можно бы так управлять

PRIBOR(переменная номер нужного прибора) = 1;
// выдать "1" на прибор номер как значение переменной.


PRIBOR(переменная номер нужного прибора) = OUT ;
// включить на выход ножку к прибору номер как значение переменной.

это возможно ? не могу придумать как.

Подскажите пожалуйста.
rezident
Как я понял вам нужно выполнять не одну операцию, а несколько, поэтому лучше оформить это как функцию с передачей номера прибора и типа действия в качестве параметров. Это будет проще и доступнее для восприятия, чем супернавороченный макрос.
Если же вам "ни в жить" именно с помощью define нужно обозначить, то см. главу "А12.3. Макроопределение и макрорасширение" в книге K&R.
Shurmas
мне в принципе все равно как, но хочется чтоб гдето в начале можно было компактно переназначить выводы МК для приборов.

я и подумал про дефайн. Как например определяют какой то параметр, а потом легко его меняют в одном месте а не по всей програме.
rezident
Цитата(Shurmas @ Aug 18 2006, 00:07) *
мне в принципе все равно как, но хочется чтоб гдето в начале можно было компактно переназначить выводы МК для приборов.

я и подумал про дефайн. Как например определяют какой то параметр, а потом легко его меняют в одном месте а не по всей програме.

Дык обозначить пины это нормально, но ведь вам, как я понял, нужны макросы управления этими "ножками", а не просто их символьные обозначения? Это уже функция получается, будь она inline-функцией или обычной.
P.S. вы бы уточнили эти пины относятся к одному порту или к разным?
spf
Цитата(Shurmas @ Aug 18 2006, 00:07) *
мне в принципе все равно как, но хочется чтоб гдето в начале можно было компактно переназначить выводы МК для приборов.

я и подумал про дефайн. Как например определяют какой то параметр, а потом легко его меняют в одном месте а не по всей програме.

Глянь pin_macros (for MB90xxx). Надо что-то типа этого?
Где-то ходит вариант и для AVR.

Определяешь нужные пины и работаешь через макросы при прямых операциях. Если необходимо обращение через "переменную" то придется оформить функцию со switch...
AVR
Цитата(Shurmas @ Aug 17 2006, 18:58) *
Мне нужно управлять (подавать "1" или "0") 6-ю приборами с 6 ног мега16.
Хочу чтоб в верху программы были дефайны типа
#define PRIBOR(1) (тут порт и номер ноги к которой подключен)
и так 6 строчек. Но не могу понять что там писать ? Ведь нужна возможность писать и разные порты

Вроде так:
Код
#define PRIBOR(Port, N, V) \
{ \
  *(Port - 1) |= (1<<N); \ //Делаем выходом вывод порта
  if(V) Port |= (1<<N); \ //Устанавливаем в V (1 или 0) соотвествующий вывод
  else Port &= ~(1<<N); \
}
//Далее
#define S1 PRIBOR(PORTA, 2, 1)
#define C1 PRIBOR(PORTA, 2, 0)
_Bill
Цитата(Shurmas @ Aug 17 2006, 21:07) *
мне в принципе все равно как, но хочется чтоб гдето в начале можно было компактно переназначить выводы МК для приборов.

я и подумал про дефайн. Как например определяют какой то параметр, а потом легко его меняют в одном месте а не по всей програме.

В общем, правильно подумали. Я, например, так делаю:
Код
//
// LCD port and bit definitions
//
#define        LCD_DATA         PORTA        // PORTA is LCD data port
#define        LCD_CTRL         PORTA        // PORTA is LCD control port
#define        DATA_MASK        0xF0         // Data have to be at high nibble
#define        LCD_E            (1<<2)       // LCD E control signal
#define        LCD_RS           (1<<1)       // LCD RS control signal
Terminator
Где-то видел красивый макрос для IAR, но уже на найду sad.gif
Для gcc делал следующим образом:
Написал "прогу" для awk которая из файла с описаниями типа
LED_R A 1 1
генерила .h с кучей #define на все случаи жизни, типа
#define LED_R_HIGH (PORTA |= _BV(1))
#define LED_R_LOW (PORTA &= ~_BV(1))
и т.п.
AlexOr
Можно так.
Evgeny_CD
Для генерации таких вещей COG идеально подходит
http://www.nedbatchelder.com/code/cog/index_ru.html
http://www.onembedding.com/articles/cog-n-make/
http://www.onembedding.com/articles/cog-n-make/examples.htm
Дон Амброзио
Подскажите по использованию препроцессорной директиве #define в AVR Studio в программе на АССЕМБЛЕРЕ при использовании её не для определения константы, а для определения макроса-функции.

В общем виде определение препроцессорного макроса-функции выглядит так: #define prepMacrosName (список аргументов) (определение функции)

Вопрос №1

В хелпе приводиться такой пример:
#define SQR(X) ((X)*(X))

Т.е. если я вызову

ldi ZL , low SQR(17)

, то компилятор вместо SQR(17) напишет"

ldi ZL , low ((17) x (17)) или ldi ZL , low (289) ???

Вопрос №2

Обязательно ли в качестве аргументов "функции" макроса числовые переменные? Или можно и куски текстовых строк?
Могу ли я например использовать такой макрос:
#define Command (InstructionType) (InstructionType)

в строке программы

Command (and)i R16 , 0b01001000 // эквивалетно andi R16, 0b01001000
Command (or)i R16 , 0b01001110 // эквивалетно ori R16, 0b01001110


Замечание: как это сделано в СИ-компиляторах НЕ ИНТЕРЕСУЕТ. Интересует как это сделано для ассемблера в AVR Studio
Дон Амброзио
Цитата(Дон Амброзио @ Mar 9 2008, 14:11) *
Вопрос №2

Обязательно ли в качестве аргументов "функции" макроса числовые переменные? Или можно и куски текстовых строк?
Могу ли я например использовать такой макрос:
#define Command (InstructionType) (InstructionType)

в строке программы

Command (and)i R16 , 0b01001000 // эквивалетно andi R16, 0b01001000
Command (or)i R16 , 0b01001110 // эквивалетно ori R16, 0b01001110
Замечание: как это сделано в СИ-компиляторах НЕ ИНТЕРЕСУЕТ. Интересует как это сделано для ассемблера в AVR Studio


Проблему решил. Кому интересно посмотрите в Хэлпе AVR Studio. Ключевые слова «Stringification» и «Concatenation»
Цыкетчик
Цитата(Shurmas @ Aug 17 2006, 18:58) *
прошу совета.

Мне нужно управлять (подавать "1" или "0") 6-ю приборами с 6 ног мега16.

Хочу чтоб в верху программы были дефайны типа

#define PRIBOR(1) (тут порт и номер ноги к которой подключен)
и так 6 строчек. Но не могу понять что там писать ? Ведь нужна возможность писать и разные порты. И как потом в программе управлять DDR - хотя бы раз чтоб сделать соотв. ножки выходами ?
если я в дефайнах пропишу PORTx.x то как управлять DDRx ? или только 12 дефайнами решается ?

Компилер IAR или WinAVR но можно и под другой.

в идеале нужно чтоб можно бы так управлять

PRIBOR(переменная номер нужного прибора) = 1;
// выдать "1" на прибор номер как значение переменной.
PRIBOR(переменная номер нужного прибора) = OUT ;
// включить на выход ножку к прибору номер как значение переменной.

это возможно ? не могу придумать как.

Подскажите пожалуйста.

Тут лучше использовать не препроцессорные, а обычные макросы.
Примерно так biggrin.gif
.macro Pribor
; Пример для ATmega128 у которой некоторые регистры управления портами
; расположены в пространстве дополнительных РВВ
; Номера разрядов и имена портов взяты произвольно (так как автор темы не указал их)
; @0 - номер прибора
; @1 - требуемое состояние пина, управляющего прибором

.if @0 > 6
.error "Ошибка: номер прибора больше 6-ти."
.endif

.if @0 == 1
.set Number_of_Digit = 6
.set DDR_Addres = DDRF
.set PORT_Addres = PORTF
.endif

.if @0 == 2
.set Number_of_Digit = 3
.set DDR_Addres = DDRF
.set PORT_Addres = PORTF
.endif

.if @0 == 3
.set Number_of_Digit = 5
.set DDR_Addres = PORTF
.set PORT_Addres = PORTF
.endif

.if @0 == 4
.set Number_of_Digit = 0
.set DDR_Addres = DDRD + $20
.set PORT_Addres = PORTD + $20
.endif

.if @0 == 5
.set Number_of_Digit = 4
.set DDR_Addres = DDRD + $20
.set PORT_Addres = PORTD + $20
.endif

.if @0 == 6
.set Number_of_Digit = 1
.set DDR_Addres = DDRD + $20
.set PORT_Addres = PORTD + $20
.endif

; Запрограммировать пин на вывод
lds R16 , DDR_Addres
sbr R16 , ( 1 << Number_of_Digit )
sts DDR_Addres , R16

; Установить нужный логический уровень на пине
lds R16 , PORT_Addres
.if @1 = 0
cbr R16 , ( 1 << Number_of_Digit ) ; Выставили '0' на пине
.else
sbr R16 , ( 1 << Number_of_Digit ) ; Выставили '1' на пине
.endif
sts PORT_Addres , R16

.endmacro

.........................
.........................
.........................

; Установить '1' на пине, управляющем прибором №3
Pribor 3, 1

.........................
.........................
; Установить '0' на пине, управляющем прибором №6
Pribor 6, 0
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.