Alexashka 0 10 января, 2013 Опубликовано 10 января, 2013 · Жалоба Добрый день всем! Тут знакомый задал задачку, которую с наскоку не смог решить, хотя с виду простая. Может я туплю, но чтото с кейлом у нас взаимопонимания не получилось. Смысл задачи в следующем: нужно в функцию передать адрес SFR регистра (ну допустим адрес ноги порта Р0, в которую мы хотим вывести бит данных, или прочитать ее значение), номер изменяемого бита и собсно бит данных, который по этому адресу нужно прописать. Собственно попытка передать адрес (например порта Р0) со смещением на номер бита и затем приведение его к типу sbit провалилась. Примеров много просмотрел, хэлп читал, но чтото безрезультатно. Подскажите как тут можно поступить, желательно без запихивания всей функции в дефайны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 10 января, 2013 Опубликовано 10 января, 2013 · Жалоба Задача в этом виде - нерешаемая. Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель). Собственно, поэтому при попытке обращения к SFR через указатель, происходит обращение к ОЗУ, имеющее такой же адрес, что и SFR... Имхо, единственное решение - типа такого: в подпрограмме (функции) в зависимости от адреса, переданного в качестве операнда, предусмотреть прямое обращение к SFR. Естественно, функция "разрастется" до анализа и обращений всех ко всем SFR. Выгода от такого решения - сомнительная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 10 января, 2013 Опубликовано 10 января, 2013 · Жалоба Задача в этом виде - нерешаемая. Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель). Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции? Тогда да, идеологию надо в корне менять, спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 10 января, 2013 Опубликовано 10 января, 2013 · Жалоба выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции? Да. Но, можно сделать так, как я говорил выше, примерно, так: #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); } Вот, только, вопрос: а, нужно ли это; будет ли от этого некая выгода ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 10 января, 2013 Опубликовано 10 января, 2013 · Жалоба Да. Но, можно сделать так, как я говорил выше, примерно, так: #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 будет переменной, тогда совсем никак. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ChipKiller 0 21 января, 2013 Опубликовано 21 января, 2013 · Жалоба Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 22 января, 2013 Опубликовано 22 января, 2013 · Жалоба ... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM. И схема должна быть разведена под фон-неймановскую архитектуру. И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти. Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно. Если извратить мысль еще больше, то современные МК в большинстве случаев имеют возможности по модификации своего кода. То есть функция может модифицировать код в зависимости от аргумента (всего то один байт) и выполнить данный фрагмент. Накладно, затратно, но теоретически возможно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ChipKiller 0 22 января, 2013 Опубликовано 22 января, 2013 · Жалоба И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти. Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно. не только теоретически ... и не стоит быть слишком категоричным - случаи бывают разные ( через внешнюю шину можно не только нарастить память, но и подключить доп. порты В/В ). К тому же иногда такие "извращения" бывают весьма удобны .... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться