Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подключение внешней памяти через мультиплексированную шину
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
nagserg
Подскажите пожалуйста как обратится к внешней памяти, используя альтернативные выводы (ALE, WR, RD)?
Работаю в CodeVision

........

MCUCR = 0x80; // Разрешаем работу с внешним ОЗУ

XMCRB = 0x07; // Адресные выводы порта С A8...A15 не использовать

а вот как прочитать записать по определенному адресу? Подскажите пожалуйста.
BVU
Цитата(nagserg @ Dec 22 2005, 12:21) *
Подскажите пожалуйста как обратится к внешней памяти, используя альтернативные выводы (ALE, WR, RD)?
Работаю в CodeVision

........

MCUCR = 0x80; // Разрешаем работу с внешним ОЗУ

XMCRB = 0x07; // Адресные выводы порта С A8...A15 не использовать

а вот как прочитать записать по определенному адресу? Подскажите пожалуйста.

Почитайте здесь (на русском), лучшего описания использованияпамяти памяти не встречалось:
http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/2.htm
Rash
А какую внешню память в качестве ОЗУ используете, её тип?
nagserg
Честно говоря я использую не память, а контроллер USB ISP1581, который использует такой же интерфейс - мультиплексированную шину адреса/данных. Вот не совсем понятно как прочитать, записать байт по определенному адресу.
BVU
Цитата(nagserg @ Dec 22 2005, 14:03) *
Честно говоря я использую не память, а контроллер USB ISP1581, который использует такой же интерфейс - мультиплексированную шину адреса/данных. Вот не совсем понятно как прочитать, записать байт по определенному адресу.

Посмотрите блок схему подключения USB ISP1581 к микроконтроллеру.
http://www.gaw.ru/html.cgi/txt/publ/interface/usb.htm
и соотнесите адресное пространство внешней памяти своего микроконтроллера с имеющимися адресамиадресами в USB ISP1581.
Писать и читать ячейки данной памяти (USB ISP1581), точно так же как и память внутреннюю. Можете объявить ее, как массив или присвоить начальной области значение указателя. А наверняка там имеются и регистры управления, для инициализации устройства. Лучше всего организовать структуру в которой бы описывалась внутренняя организация регистров и ячеек памяти для данных. Для компилятора надо указывать тип данных, как внешняя память.
mse
Цитата
XMCRB = 0x07; // Адресные выводы порта С A8...A15 не использовать

Круто... У м128, ваще-то, 4К нутрянной мемори. Так что из А8...А15, кой-кого пользовать, таки, придёцца ;О) Ымею в виду, что-нить типа CS для внешней микрухи. Ну и писать, соотвецтвенно, в память выше $1100, предварительно опустив/подняв CS в нуную позу. Вот.
nagserg
Цитата(BVU @ Dec 22 2005, 14:58) *
Цитата(nagserg @ Dec 22 2005, 14:03) *

Честно говоря я использую не память, а контроллер USB ISP1581, который использует такой же интерфейс - мультиплексированную шину адреса/данных. Вот не совсем понятно как прочитать, записать байт по определенному адресу.

Посмотрите блок схему подключения USB ISP1581 к микроконтроллеру.
http://www.gaw.ru/html.cgi/txt/publ/interface/usb.htm
и соотнесите адресное пространство внешней памяти своего микроконтроллера с имеющимися адресамиадресами в USB ISP1581.
Писать и читать ячейки данной памяти (USB ISP1581), точно так же как и память внутреннюю. Можете объявить ее, как массив или присвоить начальной области значение указателя. А наверняка там имеются и регистры управления, для инициализации устройства. Лучше всего организовать структуру в которой бы описывалась внутренняя организация регистров и ячеек памяти для данных. Для компилятора надо указывать тип данных, как внешняя память.


Вот например в ISP1581 есть адрес Mode 0x0C.
Задача: записать в этот адрес какое-нибудь число, затем прочитать.
Просто сначала хочу хотя бы это научится, потом буду думать как соотнести адресное пространство внешней памяти контроллера с адресами в USB1581
mse
Цитата
от например в ISP1581 есть адрес Mode 0x0C.
Задача: записать в этот адрес какое-нибудь число, затем прочитать.

