Ардуино IDE. Как использовать метки в макросе?

Это Arduino Uno. Я часами читал в Интернете, но пока ничего не нашел. Если вы используете метку в макросе, при втором вызове вы получите ошибку дублирования метки.

, 👍0

Обсуждение

Пожалуйста, предоставьте свой код и точное сообщение об ошибке и опишите, чего вы пытаетесь достичь., @chrisl

Я предлагаю использовать только [локальные метки](https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels-1) в макросах сборки., @Edgar Bonet

Это aduino uno ... нет, это не так ... проблема, которую вы описываете, не имеет ничего общего с типом arduino., @jsotola

Большое спасибо Эдгар Боне. Местные лейблы - это именно то, что я искал., @John McDonald


2 ответа


-1

Добро пожаловать, это та же самая проблема, с которой я столкнулся несколько лет назад. Определите метку в макросе (функция), и она будет локальной и недоступной для остального мира. Вы можете использовать одну и ту же метку столько раз, сколько захотите, просто она должна быть внутри макроса.

void macro(int label) 
{ 
   Do something with label and then exit;
} 

Вы можете делать все, что хотите, например, получить значение нескольких контактов, чтобы увидеть, все ли они включены, а затем использовать возврат true или false. Когда вы покинете макрос, все переменные будут потеряны, а память вернется в кучу. Во многих библиотеках это делается несколькими способами.

,

Вопрос касается использования меток в макросах сборки, а не использования переменных в функциях C++., @Edgar Bonet


2

Чтобы прояснить вопрос, давайте рассмотрим простой пример. Учитывать следующий макрос сборки, реализующий цикл задержки:

.macro short_delay
    clr  r0
repeat:
    dec  r0
    brne repeat
.endm

и использовать его в программе, которая многократно мигает встроенным светодиодом Arduino Uno (более быстрая версия «Blink»):

main:
    sbi  DDRB, PB5   ; set pin 13 = PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    short_delay
    cbi  PORTB, PB5  ; turn PB5 LOW
    short_delay
    rjmp loop

Когда ассемблер разворачивает макрос, получается следующее:

main:
    sbi  DDRB, PB5   ; set PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    cbi  PORTB, PB5  ; turn PB5 LOW
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    rjmp loop

и это не работает с

Error: symbol `repeat' is already defined

Решение этой проблемы заключается в использовании внутри макроса только local ярлыки. Эти метки — просто цифры. При их использовании необходимо добавить суффикс «b» (для обратного) или «f» (для прямого) в зависимости от определена ли метка до или после точки, в которой она находится ссылка.

Локальные ярлыки хороши тем, что они... ну... местные и таким образом, их можно безопасно использовать повторно много раз. Ассемблер устраняет неоднозначность их, выбрав определение, которое ближе к месту использования, по указанному направлению. С локальной меткой (я выбираю 0) Макрос задержки становится:

.macro short_delay
    clr  r0
0:  dec  r0
    brne 0b  ; целью ветки является предыдущая метка `0'
.endm

Когда макрос раскрывается, основная программа становится:

main:
    sbi  DDRB, PB5   ; установить PB5 в качестве выхода
loop:
    sbi  PORTB, PB5  ; включить PB5 HIGH
    clr  r0
0:  dec  r0
    brne 0b
    cbi  PORTB, PB5  ; повернуть PB5 LOW
    clr  r0
0:  dec  r0
    brne 0b
    rjmp loop

Хотя метка повторяется, она не является двусмысленной, так как brne 0b всегда относится к ближайшей метке 0 в направлении bназад.

,