Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Тонкости работы с LPC2xxx
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
GetSmart
Для начала, кто знает как инвертировать пин P0.31 на процах LPC213x ?
alexander55
Цитата(GetSmart @ Nov 15 2007, 13:11) *

Как вариант.
#define LED3_ON (IO0CLR_bit.P0_31 = 1)
#define LED3_OFF (IO0SET_bit.P0_31 = 1)
#define Test_LED3 (IO0PIN_bit.P0_31)

if(Test_LED3) LED3_ON ;
else LED3_OFF;
etoja
P0.31 -только на вывод.

Как писал DASM
(http://electronix.ru/forum/index.php?showtopic=38750&pid=317363&mode=threaded&show=&st=0&#entry317363)

"Битиком нельзя вот почему. на P0-31 если без транзистора включить подтягивающий резистор, то на нем будет низкий уровень при сбросе устройства, а это делать нельзя ибо "Note: This pin MUST NOT be externally pulled LOW when RESET pin is LOW or the
JTAG port will be disabled." Это ис хождения по собственным граблям. Про остальное не скажу"
GetSmart
Цитата(etoja)
P0.31 -только на вывод.
Дык я знаю, что только на вывод. А разве действие "инвертировать" можно применять на вход?!? И на землю его подтягивать я не собираюсь.

Например в одной из схем я догадался повесить на этот пин светодиод, второй пин светодиода при этом подключён к питанию. Такое включение 100% надёжно и не надо тут "мутить воду". Так вот, прошу написать тут самый простой и красивый способ инверсии пина P0.31. Тот, что написал alexander55 - нерабочий! smile.gif
alexander55
Цитата(GetSmart @ Nov 15 2007, 14:05) *
Тот, что написал alexander55 - нерабочий! smile.gif

Надеюсь, Вы не забыли добавить для инициализации
IO0DIR_bit.P0_31 = 1; //Init LED3 as output
GetSmart
Цитата(alexander55)
#define Test_LED3 (IO0PIN_bit.P0_31)
Конкретно вот эта строчка нерабочая.

Просто для информации. Я знаю как инвертировать.
Мне интересно знает ли кто ещё. Особенно zltigo smile.gif
alexander55
Цитата(GetSmart @ Nov 15 2007, 14:53) *
Конкретно вот эта строчка нерабочая.

Я работаю с LPC2148. Это работает без проблем.

Цитата(GetSmart @ Nov 15 2007, 14:53) *
Я знаю как инвертировать.
Мне интересно знает ли кто ещё. Особенно zltigo smile.gif

Я тоже знаю еще способы, но предложенный мне нравится больше всего.
tyro
Цитата(GetSmart @ Nov 15 2007, 14:53) *
Конкретно вот эта строчка нерабочая.
Просто для информации. Я знаю как инвертировать.
Мне интересно знает ли кто ещё. Особенно zltigo smile.gif

Цитата(alexander55 @ Nov 15 2007, 15:06) *
Я работаю с LPC2148. Это работает без проблем.
Я тоже знаю еще способы, но предложенный мне нравится больше всего.

Поскольку все знаем, но не хотим делиться, а хотим узнать кто еще знает... то может перенести эту тему в Offtopics ?
GetSmart
Цитата(alexander55)
Я работаю с LPC2148. Это работает без проблем.
Возможно это работает только в новых ревизиях.
Цитата
Я тоже знаю еще способы...
Можете написать? Особенно если они короче уже написанного.

Цитата(tyro)
Поскольку все знаем, но не хотим делиться, а хотим узнать кто еще знает... то может перенести эту тему в Offtopics ?
Хотим smile.gif
Щас узнаю что другие знают и напишу сам.
Буду тут выкладывать полезную информацию. Причём тут Offtopics ?
tyro
Цитата(GetSmart @ Nov 15 2007, 15:19) *
Возможно это работает только в новых ревизиях.
Можете написать? Особенно если они короче уже написанного.

Хотим smile.gif
Щас узнаю что другие знают и напишу сам.
Буду тут выкладывать полезную информацию. Причём тут Offtopics ?

Поскольку в сообщениях нет намека на исходно поставленный вопрос. smile.gif
Для Offtopics добавлю: поставить за ножкой инвертор. smile.gif
Сергей Борщ
Цитата(GetSmart @ Nov 15 2007, 13:53) *
Просто для информации. Я знаю как инвертировать.
Мне интересно знает ли кто ещё. Особенно zltigo smile.gif
Для 2214 я использую конструкцию IO0PIN ^= (1UL << 31); Не смотрел даташит на 213х, но не думаю, что там сильно что-то поменяли. Или конкретно с 0.31 есть подводный камень?
GetSmart
Цитата(Сергей Борщ)
Или конкретно с 0.31 есть подводный камень?
Именно!

Цитата(tyro)
Для Offtopics добавлю: поставить за ножкой инвертор.
Вопрос - как программно инвертировать. (много раз)

Хотя сам способ инверсии универсальный (для любого порта и пина).
alexander55
Цитата(Сергей Борщ @ Nov 15 2007, 15:25) *
Для 2214 я использую конструкцию IO0PIN ^= (1UL << 31); Не смотрел даташит на 213х, но не думаю, что там сильно что-то поменяли. Или конкретно с 0.31 есть подводный камень?

Я подумал, чтобы расставить точки на И, надо, наверное, указать компилятор. Я использую IAR 5.10.
abcdefg
Да вроде как мы с вами уже обсуждали smile.gif
http://electronix.ru/forum/index.php?showtopic=32375

в моем случае - дублирую состояние в отдельной переменной.
GetSmart
Блин, точно! И я там был...
Но появились новые сведения. Оказывается ничего плохого в этом пине нет. И вааще, правильнее инвертировать все пины так, как я скоро напишу smile.gif Ждёмс...
alexander55
Цитата(GetSmart @ Nov 15 2007, 16:38) *
Блин, точно! И я там был...
Но появились новые сведения. Оказывается ничего плохого в этом пине нет. И вааще, правильнее инвертировать все пины так, как я скоро напишу smile.gif Ждёмс...

А чего, собственно, ждемс ? Новую еррату или еще что-то ?
Сергей Борщ
Цитата(GetSmart @ Nov 15 2007, 15:38) *
Но появились новые сведения.
Выкладывайте ваши карты. Я скачал узер мануал и внимательно прочитал раздел про порты, хотя с 213х не работаю и пока не планирую. Ничего особенного про 0.31 там нет. Более того:
Цитата
Bit 0 in IO1PIN corresponds to P1.0 ... Bit 31 in IO1PIN corresponds to P1.31
.......
Following code will preserve existing output on PORT0 pins P0.[31:16] and P0.[7:0] and at the same time set P0.[15:8] to 0xA5, regardless of the previous value of pins P0.[15:8]:
IO0PIN = (IO0PIN && #0xFFFF00FF) || #0x0000A500
Скачал эррату. Там тоже ничего про эту ногу нет. Эррата датирована июлем - если бы особенности были, их бы с тех пор успели найти и описать. Поэтому я не понимаю, почему IO0PIN ^= (1U << 31); может не работать и почему, скажем, IO0PIN ^= (1U << 20); может испортить 31 бит. Не томите wink.gif
GetSmart
Цитата(Сергей Борщ)
IO0PIN = (IO0PIN && #0xFFFF00FF) || #0x0000A500
Ну если они в этом выражении умудрились столько ошибок наставить, то неудивительно, что про особенность P0.31 в попыхах забыли.

Ведь не только я вставал на эти грабли. Другие подтвердят. При чтении из IOPIN0 старший бит всегда читается установленным.
Сергей Борщ
Цитата(GetSmart @ Nov 15 2007, 17:20) *
Ведь не только я вставал на эти грабли. Другие подтвердят. При чтении из IOPIN0 старший бит всегда читается установленным.
Хорошо, поверю на слово. Тогда надо читать IO0SET. IO0PIN = IO0SET ^ (1U<<31 );
или IO0SET & (1U<<31 ) ? IO0CLR = (1U<<31 ) : IO0SET = (1U<<31 );
или развивая тему (signed int)IO0SET < 0 ? IO0CLR = (1U<<31 ) : IO0SET = (1U<<31 );
klen
Потетики много. Предлагаю уточнить задачу. КАК на АСМЕ это сделать. команды иныерсии бита в наборе инструкций отсутствуют sad.gif , после того как разберемся будет понятно как на С это коротко сделать.

могли б уже производители добавить к IOPIN IOCLR IOSET еще регистр IOTGL - для переворачивания битов wink.gif этож не проц а переферия - лицензии платить никому не нада
GetSmart
Цитата(Сергей Борщ)
Тогда IO0PIN = ( IO0PIN & ~(1U << 31) ) | ( IO0CLR & (1U<<31 ));
Орригинально smile.gif Однако неправильно. Тем более, что IO0CLR Write Only!

Щас, подождём zltigo и произойдёт чудо smile.gif

Цитата(Сергей Борщ)
Тогда надо читать IO0SET. IO0PIN = IO0SET ^ (1U<<31);
Вот именно!!!
Там хранится реально выводимое значение порта, даже если какой-либо пин в данный момент сделан входом. Это значит если на лету переключить пин на вывод, то именно значение из IOxSET появится на этом выходном пине.

Короче, это самый простой и правильный метод инверсии выходных пинов. Вне зависимости от того, на вход или выход и на какую альтернативную функцию в данный момент пин настроен.
klen
Пока что умнее чем
#define LED_TOGGLE() \
IO1PIN & (1<<LINK_LED_IOPIN) ? (IO1CLR = (1<<LINK_LED_IOPIN)) : (IO1SET = (1<<LINK_LED_IOPIN));
не придумал

вот код который генерится:

ldr r2, [pc, #72] ; 0x2f8 <main+152>
ldr r3, [r2, #16]
tst r3, #16777216 ; 0x1000000
movne r3, #16777216 ; 0x1000000
moveq r3, #16777216 ; 0x1000000
strne r3, [r2, #28]
streq r3, [r2, #20]

м
GetSmart
Цитата(klen)
IO1PIN & (1<<LINK_LED_IOPIN) ? (IO1CLR = (1<<LINK_LED_IOPIN)) : (IO1SET = (1<<LINK_LED_IOPIN));
Скажем так, по условию задачи нельзя читать текущее состояние из IOxPIN. Для P0.31 это так на самом деле.

А самый короткий способ как на Си, так и на АSMе я уже написал:
IOxPIN = IOxSET ^ (1U<<n);

ЗЫ: Меня всегда интересовало почему IOxSET для чтения/записи, а IOxCLR только для записи. И недавно я это выяснил smile.gif Теперь всё встало на свои места!
Сергей Борщ
Цитата(GetSmart @ Nov 15 2007, 17:53) *
Там хранится реально выводимое значение порта, даже если какой-либо пин в данный момент сделан входом. Это значит если на лету переключить пин на вывод, то именно значение из IOxSET появится на этом выходном пине.
Да, познавательно. Спасибо! Полез редактировать свои макросы.
alexander55
Цитата(GetSmart @ Nov 15 2007, 20:20) *
ЗЫ: Меня всегда интересовало почему IOxSET для чтения/записи, а IOxCLR только для записи. И недавно я это выяснил smile.gif Теперь всё встало на свои места!

Да, это нюанс, который проясняет назначение IOxSET для чтения. Спасибо. a14.gif
Я подумаю над изменением
#define Test_LED3 (IO0PIN_bit.P0_31)
на
#define Test_LED3 (IO0SET_bit.P0_31)


Но теперь остается еще нюансы с IOxPIN.
Я так понимаю.
Если биты порта сконфигурированы как GPIO (я подчеркиваю это), то IOxPIN в этих битах указывает состояние на самих пинах.
Т.е. если бит сконфигурирован как выход, то состояние выхода.
Если бит сконфигурирован как вход, то состояние входа.
Теперь объясните мне, за что сражались. biggrin.gif

Цитата(Сергей Борщ @ Nov 16 2007, 03:34) *
Да, познавательно. Спасибо! Полез редактировать свои макросы.

Зачем так спешить.

Цитата(alexander55 @ Nov 16 2007, 08:46) *
Я подумаю над изменением
#define Test_LED3 (IO0PIN_bit.P0_31)
на
#define Test_LED3 (IO0SET_bit.P0_31)

Проверил, работают аналогично.
Что лучше реальное состояние выхода или записанное - вопрос, конечно, интересный. biggrin.gif
GetSmart
Цитата(alexander55 @ Nov 16 2007, 11:36) *
Но теперь остается еще нюансы с IOxPIN.
Я так понимаю.
Если биты порта сконфигурированы как GPIO (я подчеркиваю это), то IOxPIN в этих битах указывает состояние на самих пинах.
Т.е. если бит сконфигурирован как выход, то состояние выхода.
Если бит сконфигурирован как вход, то состояние входа.
Теперь объясните мне, за что сражались. biggrin.gif
Уже написал. Повторяю для особо невнимательных:
В процессоре LPC213x при чтении IO0PIN старший бит читается установленным ВСЕГДА!!!
Поэтому любая конструкция типа IO0PIN ^= (1<<N) разрушит содержимое этого пина, а точнее установит на нём еденицу.
Для LPC214x не проверял, особенно в старых ревизиях.
alexander55
Цитата(GetSmart @ Nov 16 2007, 11:37) *
В процессоре LPC213x при чтении IO0PIN старший бит читается установленным ВСЕГДА!!!

Да, это любопытно. Возьмем на заметку, спасибо.
GetSmart
Оказывается аналогичная ситуация с и с другими регистрами, в которых используется пара функций SET / CLR. Например VICIntEnable / VICIntEnClr и VICSoftInt / VICSoftIntClear. Из VICIntEnable и VICSoftInt можно читать всю карту разрешённых/установленных прерываний, а запись значения может только устанавливать биты, но не сбрасывать.
alexander55
Цитата(GetSmart @ Nov 23 2007, 18:07) *
Оказывается аналогичная ситуация с и с другими регистрами, в которых используется пара функций SET / CLR. Например VICIntEnable / VICIntEnClr и VICSoftInt / VICSoftIntClear. Из VICIntEnable и VICSoftInt можно читать всю карту разрешённых/установленных прерываний, а запись значения может только устанавливать биты, но не сбрасывать.

Это очень логично с точки зрения унификации.
Хотя, для портовых регистров возможность чтения по актуальности намного выше.
Инверсии выходов используются для организации частотных выходов (это используется достаточно часто).
PS. GetSmart, спасибо за Ваши исследования (никогда не знаешь, что может понадобиться со временем). Я за четкость понимания, особенно, если производитель что-то не договаривает.
Alex03
Не знаю что вы тут с GPIO нового нашли. У меня ещё в древнем мануале на 2114/.../2214 написано:
Цитата
GPIO Output Set Register
(IO0SET - 0xE0028004, IO1SET - 0xE0028014, IO2SET - 0xE0028024, IO3SET - 0xE0028034)
This register is used to produce a HIGH level output at the port pins if they are configured as GPIO in an OUTPUT mode. Writing
1 produces a HIGH level at the corresponding port pins. Writing 0 has no effect. If any pin is configured as an input or a secondary
function, writing to IOSET has no effect.
Reading the IOSET register returns the value of this register, as determined by previous writes to IOSET and IOCLR (or IOPIN as noted above). This value does not reflect the effect of any outside world influence on the I/O pins.


Цитата
Applications that require instanatneous appearance of zeros and ones on the respected parallel port can use direct access to port’s corresponding GPIO Pin Value Register (IOPIN).
Assuming that pins P0.8 to P0.15 are configured as output, write to IO0PIN:
IO0PIN = 0x0000 C700
will produce the same output as following sequence of writes:
IO0SET = 0x0000 C700
IO0CLR = 0x0000 3800
Solution utilizing access to IO0SET and IO0CLR will take more steps compared to a single IO0PIN write access.


Хотя тамже IO0PIN и указан как RO.

Другими словами:
Чтение IOхPIN читает реальное состояние пинов, например для сконфигурённого на выход пина с установленным в нём нулём, из IOхPIN можно прочитать единицу если этот порт сильно нагружен, например сильноточным светодиодом. (ни в коей мере не призываю выходить за границы дозволеных токов.)
Чтение IOxSET читает то что задумывалось программерами на выход. (даже если пин сконфигурён как вход).
Запись в IOxPIN - есть параллельная запись всего порта.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.