Код
  ...
      cbi   portX,_CS_ISP1581_
      ldi   r16,direct_data
      sts  $1100+$0c,r16
      lds  r16,$1100+$0c
      sbi  portX,_CS_ISP1581_
  ...
nagserg
Спасибо огромное за ответы, смысл понятен, хотелось бы конечно на Си, а то я в ассемблере ни бум-бум.
_artem_
char *ptr_p, getit;

ptr_p = (char*)0xffff;

getit = *ptr_p; // read

*ptr_p = getit; // write
defunct
Цитата(Rash @ Dec 22 2005, 11:51) *
А какую внешню память в качестве ОЗУ используете, её тип?


Используем SRAM. дешевые и доступные микросхемы UT621024-LL70, UT62256-LL70.
Стандартная схема включения через защелки (LATCH). В качестве защелки используем отечественный 1533ИР22. А для работы с внешней памятью в C не требуется никаких специфических телодвижений.. MCUCR = ( 1 << SRE) и все..

на асме аналогично

Код
ldi al, (1 << SRE)
out MCUCR, al


и читать/писать ld/st, lds/sts как и внутренний SRAM.

Читать с определенного адреса:
Код
ldi  ZH, High( Определенный адрес)
ldi  ZL, Low( Определенный адрес)
ld  AL, Z


на C будет типа такого:

Код
  char* vp = (char *)Определенный Адрес;
  char  a;
   a = *vp;  // читать
   *vp = a;  // писать
_artem_
defunct , ram kotorij ti upomyanul - on nizkoskorostnoj . Na 16 MHz ne ponyanet bez wait steyta. Lucse ispolzovat fast asynchronous sram's szaderzkoj do 20 nanosec. Primeri podobnyx chipov mozno nayti v STK501 guide gde recommenduyutsya tipy sram'ov dlja zapajki .
nagserg
char* vp = (char *)Определенный Адрес;
char a;
a = *vp; // читать
*vp = a; // писать

Так всё работает прекрасно, но вот возник такой вопрос: создана структура типа:

typedef union
{
unsigned char byte;
struct
{
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} bit_field;
} as_bit_field_of_byte;
nagserg
Цитата(nagserg @ Dec 26 2005, 12:19) *
char* vp = (char *)Определенный Адрес;
char a;
a = *vp; // читать
*vp = a; // писать

Так всё работает прекрасно, но вот возник такой вопрос: создана структура типа:

typedef union
{
unsigned char byte;
struct
{
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} bit_field;
} as_bit_field_of_byte;


Каким образом привязать адрес этой структуры к "Определенному адресу" char* vp = (char *)Определенный Адрес;
defunct
Цитата(_artem_ @ Dec 26 2005, 02:10) *
defunct , ram kotorij ti upomyanul - on nizkoskorostnoj . Na 16 MHz ne ponyanet bez wait steyta. Lucse ispolzovat fast asynchronous sram's szaderzkoj do 20 nanosec. Primeri podobnyx chipov mozno nayti v STK501 guide gde recommenduyutsya tipy sram'ov dlja zapajki .


20нс абсолютно не нужно. Не настолько быстр AVR как этого хотелось бы.

Приведенная мной 70нс память, работает без дополнительных waitstate и на 14.7456 Mhz, и на 16 Mhz. AVR считывает ячейку памяти (без waitstate) за три такта, длительность такта будет равна 62.5 нс при Fosc = 16Mhz, соответственно длительность строба RD/WR равна 2*62.5нс = 125 нс, что вполне удовлетворяет требованиям памяти (у приведенных микросхем памяти длительность цикла чтения/записи - 70нс).
defunct
Цитата(nagserg @ Dec 26 2005, 12:49) *
Каким образом привязать адрес этой структуры к "Определенному адресу" char* vp = (char *)Определенный Адрес;


Считаю, что лучше не привязывать эту структуру к определенному адресу, т.к. при обращении к каждому биту будет произведено повторное чтение.. Если у Вас используется DMA то это приведет к неправильной работе.. Думаю, правильней будет вначале прочитать, а потом уже проверять/устанавливать отдельные биты:

