Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с SFR по указателю
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > MCS51
Alexashka
Добрый день всем! Тут знакомый задал задачку, которую с наскоку не смог решить, хотя с виду простая. Может я туплю, но чтото с кейлом у нас взаимопонимания не получилось. Смысл задачи в следующем: нужно в функцию передать адрес SFR регистра (ну допустим адрес ноги порта Р0, в которую мы хотим вывести бит данных, или прочитать ее значение), номер изменяемого бита и собсно бит данных, который по этому адресу нужно прописать. Собственно попытка передать адрес (например порта Р0) со смещением на номер бита и затем приведение его к типу sbit провалилась. Примеров много просмотрел, хэлп читал, но чтото безрезультатно. Подскажите как тут можно поступить, желательно без запихивания всей функции в дефайны.
Палыч
Задача в этом виде - нерешаемая.
Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель). Собственно, поэтому при попытке обращения к SFR через указатель, происходит обращение к ОЗУ, имеющее такой же адрес, что и SFR... Имхо, единственное решение - типа такого: в подпрограмме (функции) в зависимости от адреса, переданного в качестве операнда, предусмотреть прямое обращение к SFR. Естественно, функция "разрастется" до анализа и обращений всех ко всем SFR. Выгода от такого решения - сомнительная.

Alexashka
Цитата(Палыч @ Jan 10 2013, 10:45) *
Задача в этом виде - нерешаемая.
Дело в том, что SFR и "верхние" 128 байт ОЗУ МК51 имеют одни и те же адреса, и "различаются" только способом адресации: SFR - прямая адресация, ОЗУ - косвенная (через указатель).

Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?
Тогда да, идеологию надо в корне менять, спасибо.
Палыч
Цитата(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);
}

Вот, только, вопрос: а, нужно ли это; будет ли от этого некая выгода ?
Alexashka
Цитата(Палыч @ 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 будет переменной, тогда совсем никак.
ChipKiller
Цитата("Alexashka")
Т.е адрес SFR фактически заложен в самой команде? Т.е выходит подставить его "риал-тайм" никак не получится, он должен быть определен на этапе компиляции?
... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM.
редактор
Цитата(ChipKiller @ Jan 21 2013, 13:09) *
... "подставить" можно, только с оговоркой, что код должен выполняться во внешнем ПЗУ, в качестве которого подключен RAM.

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

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

Если извратить мысль еще больше, то современные МК в большинстве случаев имеют возможности по модификации своего кода. То есть функция может модифицировать код в зависимости от аргумента (всего то один байт) и выполнить данный фрагмент. Накладно, затратно, но теоретически возможно.
ChipKiller
Цитата("редактор")
И необходимость в этом как-бы отпадет, поскольку (если брать классику) из 4-х портов 2,5 будут заняты на обслуживание внешней памяти.

Но чисто теоретически сформировать код команды для чтения порта и выполнить его можно.
не только теоретически ... и не стоит быть слишком категоричным - случаи бывают разные ( через внешнюю шину можно не только нарастить память, но и подключить доп. порты В/В ). К тому же иногда такие "извращения" бывают весьма удобны ....
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.