|
|
  |
Сбылась мечта идиота - приехали программатор и SAM7S256, Теперь нужен ликбез. |
|
|
|
May 13 2010, 07:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(zheka @ May 13 2010, 09:57)  В АВР было просто - PORTA.1=1, либо PORTA.1=0; Тяжелое наследие CVAVR. В стандартном С нет записи вида Var.Bit Макросы имени Аскольда Волкова спрячут реализацию - что на AVR, что на ARM, что на PIC, что на MSP: on(LED); off(LED); Цитата(zheka @ May 13 2010, 09:57)  Объясните, если я пишу в CODR, то в SODR автоматом меняется значение и наоборот? Нет. Из SODR читать вообще нельзя. Для чтения состояния там соседний регистр. Логику вы поняли правильно. Цитата(zheka @ May 12 2010, 21:00)  То есть Вашмим словами - ULINK это не название программатора? Название программатора. Но ведь никто не запрещает этим же названием назвать совокупность значений опций среды, необходимых для сборки и отладки проекта именно этим программатором
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 07:38
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(zheka @ May 13 2010, 10:57)  Как же все-таки сложно переделывать заложенные в голове азбучные истины. В АВР было просто - PORTA.1=1, либо PORTA.1=0; В ARM же CODR, SODR. Объясните, если я пишу в CODR, то в SODR автоматом меняется значение и наоборот? У меня складывается ассоциация как с кнопками - в АВР одна кнопка которую можно либо нажать либо отжать, а в SAM7 - две кнопки, из которых одновременно может быть нажата только одна, при нажатии одной, вторая автоматом отщелкивается. Я правильно понял логику работы пина? Вы полагаете, это плохо, что в ARM кроме записи слова в регистр аппаратно реализованы так же и установка отдельных битов регистра в 1, установка отдельных битов регистра в 0 и побитовая адресация регистров? Вам эти расширенные возможности обращения с регистрами мешают?
|
|
|
|
|
May 13 2010, 07:49
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата(zheka @ May 13 2010, 10:57)  Как же все-таки сложно переделывать заложенные в голове азбучные истины. В АВР было просто - PORTA.1=1, либо PORTA.1=0; В ARM же CODR, SODR. Объясните, если я пишу в CODR, то в SODR автоматом меняется значение и наоборот? У меня складывается ассоциация как с кнопками - в АВР одна кнопка которую можно либо нажать либо отжать, а в SAM7 - две кнопки, из которых одновременно может быть нажата только одна, при нажатии одной, вторая автоматом отщелкивается. Я правильно понял логику работы пина? А мне очень понравилось это расширение от привычной по AVR схемы. Вот как выглядят привычные подпрогаммы выдачи полубайтов: Код #define LCD_TARGET_PORT_S (AT91C_BASE_PIOA->PIO_SODR) #define LCD_TARGET_PORT_C (AT91C_BASE_PIOA->PIO_CODR)
#define LCD_DIRECTION_PORT_S (AT91C_BASE_PIOA->PIO_OER) #define LCD_DIRECTION_PORT_C (AT91C_BASE_PIOA->PIO_ODR) #define LCD_INPUT_PORT (AT91C_BASE_PIOA->PIO_PDSR) // was PINA
#define STROBE_BIT AT91C_PIO_PA31 #define WRITEE_BIT AT91C_PIO_PA1 #define ADDRES_BIT AT91C_PIO_PA0 #define DATAS_BITS (AT91C_PIO_PA26 | AT91C_PIO_PA25 | AT91C_PIO_PA24 | AT91C_PIO_PA23) #define DATA_BIT_LOW 23 // какой бит данных младшй в слове считанном с порта
// sent four bits from d7..d4 of argument v static void ws1602_send4_high(uint_fast8_t v) { LCD_TARGET_PORT_S = (v << (DATA_BIT_LOW - 4)) & DATAS_BITS; LCD_TARGET_PORT_C = ~ (v << (DATA_BIT_LOW - 4)) & DATAS_BITS; }
// send four bits from d3..d0 of argument v static void ws1602_send4_low(uint_fast8_t v) { LCD_TARGET_PORT_S = (v << (DATA_BIT_LOW - 0)) & DATAS_BITS; LCD_TARGET_PORT_C = ~ (v << (DATA_BIT_LOW - 0)) & DATAS_BITS; }
static uint_least8_t ws1602_pulse_strobe(void) { uint_fast8_t v;
LCD_TARGET_PORT_S = STROBE_BIT; // activate EN signal ws1602_delay(); v = (LCD_INPUT_PORT & DATAS_BITS) >> DATA_BIT_LOW; LCD_TARGET_PORT_C = STROBE_BIT; // deactivate EN signal ws1602_delay(); return v; }
Сообщение отредактировал Genadi Zawidowski - May 13 2010, 07:54
|
|
|
|
|
May 13 2010, 08:17
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Цитата Нет. Из SODR читать вообще нельзя. Для чтения состояния там соседний регистр. Логику вы поняли правильно. Я понимаю, что читать нельзя, читаю не я, а логическая схема порта, которая определяет будет ли на вызоде ноль или единица. Под соседним регистром вы имеете ввиду ODSR? Цитата Вы полагаете, это плохо, Я понимаю, что более гибкий доступ к функциям камня это хорошо, мне непонятно, почему так сделано. Ведь в любом слчуае выполняется оперция присваивания. Ну ведь логически проще написать ВЫХОД_Х=1, чем писать ПРИЗНАК_ВКЛЮЧЕННОСТИ=БИНАРНОЕ_ЧИСЛО_ОПРЕДЕЛЯЮЕЕ_НОМЕРА_ВЫХОДОВ_ПРИЗНАК_ВКЛЮЧЕННО СТИ_КОТОРЫХ_НАСТРАИВАЕТСЯ или ПРИЗНАК_ВЫКЛЮЧЕННОСТИ=БИНАРНОЕ_ЧИСЛО_ОПРЕДЕЛЯЮЩЕЕ_НОМЕРА_ВЫХОДОВ_ПРИЗНАК_ВЫКЛЮЧЕ ННОСТИ_КОТОРЫХ_НАСТРАИВАЕТСЯ. Опять таки, если я правильно понял логику работы. Цитата аппаратно реализованы так же и установка отдельных битов регистра в 1, установка отдельных битов регистра в 0 и побитовая адресация регистров? Разве в AVR такого не было? Вопрос такой, каковы преимущества порта в ARM по сравнению с AVR, кроме того, что можно читать состояние пинов, как пишет Редькин, непосредственно на выходе? Вот скажем, в ODSR откуда берется информация? Она попадает туда во время записи в регистр SODR, или же состояние ODSR зависит от фактического состояни пина? Ну скажем, что-то на выходе порта выгорело, или на выходе значительная просадка напряжения, мы пишем в него единичку, а результата не имеем, можно ли это диагностировать с помощью ODSR ? Посмотрел я макросы Аскольда. А не слишком ли громоздко? Например Код #define _setL(port,bit) do { AT91C_BASE_PIO##port##->PIO_CODR = (1 << bit); } while(0) Не до хрена ли это тактов займет? Или вот еще круче - одно и то ж действие по-разному обзывается: Код #define _setH(port,bit) do { AT91C_BASE_PIO##port##->PIO_SODR = (1 << bit); } while(0) #define _clrL(port,bit) do { AT91C_BASE_PIO##port##->PIO_SODR = (1 << bit); } while(0) Ведь как я понял, по принципу двух исключающих друг друга конпок, SetH автоматом делает ClearL. охох..голова кругом, сколько плясок с бубном...
|
|
|
|
|
May 13 2010, 09:32
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(zheka @ May 13 2010, 11:17)  Под соседним регистром вы имеете ввиду ODSR? Да. И в него можно писать состояние всего порта, как и в PORTx в AVR (записав единицы в нужные биты OWSR). Цитата(zheka @ May 13 2010, 11:17)  Я понимаю, что более гибкий доступ к функциям камня это хорошо, мне непонятно, почему так сделано. Ведь в любом слчуае выполняется оперция присваивания. Ну ведь логически проще написать ВЫХОД_Х=1, чем писать Это вам на С кажется, что PORTC.1=1 это одна операция присваивания. На ассемблере (без оптимизации или для портов, не попавших в IO space, как PORTE) это операция чтения, наложения маски по "или" и запись обратно в порт. А перед этим еще загрузка маски в регистр, потому что AVR умеет "или" только с регистром. А в случае SODR/CODR это будет действительно одна операция записи (и одна загрузки маски в регистр). Причем если надо одной командой установить до восьми соседних битов, то даже загрузку маски можно уместить в эту же команду за счет использования аппаратного сдвигателя ARM. Цитата(zheka @ May 13 2010, 11:17)  Вопрос такой, каковы преимущества порта в ARM по сравнению с AVR, кроме того, что можно читать состояние пинов, как пишет Редькин, непосредственно на выходе? Хотелось бы спросить у Редькина - а что, у AVR чтение PINx/PORTx работает по-другому? Цитата(zheka @ May 13 2010, 11:17)  Вот скажем, в ODSR откуда берется информация? Она попадает туда во время записи в регистр SODR, или же состояние ODSR зависит от фактического состояни пина? Ну скажем, что-то на выходе порта выгорело, или на выходе значительная просадка напряжения, мы пишем в него единичку, а результата не имеем, можно ли это диагностировать с помощью ODSR ? Нет, нельзя. Выкиньте Редькина, откройте даташит (на худой конец его перевод с gaw.ru), посмотрите картинку 15-3 и сразу увидете, что ODSR - это то, что вы хотите вывести на ноги (аналог PORTx в AVR). А PDSR - то, что читается с ног, аналог PINx у AVR. Цитата(zheka @ May 13 2010, 11:17)  Посмотрел я макросы Аскольда. А не слишком ли громоздко? Например Код #define _setL(port,bit) do { AT91C_BASE_PIO##port##->PIO_CODR = (1 << bit); } while(0) Не до хрена ли это тактов займет? Нет. Быстрее точно никак. К тому же сдвиг вычисляется на этапе компиляции. Цитата(zheka @ May 13 2010, 11:17)  Или вот еще круче - одно и то ж действие по-разному обзывается: Да, с тех пор утекло много времени, все развивается. Вот более оптимальный с точки зрения исходника вариант для ARM под gcc (но компилится он в абсолютно те же команды).
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 11:27
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Ну вот еще одна непонятка. Опять таки сравниваем c AVR PORTA=0xF0; PORTA=0x0F; На выходе будет 0x0F, сразу же; Если же работать с SAM7: AT91C_BASE_PIOA->PIO_SODR = 0xFFFF0000; AT91C_BASE_PIOA->PIO_SODR = 0x0000FFFF; То на выходе будет 0xFFFFFFFF. Для того чтобы получить искомые 0x0000FFFF нужно сначала обнулить, а это лишние такты. А если я хочу это сделать быстро, как мне быть? МОжно ли как-то записать 32битное число в порт, чтобы не беспокоиться о том что же в этот момент в порту записано, или нужно взять за правило обнулять порт перед записью нового числа? Прошу прощения за чайниковые вопросы. Цитата Выкиньте Редькина, откройте даташит А есть что-нибудь такое же правильное как даташит, но такое же русское, как Редькин? В общем я чувствую что запутываюсь окончательно. Вы правы - тяжелое наследие работы с CodeVision. Еще тогда кто-то сказал, что COdeVision для новичка - лучший способ испортить стиль программирования. У меня к присутствющим просьба: вот задача - есть PIOA c его 32 ножками. Есть два 8-ми битных числа a и b. Мне нужно поместить биты числа а в биты №№0-7 порта, а биты числа b вы биты №№24-31 порта. Подскажите как это сделать, тогда мне будет от чего отталкиваться, а то от макроса в последнем вложении голова кругом пошла.
|
|
|
|
|
May 13 2010, 11:44
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(zheka @ May 13 2010, 14:43)  Ну вот еще одна непонятка. Опять таки сравниваем c AVR PORTA=0xF0; PORTA=0x0F; На выходе будет 0x0F, сразу же;
Если же работать с SAM7: AT91C_BASE_PIOA->PIO_SODR = 0xFFFF0000; AT91C_BASE_PIOA->PIO_SODR = 0x0000FFFF;
То на выходе будет 0xFFFFFFFF. Для того чтобы получить искомые 0x0000FFFF нужно сначала обнулить, а это лишние такты. А если я хочу это сделать быстро, как мне быть?
МОжно ли как-то записать 32битное число в порт, чтобы не беспокоиться о том что же в этот момент в порту записано, или нужно взять за правило обнулять порт перед записью нового числа? Прошу прощения за чайниковые вопросы. А разве вSAM7 нет вывода в регистр? Тогда переходите на кортекс Там есть все три LPC_GPIO0->FIOPIN=i // выводит значение i в регстр0 LPC_GPIO0->FIOSET=i // устанавливает в регстре0 в 1 те биты, которые в i равны 1, остальные не меняются LPC_GPIO0->FIOCLR=i // устанавливает в регстре0 в 0 те биты, которые в i равны 1, остальные не меняются
|
|
|
|
|
May 13 2010, 12:38
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(zheka @ May 13 2010, 14:27)  Ну вот еще одна непонятка. Опять таки сравниваем c AVR PORTA=0xF0; PORTA=0x0F; На выходе будет 0x0F, сразу же;
Если же работать с SAM7: AT91C_BASE_PIOA->PIO_SODR = 0xFFFF0000; AT91C_BASE_PIOA->PIO_SODR = 0x0000FFFF;
То на выходе будет 0xFFFFFFFF. Для того чтобы получить искомые 0x0000FFFF нужно сначала обнулить, а это лишние такты. А если я хочу это сделать быстро, как мне быть? Читать даташит. В крайнем случае его перевод на русский язык с сайта gaw.ru. Код AT91C_BASE_PIOA->PIO_OWER = 0xFFFFFFFF; // <-- один раз в начале программы AT91C_BASE_PIOA->PIO_ODSR = 0x12345678; // Записали 32 бита в порт Цитата(zheka @ May 13 2010, 14:27)  У меня к присутствющим просьба: вот задача - есть PIOA c его 32 ножками. Есть два 8-ми битных числа a и b. Мне нужно поместить биты числа а в биты №№0-7 порта, а биты числа b вы биты №№24-31 порта. А что вы хотите сделать с остальными битами (8-23)? Если не хотите их менять: Код // Вариант А: uint32_t Tmp = AT91C_BASE_PIOA->PIO_OWSR; AT91C_BASE_PIOA->PIO_OWER = 0xFF0000FF; AT91C_BASE_PIOA->PIO_OWDR = ~0xFF0000FF; AT91C_BASE_PIOA->PIO_ODSR = (b << 23) | (a<<0); AT91C_BASE_PIOA->PIO_OWER = Tmp; AT91C_BASE_PIOA->PIO_OWDR = ~Tmp; // Вариант B: AT91C_BASE_PIOA->PIO_SODR = (b << 23) | (a<<0); AT91C_BASE_PIOA->PIO_CODR = ~((b << 23) | (a<<0) | (0xFFFF << 8)); А как бы вы записали по 2 бита из каждой переменной в биты 0,1 и 6,7 на AVR?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
May 13 2010, 14:44
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
С битами 8-23 я ничего не собирался делать. А в АВР я делал бы точно так же как и с АРМ, так как вы написали с этим то проблем не было, я даже в симулятор гонял. В от только когда в 0-7 записано 0xFF, а затем 0xAA, то все равно остается 0xFF. Ваш ответ про OWDR я прочел, сейчас буду пробовать. Код // Вариант B: AT91C_BASE_PIOA->PIO_SODR = (b << 23) | (a<<0); AT91C_BASE_PIOA->PIO_CODR = ~((b << 23) | (a<<0) | (0xFFFF << 8)); А второй строкой вы что хортели сделать? НИже код - наличие/присутствие строки ничего в симуляторе не изменило. Код AT91C_BASE_PIOA->PIO_SODR = 0x00AAAA00; //записываем AAAA в биты 8-23, неузявимость которых хотим проверить AT91C_BASE_PIOA->PIO_SODR = (0xFF << 23) | (0xFF<<0); ///записываем 0xFF по краям. //AT91C_BASE_PIOA->PIO_CODR = ~((0xFF << 23) | (0xFF<<0) | (0xFFFF << 8) ); ///Ваша строка AT91C_BASE_PIOA->PIO_SODR = (0xAA << 23); // Записываем 0xAA в биты 24-31, чтобы проверить, затирается ли 0xFF после записи и остается ли сохранной информация в битах 8-23. Результат - в битах 24-31 остается 0xFF, биты 8-23 целы. Комментирование/раскомментирование Вашей строки не меняет результат.
|
|
|
|
|
May 13 2010, 14:46
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(vallav @ May 13 2010, 14:44)  Тогда переходите на кортекс Там есть все три LPC_GPIO0->FIOPIN=i // выводит значение i в регстр0 LPC_GPIO0->FIOSET=i // устанавливает в регстре0 в 1 те биты, которые в i равны 1, остальные не меняются LPC_GPIO0->FIOCLR=i // устанавливает в регстре0 в 0 те биты, которые в i равны 1, остальные не меняются А причем тут какое-либо ядро к организации GPIO конкретного контроллера? В отношении Cortex-M3, ну там разве только от ядра bit-band может быть использован для частичной эмуляции помянутых Вами LPC-шных SET/CLR
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 13 2010, 14:58
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Значит так, господа давайте изложу проблему детально. 1. Записываю информацию в серединку 8-23, записываю, скажем так, навсегда. 2. Пишу в биты 0-7 и 23-31 числа 0xFF. 3. Убеждаюсь что биты 8-23 не тронуты. 4. Снова пишу другое число - 0xAA в биты 0-7 и 23-31. Очень хочу, чтобы там оказались AA - чередование 0 и 1. Можно ли это сделать без предварительной очистки в ноль битов 0-7 и 23-31 ??? Пока сделал так: Код AT91C_BASE_PIOA->PIO_PER = 0xFFFFFFFF; AT91C_BASE_PIOA->PIO_OER = 0xFFFFFFFF; AT91C_BASE_PIOA->PIO_OWER = 0xFFFFFFFF;
AT91C_BASE_PIOA->PIO_SODR = 0x00AAAA00; AT91C_BASE_PIOA->PIO_SODR = (0xFF << 24) | (0xFF<<0); //AT91C_BASE_PIOA->PIO_CODR = ~((0xFF << 24) | (0xFF<<0) | (0xFFFF << 8) ); AT91C_BASE_PIOA->PIO_SODR = (0xAA << 24) | (0xAA<<0); Средние биты защищены. А вот в крайних так и остается 0xFF.
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|