Код
typedef union
{
unsigned char byte;
struct
{
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} bit_field;
} dummy_union;

void test(void)
{
  char* vp = (char *)0x300; // адрес 300h
  dummy_union a;             // ваша структура
  a.byte = *vp;                   // считываем данные с адреса 300h
  if (a.bit_field.b0) {};             // проверяем отдельные биты..
  /*.....................................*/
  /*.. выполняем какие-то действия над битами ..*/
  /*.....................................*/
  *vp = a.byte;                   // записываем изменения..
}
_artem_
Цитата(defunct @ Dec 27 2005, 02:00) *
Цитата(_artem_ @ Dec 26 2005, 02:10) *

defunct , ram kotorij ti upomyanul - on nizkoskorostnoj . Na 16 MHz ne ponyanet bez wait steyta. Lucse ispolzovat fast asynchronous sram's szaderzkoj do 20 nanosec. Primeri podobnyx chipov mozno nayti v STK501 guide gde recommenduyutsya tipy sram'ov dlja zapajki .


20нс абсолютно не нужно. Не настолько быстр AVR как этого хотелось бы.

Приведенная мной 70нс память, работает без дополнительных waitstate и на 14.7456 Mhz, и на 16 Mhz. AVR считывает ячейку памяти (без waitstate) за три такта, длительность такта будет равна 62.5 нс при Fosc = 16Mhz, соответственно длительность строба RD/WR равна 2*62.5нс = 125 нс, что вполне удовлетворяет требованиям памяти (у приведенных микросхем памяти длительность цикла чтения/записи - 70нс).



Рисунок 13 дата шит атмега 128 - первые два такта используются для установления адреса в латч триггер . Сам сигнал /write (с которого отсчет на выборку ячейки идет) на память начинается вровень с третьим тактом вместе (даже на рисунке видно небольшое запаздывание по отношению к тактовой частоте). В итоге мы получаем не три такта на выборку адреса а один, что в конечном итоге меньше 62.5 наносек на максимальной частоте. (without delay state)

Почему то атмел рекомендует 20 нанoсекундные чипы, хотя можно в принципе и 55 наносек поставить. Но вот интересный материал правда на японском http://elm-chan.org/docs/avr/jitter.html. Там видно что тактовая может прыгать на атмегах. Читал что этот эффект используется в мсп430 для того чтобы уменьшить спектр излучения микросхемой эм энергии в соответствии со своими америкосовскими нормами (насчет норм могу и ошибаться). Если атмел тоже это специально сделал в тактовой то наверняка возможна ситуация со временем обрашения меньше чем даже 60 наносек.
defunct
Цитата(_artem_ @ Dec 27 2005, 02:45) *
Рисунок 13 дата шит атмега 128 - первые два такта используются для установления адреса в латч триггер . Сам сигнал /write (с которого отсчет на выборку ячейки идет) на память начинается вровень с третьим тактом вместе (даже на рисунке видно небольшое запаздывание по отношению к тактовой частоте). В итоге мы получаем не три такта на выборку адреса а один, что в конечном итоге меньше 62.5 наносек на максимальной частоте. (without delay state)


Эх, сорри, облажался я.. sad.gif

Да вы правы, строб идет не 2 такта, а один.. итого 62.5нс на выборку на 16Mhz. И действительно на 16Mhz память может не успевать. На практике же у нас редко m128 работает на 16mhz (пару раз испытали - память работала устойчиво, разумеется понимаю, что пара раз - не показатель). В основном тактируем мегу 14.7456Mhz, глюков указанной памяти не замечено. (waitstate не ставим).

тактируем либо кристалом с запрограммированными фузами CKOUT/CKOPT, либо от внешнего генератора, поэтому тактовая частота у нас не прыгает..

Цитата(_artem_ @ Dec 27 2005, 02:45) *
Если атмел тоже это специально сделал в тактовой то наверняка возможна ситуация со временем обрашения меньше чем даже 60 наносек.


Врятли, скорее наоборот - в большую сторону.
nagserg
Цитата(defunct @ Dec 27 2005, 03:28) *
Цитата(nagserg @ Dec 26 2005, 12:49) *

