Перейти к содержанию
    

Работа с SFR по указателю

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача в этом виде - нерешаемая.

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача в этом виде - нерешаемая.

Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель).

Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?

Тогда да, идеологию надо в корне менять, спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?

Да. Но, можно сделать так, как я говорил выше, примерно, так:

#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);
}

Вот, только, вопрос: а, нужно ли это; будет ли от этого некая выгода ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. Но, можно сделать так, как я говорил выше, примерно, так:

#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 будет переменной, тогда совсем никак.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?
... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM.

И схема должна быть разведена под фон-неймановскую архитектуру.

И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти.

 

Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно.

 

Если извратить мысль еще больше, то современные МК в большинстве случаев имеют возможности по модификации своего кода. То есть функция может модифицировать код в зависимости от аргумента (всего то один байт) и выполнить данный фрагмент. Накладно, затратно, но теоретически возможно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти.

 

Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно.

не только теоретически ... и не стоит быть слишком категоричным - случаи бывают разные ( через внешнюю шину можно не только нарастить память, но и подключить доп. порты В/В ). К тому же иногда такие "извращения" бывают весьма удобны ....

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...