Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры
Войти
Регистрация
Восстановить пароль
 
 
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
1

область памяти XDATA для микроконтроллера MSC-51 (i8051, АТ89С52)

07.10.2019, 21:51. Просмотров 426. Ответов 24
Метки нет (Все метки)

здр.. имеется следующее задание.. нужно в области памяти XDATA задать массив целых беззнаковых двухбайтных чисел arr[i].. все это должно быть написано в среде Keil uVision 4 для микроконтроллера MCS-51 (8051, АТ89С52).. пжл, проверьте правильность написания мной кода конкретно для этого задания и вообще всей структуры программы.. прошу указать мне и исправить ошибки, если таковые имеются..
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
;Общие для модуля директивы
$NOMOD51
$NOLIST
$INCLUDE(REG52.INC)                    ; или #include <reg52.h>
$LIST
 
?STACK SEGMENT  IDATA              ; размещение сегмента стека ?STACK в главном модуле
       RSEG     ?STACK
       DS   20
 
xdata_seg  SEGMENT XDATA            
        RSEG    xdata_seg          
arr:        dd 1,2,3,4,5           ; в области памяти XDATA задан массив целых беззнаковых двухбайтных чисел arr[i]            
 
;переход на стартовый адрес (0) в главном модуле
CSEG AT 0
LJMP START
 
START:      MOV SP,#?STACK-1           ; установка начала стека
 
;здесь размещается остальной код
 
CSEG AT 0
 
END                                    ; конец файла
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.10.2019, 21:51
Ответы с готовыми решениями:

Выбор чисел из массива в диапазоне от 105 до 115 для микроконтроллера i8051
Как можно выбирать числа от 105 до 115

Область памяти для переменной и её значения. Это одна и та же область?
Добрый день! Задумался над таким вопросом. Есть переменная, а есть её значение. При создани...

Куплю Zyxel MSC-1000A (MSC-1000) Управляющий контроллер. Б/У
Куплю бу модуль управления DSLAM Zyxel MSC-1000A или MSC-1000. Стоят в шасси IES-2000 или IES-3000.

Подскажите область фактической памяти для работы *com - программы
Подскажите начало диапазона фактических адресов памяти для работы собственно-ручно писанной *com -...

Как выделить произвольную область в памяти для записи
Есть некоторое устройство на PCIe шине. Оно формирует в режиме master транзакции и передает поток...

24
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
08.10.2019, 16:26  [ТС] 2
хорошо, семейство MCS-51 (i8051) - восьмиразрядные микроконтроллеры.. но как тогда объявить и инициализировать массив байт в области памяти XDATA, чтобы потом их можно было обрабатывать как двухбайтные числа?
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
08.10.2019, 17:16 3
Цитата Сообщение от proc3nt Посмотреть сообщение
arr: dd 1,2,3,4,5
DW
DD - это 4 байта

А во вторых - с XDATA такая конструкция не получится.
Сначала завести массив в CODE, выделить место в XDATA (через DS) и скопировать из CODE в XDATA
1
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
08.10.2019, 17:39  [ТС] 4
Intel4004, а в каком порядке должны располагаться байты в словах в XDATA в i8051? также как в i386 младший байт по младшему адресу? или в обычном варианте младший байт по старшему адресу? так же как мне можно будет проверить то, скопировались или нет в XDATA данные?
0
08.10.2019, 17:39
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
08.10.2019, 18:04 5
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "AT89X52.H"
 
#define Array_Size  (Array_Source_End-Array_Source)
#define Array_Count (Array_Size/2)
 
CSEG    AT  0x0000
        LJMP    Startup
 
?STACK      SEGMENT IDATA
RSEG        ?STACK
Stack:      DS  20
 
?C_ARRAY    SEGMENT CODE
RSEG        ?C_ARRAY
Array_Source:   DW  1,2,3,4,5
Array_Source_End:
 
?X_ARRAY    SEGMENT XDATA
RSEG        ?X_ARRAY
Array:      DS  Array_Size
 
?STARTUP    SEGMENT CODE
RSEG        ?STARTUP
 
Startup:
    CLR EA
    MOV SP,#?STACK-1
 
//здесь надо написать код для копирования из Array_Source в Array
 
//здесь размещается остальной код
 
    LJMP    Startup
 
    END
оператор DW сам расположит слово старшим байтом вперед.
1
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
08.10.2019, 18:58  [ТС] 6
Intel4004, начал копировать.. почему-то выскакивает ошибка на инструкции mov A, @R0.. в чем дело?
*** error 65: access violation at C:0x001A : no 'execute/read' permission
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$NOMOD51
$NOLIST
$INCLUDE(REG52.INC)                
$LIST
 
?stack segment idata               
       rseg ?stack
       ds 20
         
x_array segment xdata         
       rseg x_array    
buf: ds 10
 
cseg at 0
ljmp start
 
arr: dw 1122h,3344h,5566h,7788h,9900h
arr_end:
 