Каким образом привязать адрес этой структуры к "Определенному адресу" char* vp = (char *)Определенный Адрес;


Считаю, что лучше не привязывать эту структуру к определенному адресу, т.к. при обращении к каждому биту будет произведено повторное чтение.. Если у Вас используется DMA то это приведет к неправильной работе.. Думаю, правильней будет вначале прочитать, а потом уже проверять/устанавливать отдельные биты:

Код
typedef union
{
unsigned char byte;
struct
{
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} bit_field;
} dummy_union;

void test(void)
{
  char* vp = (char *)0x300; // адрес 300h
  dummy_union a;             // ваша структура
  a.byte = *vp;                   // считываем данные с адреса 300h
  if (a.bit_field.b0) {};             // проверяем отдельные биты..
  /*.....................................*/
  /*.. выполняем какие-то действия над битами ..*/
  /*.....................................*/
  *vp = a.byte;                   // записываем изменения..
}


Я DMA не использую пока и всё-таки каким образом можно привязать структуру к определенному адресу? или не совсем понятно:
Цитата(BVU @ Dec 22 2005, 14:58) *
Посмотрите блок схему подключения USB ISP1581 к микроконтроллеру.
http://www.gaw.ru/html.cgi/txt/publ/interface/usb.htm
и соотнесите адресное пространство внешней памяти своего микроконтроллера с имеющимися адресами в USB ISP1581.
Писать и читать ячейки данной памяти (USB ISP1581), точно так же как и память внутреннюю. Можете объявить ее, как массив или присвоить начальной области значение указателя. А наверняка там имеются и регистры управления, для инициализации устройства. Лучше всего организовать структуру в которой бы описывалась внутренняя организация регистров и ячеек памяти для данных. Для компилятора надо указывать тип данных, как внешняя память.

Можно поподробнее, работаю в CodeVision
defunct
> Я DMA не использую пока и всё-таки каким образом можно
> привязать структуру к определенному адресу?

Привязать точно также как и char..

dummy_union* vp = (dummy_union *)определенный адрес;

использовать можно так:

unsigned char a;
a = (*vp).byte;
(*vp).byte = a;

обращение к битам:

(*vp).bit_field.b0 = 1;
(*vp).bit_field.b5 = 0;


ps: а чем не устраивает чтение-модификация-запись в предыдущем примере?
nagserg
Цитата(defunct @ Dec 27 2005, 11:50) *
ps: а чем не устраивает чтение-модификация-запись в предыдущем примере?

У меня есть пример на Keil, скачал с какого-то Китайского сайта, так там вот такое обращение к регистрам:

if(USB_Int_Flag.BITS.SUSP)
{
.......

D14_Cntrl_Reg.D14_MODE.BITS.GOSUSP = 1;
}

или

D14_Cntrl_Reg.D14_ADDRESS.VALUE = 0x80;

вот как применить подобное - не понимаю.

Вот например файл описания регистров
BVU
nagserg, когда Вы хотите использовать обращение к внешней памяти, необходимо четко представлять по каким логическим и физическим адресам в Вашей системе они распологаются. Для этого у ATmega128 существует 'Карта памяти данных', которая в свою очередь может быть настроена для использования как конфигурации 'A' или 'B' где начало внешнего СОЗУ немного отличаются. Далее у Вас (схемотехника) должны быть подключены одноименные выводы микроконтроллера и внешнего устройства. Все это следует из той ссылки которую я Вам давал в прошлый раз:
http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/2.htm
посмотрите внимательно как можно использовать внешнюю память в разделе 'Использование всех ячеек внешней памяти размером менее 64 кбайт', там очень хорошо изложен принцип привязки физических и логических адресов. Так же там есть примеры кода на ASM и 'C'.
Рекомендую так же ссылку с нашего форума:
http://electronix.ru/forum/index.php?showt...ется+с+адреса+0
Попробуйте также найти книгу: 'Применение мк-ров AVR: схемы, алгоритмы, программы', ирма:Додэка-XXI, Год выпуска: 2004. там все это разбирается на примере ATmega8515.
Так же посмотрите ссылку:
http://bvn123.boom.ru/Controller.html

Удачи,
BVU
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.