|
Работа с опреативной памятью в AVR ASM |
|
|
|
Jan 18 2011, 09:56
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Здравствуйте, так получилось, что на C/С++ для АВРов начал писать раньше, чем на АСМе. Теперь не совсем понятно как корректно работать с переменными в SRAM. Если на С задачу копирования адреса я решал так: Код unsigned char *ptr1, *ptr2;
ptr2 = ptr1; и копирование значения (как вариант): Код unsigned char *ptr1, *ptr2;
*ptr2 = *ptr1; то как такие задачи решаются на АСМе? если написан следующий код: Код Tmp1: .byte 1 Tmp2: .byte 1
.....
lds r16,SPDR ;для примера взят регистр SPI st Z+,r16
lds Tmp1,ZH lds Tmp2,ZL то что значат последние две строки кода: что я копирую значения старшего и младшего байтов регистра Z или что я копирую новый адрес ячейки памяти, на которую указывает Z после постинкремента? Вобщем хотелось бы знать как в АСМе скопировать адрес и как скопировать значение. Надеюсь корректно описал вопрос.
|
|
|
|
|
Jan 18 2011, 10:38
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Код lds Tmp1,ZH lds Tmp2,ZL Вы считывете в Tmp1- значение расположенное по адресу находящегося ZH и соответсвенно в Tmp2 в ZL т.е не понятно откуда Скопировать значение mov TMP1,TMP2Скопировать адрес MOVW X,Z
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Jan 18 2011, 11:52
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(ILYAUL @ Jan 18 2011, 12:38)  Вы считывете в Tmp1- значение расположенное по адресу находящегося ZH и соответсвенно в Tmp2 в ZL т.е не понятно откуда предполагается, что ранее в программе в Z что-то заносилось Цитата(ILYAUL @ Jan 18 2011, 12:38)  Скопировать значение mov TMP1,TMP2 Скопировать адрес MOVW X,Z спасибо, буду пробовать Вообще, наверно, проще будет описать задачу: есть буффер из 50 элементов и в него заносятся последовательно байты; есть две байтовых переменных, в которых должна хранится high и low часть адреса следующего элемента, который будет записан (по аналогии с индексом массива в С/С++). В обработчике прерывания я заношу в буффер байт, инкрементирую регистр Z и нужно этот новый адрес записать для того, чтобы в следующем прерывании уже записывать новый элемент реализация на С для IAR простенького кольцевого буффера: Код #include <ioavr.h> #define EVER;; #define BUFF_SIZE 50
typedef unsigned char BYTE;
BYTE Buff[BUFF_SIZE]; BYTE index;
void main() { USART_Init(); //к примеру будем забирать из УСАРТа байты
for(EVER) { }
#pragma vector=USART0_RXC_vect __interrupt void usart_rxc(void) { BYTE sym;
sym = UDR0; Buff[index++] = sym; index = index % BUFF_SIZE; } } как написать подобное на АСМе? пробовал написать следующее: Код ...
.DSEG USART_Index_H: .byte 1 USART_Index_L: .byte 1 USART_BUFF: .byte 50
... ;инициализации и все такое ...
USART0_RXC: push ZH push ZL push r16
;грузим адрес нового элемента, полученный в предыдущем прерывании lds ZH,USART_Index_H lds ZL,USART_Index_L lds r16,UDR0 st Z+,r16
;сохраняем новый адрес lds USART_Index_H,ZH lds USART_Index_L,ZL reti но, полагаю, это работать не будет... Забыл дописать Код ... ;инициализация lds ZH,high(USART_BUFF) lds ZL,low(USART_BUFF) sts USART_Index_H,ZH sts USART_Index_L,ZL ... ;и забыл в конце прерывания дописать pop r16 pop ZL pop ZH
Сообщение отредактировал HoboTech - Jan 18 2011, 11:53
|
|
|
|
|
Jan 18 2011, 13:17
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Что бы понять до конца задачу - прерывания идут последовательно ? Т.е. 1, 2, 1, 2,1, 2 или нет 1111, 2, 11 ,2 и тд
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Jan 18 2011, 13:51
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(ILYAUL @ Jan 18 2011, 15:17)  Что бы понять до конца задачу - прерывания идут последовательно ? Т.е. 1, 2, 1, 2,1, 2 или нет 1111, 2, 11 ,2 и тд в общем задача сводится к тому, чтобы по приходу символа в USART заносить его последовательно в буфер прерывание одно - USART0_RXC:
|
|
|
|
|
Jan 18 2011, 15:02
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Код .def R16,temp .def R17,count .def R4,SaveSREG ... Инициализация
.DSEG USART_BUFF: .byte 50
SAVE_INDEX_Z: byte 2 SaveZL =0 SaveZH=1
MAIN: ldi ZH,HIGH(USART_BUFF) ldi ZL,LOW(USART_BUFF) ldi count,50 .........................
USART0_RXC: in SaveSREG,SREG push SaveSREG push temp push ZL push ZH lds ZL,SAVE_INDEX_Z+SaveZL lds ZH,SAVE_INDEX_Z+SaveZH lds temp,UDR0 st Z+,temp dec count brne END_RX ldi ZH,HIGH(USART_BUFF) ldi ZL,LOW(USART_BUFF) ldi count,50 END_RX: sts SAVE_INDEX_Z+SaveZL,ZL sts SAVE_INDEX_Z+SaveZH,ZH pop ZH pop ZL pop temp pop SaveSREG out SREG,SAVESREG reti Но лучше использовать регисты X или Y вместо Z- через Z идёт обращение к памяти програм и Eeprom и он чаще используется и соответственно его надо отслеживать и при необходимости PUSH и POP
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Jan 18 2011, 16:31
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 6-12-07
Из: Рига, Латвия
Пользователь №: 33 036