start:
clr ea
mov sp,#?stack-1
 
mov dptr,#buf
mov r0,#arr
mov r1,#10
init:
mov A, @R0
    
end
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
08.10.2019, 19:35 7
Цитата Сообщение от proc3nt Посмотреть сообщение
mov r0,#arr
mov A, @R0
Ну, во первых сегмент CODE адресуется так-же как и XDATA через DPTR: MOVC A,@A+DPTR
А MOV A,@R0 - это адресация сегмента IDATA
А ошибка скорее всего потому что в настройках проекта выбран процессор без IDATA. Соответственно если в R0 лежит значение 0x80 или больше, то при выполнении адресуется неиспользуемая область.

Добавлено через 6 минут
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    MOV R0,#0
Copy:
    MOV A,R0
    MOV DPTR,#arr
    MOVC    A,@A+DPTR
    PUSH    ACC
    MOV A,R0
    ADD A,#LOW(buf)
    MOV DPL,A
    CLR A
    ADDC    A,#HIGH(buf)
    MOV DPH,A
    POP ACC
    MOVX    @DPTR,A
    INC R0
    CJNE    R0,#10,Copy
1
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
08.10.2019, 20:37  [ТС] 8
Intel4004, по сути у тебя все логично получается.. но у меня почему-то само копирование не происходит.. всегда первоначально адрес BUFF (@DPTR) равен нулю.. возможно, в начале памяти находится какая-то системная информация и не дает запись в ту область.. думаю, нужно как-то сдвинуть адреса.. скажи, что мне нужно подправить?
P.S. также ошибку выдавало на пустой сегмент ?STARTUP, я его уже удалил..
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$NOMOD51
$NOLIST
$INCLUDE(REG52.INC)                
$LIST
 
?STACK SEGMENT IDATA               
       RSEG ?STACK
       DS 20
 
?C_ARRAY SEGMENT CODE
       RSEG ?C_ARRAY
ARR: DW 1122h,3344h,5566h,7788h,9090h
         
?X_ARRAY SEGMENT XDATA        
       RSEG ?X_ARRAY       
BUF: DS 10
 
CSEG AT 0
LJMP START
 
START:
MOV SP,#?STACK-1
 
MOV R0,#0
COPY:
MOV A,R0
MOV DPTR,#ARR
MOVC A,@A+DPTR
 
PUSH ACC
 
MOV A,R0
ADD A,#LOW(BUF)
MOV DPL,A
CLR A
ADDC A,#HIGH(buf)
MOV DPH,A
    
POP ACC
 
MOVX @DPTR,A
    
INC R0
CJNE R0,#10,COPY
    
END
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 00:13 9
Цитата Сообщение от proc3nt Посмотреть сообщение
всегда первоначально адрес BUFF (@DPTR) равен нулю
А чему он должен быть равен?
Адресное пространство XDATA - 0x0000-0xffff
В XDATе всего один сегмент (?X_ARRAY), линкер естественно располагает его в начале адресного пространства (адреса 0x0000-0x00a)
В этом сегменте - всего одна переменная (BUF), занимает весь сегмент (адреса 0x0000-0x00a).
Естессно адрес этой переменной - 0x0000.

Добавлено через 4 минуты
Рекомендую ознакомиться с отличиями гарвардской и фоннеймановской архитектуры.
х51 - гарвардская, все остальные популярные процессоры (включая x86) - фоннеймановская.

Добавлено через 35 минут
hint: в кейле, в окошке memory, чтобы смотреть XDATA к адресу надо добавить префикс X
x:0 - нулевой адрес XDATA
c:0 - нулевой адрес CODE
i:0 - нулевой адрес IDATA
1
northener
09.10.2019, 01:26
  #10

Не по теме:

Цитата Сообщение от proc3nt Посмотреть сообщение
или в обычном варианте младший байт по старшему адресу?
Не пойму откуда тут взялось слово "обычном"?

0
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
09.10.2019, 13:24  [ТС] 11
northener, "обычном" здесь имеется ввиду "математическом", а не "компьютерном" варианте..
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 13:58 12
Цитата Сообщение от proc3nt Посмотреть сообщение
P.S. также ошибку выдавало на пустой сегмент ?STARTUP, я его уже удалил..
Цитата Сообщение от proc3nt Посмотреть сообщение
CSEG AT 0
LJMP START
START:
MOV SP,#?STACK-1
В примитивном варианте - так можно. В реальности - инструкцию LJMP START лучше завернуть в отдельный сегмент.
По адресу 0x0003 начинается таблица прерываний. Ваш код делает невозможным использование прерываний.

Assembler
1
2
3
4
5
6
7
CSEG AT 0   //Сегмент кода по адресу 0
LJMP START //Весь сегмент состоит из одной инструкции, размер сегмента 3 байта
 
?STARTUP SEGMENT CODE //Сегмент кода. Адрес ему назначит линкер.
       RSEG ?STARTUP
