|
|
  |
Работа с SFR по указателю |
|
|
|
Jan 10 2013, 05:29
|

Практикующий маг
     
Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576

|
Добрый день всем! Тут знакомый задал задачку, которую с наскоку не смог решить, хотя с виду простая. Может я туплю, но чтото с кейлом у нас взаимопонимания не получилось. Смысл задачи в следующем: нужно в функцию передать адрес SFR регистра (ну допустим адрес ноги порта Р0, в которую мы хотим вывести бит данных, или прочитать ее значение), номер изменяемого бита и собсно бит данных, который по этому адресу нужно прописать. Собственно попытка передать адрес (например порта Р0) со смещением на номер бита и затем приведение его к типу sbit провалилась. Примеров много просмотрел, хэлп читал, но чтото безрезультатно. Подскажите как тут можно поступить, желательно без запихивания всей функции в дефайны.
|
|
|
|
|
Jan 10 2013, 06:45
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Задача в этом виде - нерешаемая. Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель). Собственно, поэтому при попытке обращения к SFR через указатель, происходит обращение к ОЗУ, имеющее такой же адрес, что и SFR... Имхо, единственное решение - типа такого: в подпрограмме (функции) в зависимости от адреса, переданного в качестве операнда, предусмотреть прямое обращение к SFR. Естественно, функция "разрастется" до анализа и обращений всех ко всем SFR. Выгода от такого решения - сомнительная.
|
|
|
|
|
Jan 10 2013, 07:19
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Alexashka @ Jan 10 2013, 11:03)  выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции? Да. Но, можно сделать так, как я говорил выше, примерно, так: Код #include <reg52.h>
#define ADR_P0 0x80 #define ADR_P1 0x90 #define ADR_P2 0xA0 #define ADR_P3 0xB0
unsigned char GetSFR(unsigned char Adr_SFR) { switch(Adr_SFR) { case ADR_P0: return P0; case ADR_P1: return P1; case ADR_P2: return P2; case ADR_P3: return P3; } return 0; }
void main(void) { unsigned char x1, x2, x3, x4; x1= GetSFR(ADR_P0); x2= GetSFR(ADR_P1); x3= GetSFR(ADR_P2); x4= GetSFR(ADR_P3); } Вот, только, вопрос: а, нужно ли это; будет ли от этого некая выгода ?
|
|
|
|
|
Jan 10 2013, 07:57
|

Практикующий маг
     
Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576

|
Цитата(Палыч @ Jan 10 2013, 11:19)  Да. Но, можно сделать так, как я говорил выше, примерно, так: Код #include <reg52.h>
#define ADR_P0 0x80 #define ADR_P1 0x90 #define ADR_P2 0xA0 #define ADR_P3 0xB0
unsigned char GetSFR(unsigned char Adr_SFR) { switch(Adr_SFR) { case ADR_P0: return P0; case ADR_P1: return P1; case ADR_P2: return P2; case ADR_P3: return P3; } return 0; }
void main(void) { unsigned char x1, x2, x3, x4; x1= GetSFR(ADR_P0); x2= GetSFR(ADR_P1); x3= GetSFR(ADR_P2); x4= GetSFR(ADR_P3); } Вот, только, вопрос: а, нужно ли это; будет ли от этого некая выгода ? Ну это да, но тогда теряется вся красивость как в случае например input = GetPIO(P0, PIN5); хотя тут то еще можно заменить дефайнами, а вот если Рx или PINx будет переменной, тогда совсем никак.
|
|
|
|
|
Jan 21 2013, 10:09
|

Участник

Группа: Участник
Сообщений: 31
Регистрация: 26-12-11
Пользователь №: 69 097

|
Цитата("Alexashka") Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции? ... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM.
|
|
|
|
|
Jan 22 2013, 05:03
|
Местный
  
Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315

|
Цитата(ChipKiller @ Jan 21 2013, 13:09)  ... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM. И схема должна быть разведена под фон-неймановскую архитектуру. И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти. Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно. Если извратить мысль еще больше, то современные МК в большинстве случаев имеют возможности по модификации своего кода. То есть функция может модифицировать код в зависимости от аргумента (всего то один байт) и выполнить данный фрагмент. Накладно, затратно, но теоретически возможно.
--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
|
|
|
|
|
Jan 22 2013, 10:12
|

Участник

Группа: Участник
Сообщений: 31
Регистрация: 26-12-11
Пользователь №: 69 097

|
Цитата("редактор") И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти.
Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно. не только теоретически ... и не стоит быть слишком категоричным - случаи бывают разные ( через внешнюю шину можно не только нарастить память, но и подключить доп. порты В/В ). К тому же иногда такие "извращения" бывают весьма удобны ....
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|