|
Цитата(HoboTech @ Jan 18 2011, 17:39)  Я так понял Ваш код будет работать только в случае, когда в основном теле программы не изменяется содержимое ZH и ZL. Меня интересует именно сохранение адреса, на который указывает регистровая пара Z после постинкремента, в переменную Если, конечно, такое возможно Есть два варианта: - сохраняем в ОЗУ; .equ ZH_save 0x0100 .equ ZL_save 0x0101 sts ZH_save,ZH sts ZL_ save,ZL - копируем регистровую пару; movw r3:r2,ZH:ZL в целом: lds ZH, ZH_save ; восстанавливаем указатель lds ZL, ZL_save in r16, UDR ; записываем принятый байт st Z+, r16 sts ZH_save, ZH ; сохраняем указатель sts ZL_save, ZL
Сообщение отредактировал Дмитрий Ветра - Jan 18 2011, 16:34
|
|
|
|
|
Jan 18 2011, 17:04
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
Цитата(Дмитрий Ветра @ Jan 18 2011, 18:31)  Есть два варианта:
- сохраняем в ОЗУ; .equ ZH_save 0x0100 .equ ZL_save 0x0101
sts ZH_save,ZH sts ZL_ save,ZL - копируем регистровую пару;
movw r3:r2,ZH:ZL
в целом:
lds ZH, ZH_save ; восстанавливаем указатель lds ZL, ZL_save
in r16, UDR ; записываем принятый байт st Z+, r16
sts ZH_save, ZH ; сохраняем указатель sts ZL_save, ZL Спасибо, а то я разбаловался языками верхнего уровня, а на уровне "кирпичиков" топчусь как лось на одном месте
|
|
|
|
|
Jan 18 2011, 17:26
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(HoboTech @ Jan 18 2011, 18:39)  Я так понял Ваш код будет работать только в случае, когда в основном теле программы не изменяется содержимое ZH и ZL. Меня интересует именно сохранение адреса, на который указывает регистровая пара Z после постинкремента, в переменную Если, конечно, такое возможно всё верно . Если Вы предполагаете изменять ZL ZH , то хотя бы напишите , что именно будет происходить в основной программе . Тогда будет понятно , каким образом сохранять Z . Толи записывать его в регистры хранения , толи в SRAM, а может будет достаточно push и pop Я Вам переписал предыдущий пост- сохранив Вам Z для прерывания и для MAIN
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Jan 21 2011, 11:19
|

Участник

Группа: Участник
Сообщений: 17
Регистрация: 27-09-10
Из: Харьков
Пользователь №: 59 762

|
И все таки туго что-то до меня доходит работа с адресами... что означает следующий код: Код .DSEG tmp: .byte 1
...
lds ZL,tmp что я заношу в регистр ZL значение байта, который находился в памяти по адресу tmp или что я записываю значение младшего байта самого адреса?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|