START:
MOV SP,#?STACK-1
1
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
09.10.2019, 15:11  [ТС] 13
Intel4004, почему может неправильно работать команда CJNE ?? при данных условиях все равно переходит на метку FIRST..
Assembler
1
2
3
4
5
6
7
FIRST:
.....
.....
.....
;R0=0x02
;2H=0x0002
CJNE R0,#2H,FIRST
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 15:17 14
Не может. Значит в R0 не 2
0
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
09.10.2019, 15:32  [ТС] 15
Intel4004, у меня может.. пжл, проверь последний цикл.. там должны копироваться только первые два байта из BUF в облать памяти, расположенную после BUF..
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
$NOMOD51
$NOLIST
$INCLUDE(REG52.INC)                
$LIST
 
?STACK SEGMENT IDATA               
       RSEG ?STACK
       DS 20
 
?C_ARRAY SEGMENT CODE
       RSEG ?C_ARRAY
ARR: DW 1122h,3344h,5566h,7788h,9090h
         
?X_ARRAY SEGMENT XDATA        
       RSEG ?X_ARRAY       
BUF: DS 10
RESULT: DS 9
 
CSEG AT 0
LJMP START
 
?STARTUP SEGMENT CODE
       RSEG ?STARTUP
 
START:
MOV SP,#?STACK-1
;------------------------------;
MOV R0,#0
COPY:
MOV A,R0
MOV DPTR,#ARR
MOVC A,@A+DPTR
 
PUSH ACC
 
MOV A,R0
ADD A,#LOW(BUF)
MOV DPL,A
CLR A
ADDC A,#HIGH(BUF)
MOV DPH,A
    
POP ACC
 
MOVX @DPTR,A
    
INC R0
CJNE R0,#10,COPY
;------------------------------;
 
MOV R0,#0
MOV R1,#1
FIRST:
MOV A,R0
ADD A,#LOW(BUF)
MOV DPL,A
CLR A
ADDC A,#HIGH(BUF)
MOV DPH,A
 
MOVX A,@DPTR
 
PUSH ACC
 
MOV A,R1
ADD A,#LOW(RESULT)
MOV DPL,A
CLR A
ADDC A,#HIGH(RESULT)
MOV DPH,A
    
POP ACC
 
MOVX @DPTR,A
    
INC R0
INC R1
CJNE R0,#2H,FIRST
 
END
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 15:52 16
Цитата Сообщение от proc3nt Посмотреть сообщение
CJNE R0,#2H,FIRST
END
При R0 == 2 переход на FIRST не происходит. Но на этой команде сегмент заканчивается, а выполнение продолжается. А дальше лежит сегмент данных. И первых два байта в этом сегменте (0x1122) - инструкция CALL. И совершенно случайно этот CALL(0x11) попадает на адрес(0x22) около метки FIRST.
Чтобы такие глюки не ловить - если программе дальше выполняться не надо - глуши ее:

Assembler
1
2
3
CJNE R0,#2H,FIRST
JMP $  // $ - это текущий адрес. JMP $ - это вечный цикл без выхода.
END
hint: если что-то непонятно с выполнением кода - лучше переключиться(ткнуть мышкой) в окно Disassembly и выполнять по шагам(F10/F11) там. Там все глюки с кодом видны намного лучше.
1
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
09.10.2019, 15:58  [ТС] 17
Intel4004, а если вместо jmp $ поставить nop, то будет тот же эффект?
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 16:03 18
нет, nop это просто команда которая не меняет регистров и флагов. Тупо задержка на микросекунду. После нее выполнение продолжается дальше.
JMP $ это аналог
DeadLoop: JMP DeadLoop
0
proc3nt
волшебник
1298 / 555 / 177
Регистрация: 26.05.2012
Сообщений: 1,586
09.10.2019, 16:37  [ТС] 19
Intel4004, ясно.. а можно ли как-то толкнуть/вытолкнуть в/из стек(а) именно флаг переноса?

следующий вариант вроде не годится..
Assembler
1
2
3
PUSH PSW.7
.....
POP PSW.7
или можно только весь регистр флагов, типа такого..?
Assembler
1
2
3
PUSH PSW
.....
POP PSW
0
Intel4004
9 / 9 / 0
Регистрация: 27.04.2015
Сообщений: 31
09.10.2019, 16:51 20
Цитата Сообщение от proc3nt Посмотреть сообщение
PUSH PSW
.....
POP PSW
Да, только так.
1
09.10.2019, 16:51
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.10.2019, 16:51

Извлечение данных из памяти микроконтроллера
Могу ли я используя AVR Studyo извлечь данные из EEPROM памяти,после его работы??

Ссылка, Указатель, Область памяти выделенная оператором new для указателя
Подскажите пожалуйста, как сделать ссылку на область памяти выделенную оператором new для указателя...

Создание массива в оперативной памяти микроконтроллера
Ситуация следующая: Есть микроконтроллер STM32F103VE и к нему подключен дисплей 128 на 64 точек....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.