Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Микроконтроллеры > МК-51 массив


Автор: hawk1 02.04.12, 18:22
Подскажите, как написать программу на асм 51, обрабатывающую массив хранящийся во внешней памяти.

Автор: medved_68 02.04.12, 19:35
Цитата hawk1 @
Подскажите, как написать программу на асм 51, обрабатывающую массив хранящийся во внешней памяти.

Внешняя память чего? Программ или данных? Обработка массива в чем заключается? Сортировка/изменение по маске/еще чего то там? :D

Автор: hawk1 03.04.12, 06:56
Внешняя память данных я так понял. Обработка - суммирование и поиск минимального элемента, но мне хотя бы понять как объявить массив и обратиться к его элементу.

Автор: medved_68 03.04.12, 16:58
Цитата hawk1 @
но мне хотя бы понять как объявить массив и обратиться к его элементу.

На чем писать собрался?

Добавлено
Цитата hawk1 @
на асм 51,

За вопрос извиняюсь. :D В DPTR заносишь адрес первого элемента массива. В любой регистр (назовем его Rx) количество элементов массива. И гонишь итерацию:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    cikle  MOVX A, @DPTR   ;пересылаем очередной байт массива в аккумулятор
    ....................   ;что то с ним делаем
           INC DPTR     ;увеличиваем указатель на элемент массива
           DJNZ Rx, cikle  ;цикл, пока не пройдем все элементы массива

Если элементов более 255 байт - то создаешь вложенный цикл.

Автор: hawk1 03.04.12, 17:44
Это понятно. А объявить массив как?

Автор: medved_68 03.04.12, 19:45
Цитата hawk1 @
А объявить массив как?

Если я правильно тебя понял - то через директиву DB резервируешь память.

Автор: hawk1 04.04.12, 18:46
А пример можно?

Автор: medved_68 05.04.12, 18:54
Цитата hawk1 @
А пример можно?

:blink: А чем тебе пост 4 не понравился? Мнемоника по другому не напишется... Тем более, что тебе:
Цитата hawk1 @
Это понятно.
:D

Автор: hawk1 07.04.12, 18:40
Дело в том, что размер массива, который нужно обработать, 1500. Как его инициализировать?

Автор: medved_68 07.04.12, 18:45
Цитата hawk1 @
Дело в том, что размер массива, который нужно обработать, 1500. Как его инициализировать?

1500 чего? Что ты подразумеваешь под инициализацией? Начальные установки каждого элемента во внешней памяти? Или...?

Автор: hawk1 07.04.12, 19:17
1500 элементов. Инициализация - то есть присвоение значения каждому элементу

Автор: medved_68 07.04.12, 19:19
Цитата hawk1 @
Инициализация - то есть присвоение значения каждому элементу

Эти значения должны быть вызваны откуда то или можно прямо в прошивке писать их в виде констант?

Автор: hawk1 08.04.12, 05:37
Не сказано.

Автор: medved_68 08.04.12, 07:01
Цитата hawk1 @
Не сказано.

Ну тогда в чем проблема? Есть два варианта:
1. Ты загружаешь константу в аккумулятор и выплевываешь ее в нужную ячейку внешней памяти.
Примерно так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
        MOV   A,#XX    ;где ХХ это необходимая байтовая константа
        MOVX  @DPTR,A  ;загружаем этот байт во внешнюю память по необходимому адресу.
        INC   DPTR     ;увеличиваем указатель на элемент массива
Недостаток - весьма большой объем программного кода.

2. При помощи директивы DB ты заносишь в участок памяти программ свой массив. Далее, в цикле ты извлекаешь из памяти программ байты этого массива в аккумулятор и заносишь их во внешнюю память данных.
Примерно так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    NABLE    DB   #02
             DB   #04
             DB   #FF   ;Это твои данные, которые должны находится в массиве при первоначальной инициализации
    ............
    ............
    ............
    ; где то в программе в секции начальной инициализации
             MOV   DPTR,NABLE   ;Инициализируем указатель началом массива
             XRL   A,A          ;обнуляем аккумулятор
             MOV   R0,DPL       ;Сохраняем младшую часть указателя в РОН
             MOV   R1,DPH       ;Сохраняем старшую часть указателя в РОН
             MOV   R2,A         ;Сохраняем смещение относительно начала массива
             MOV   DPTR,#XXXX   ;загружаем адрес начала массива во внешней памяти данных
             MOV   R3,DPL       ;Сохраняем младшую часть указателя в РОН
             MOV   R4,DPH       ;Сохраняем старшую часть указателя в РОН
    ;Далее простой расчет - у тебя количество элементов 1500, регистр может максимум 256 отсчетов, ;следовательно 1500/256 = 5. Т.е. Один регистр совершит полный оборот в цикле от нуля до нуля, а ;второй ;просчитает эти циклы. Т.е. получим 256*5 = 1280 элементов мы инициализируем за это цикл. Для оставшихся ;220 сделаем еще один, но с одним счетчиком, в который будет загружено значение 220 = DC        
             XRL   R5,R5         ;Обнуляем внутренний счетчик циклов
             MOV   R6,05         ;Загружаем внешний
    ;Ну и собственно сам цикл инициализации:
    CIKLE    MOV   DPL,R0       ;Восстанавливаем младшую часть указателя
             MOV   DPH,R1       ;Восстанавливаем старшую часть указателя
             MOV   A,R2         ;Восстанавливаем смещение относительно начала массива
             MOVC  A,@A+DPTR    ;Вытаскиваем из памяти программ байт для массива
             MOV   DPL,R3       ;Восстанавливаем младшую часть указателя на внешнюю память
             MOV   DPH,R4       ;Восстанавливаем старшую часть указателя на внешнюю память
             MOVX  @DPTR,A      ;Заносим байт во внешнюю память данных
             INC   DPTR         ;Увеличиваем указатель на внешнюю память программ
             MOV   R3,DPL       ;Сохраняем младшую часть указателя в РОН
             MOV   R4,DPH       ;Сохраняем старшую часть указателя в РОН
             INC   R2           ;Увеличиваем указатель на массив
             DJNZ  R5,CIKLE     ;Закрываем внутренний цикл
    ;По окончании внутреннего цикла необходимо снова переинициализировать указатели на память программ, скорректировав указатель DPTR на 256 байт, которые мы уже извлекли из памяти программ.
             MOV   DPH,R1       ;Восстанавливаем старшую часть указателя
             INC   DPH
             MOV   R1,DPH       ;Сохраняем старшую часть указателя в РОН
    ;Увеличение на 1 старшей части и даст нам в итоге 100, т.е +256.
             XRL   R2,R2        ;Обнуляем смещение относительно начала блока
             DJNZ  R6,CIRLE     ;И заряжаем следующую итерацию на 256 байт.

Как то так. Таким образом ты проинициализируешь свой массив данных, расположенный во внешней памяти данных, значениями, которые ты занесешь в ПЗУ контроллера при прошивке его памяти программ. :D

Автор: avreal 08.04.12, 19:13
Нет у 51-го команды
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    XRL REG, REG
Так что
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    mov R5, #0

Ну и всё можно упихать в один цикл, если аккуратно счётчики инициализировать.

hawk1, вопрос нескромный: внешняя память — она действительно внешняя, или микроконтроллер толстый с большой «внутренней внешней»?
Потому как если она действительно внешняя, висит на портах P2,P0 то можно через MOVX @Ri, A писать в любое место, используя порт P2 как регистр страницы.
И тогда совсем коротко:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    INIT_DATA:
        DB ...
        DB ...
     
    XRAM_ARRAY_LEN equ 1500
     
        mov DPTR, #INIT_DATA
        mov R0, #low  (XRAM_ARRAY)
        mov P2, #high (XRAM_ARRAY)
        ; Инициализируем 16-битный счётчик цикла, но хитрым образом
        mov R2, #low  (XRAM_ARRAY_LEN)
        mov R3, #high (XRAM_ARRAY_LEN+255)
     
    loop:
        clr A
        movc    A,@A+DPTR
        movx    @R0, A
        inc DPTR
        inc R0
        ; если после инкремента R0 стал 0, то нарастить страницу в порту P2
        cjne    R0, #0, no_inc_P2
        inc P2
    no_inc_P2:
        djnz R2, loop
        djnz R3, loop

Автор: avreal 08.04.12, 19:18
p.s. А еще бывают вариации 8051 с двумя DPTR, тогда вместо гонять туда-сюжа содержимое DPTR достаточно бит DPSEL в управляющем регистре инвертировать.

Автор: hawk1 16.04.12, 11:57
То же самое надо сделать на си-51, но когда я пишу
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    int mas[1500];

получаю ошибку auto segment too large

Автор: trainer 16.04.12, 12:16
Где пишешь? Локально в функции?

Автор: hawk1 16.04.12, 12:18
да

Автор: trainer 16.04.12, 17:18
В настройках компилятора надо указать использование внешнего ОЗУ.

Автор: hawk1 16.04.12, 18:00
Объявил массив так
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
     array: ds 1500
    array_address xdata array + 0

насколько это правильно?

Автор: hawk1 17.04.12, 17:49
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    void main (void) {
     
    /*------------------------------------------------
    Setup the serial port for 1200 baud at 16MHz.
    ------------------------------------------------*/
    #ifndef MONITOR51
        SCON  = 0x50;               /* SCON: mode 1, 8-bit UART, enable rcvr      */
        TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
        TH1   = 221;                /* TH1:  reload value for 1200 baud @ 16MHz   */
        TR1   = 1;                  /* TR1:  timer 1 run                          */
        TI    = 1;                  /* TI:   set TI to send first char of UART    */
    #endif
     
      while (1) {
         const int n = 1500;
         int array[1500];
         int i;
         int sum;
         int min;
         int avg;
         for (i = 0; i < n; i++)
            array[i] = rnd();  
         sum = 0;
         min = array[0];
         for (i = 0; i < n; i++)
         {
            sum += array[i];
            if (array[i] < min)
              min = array[i];
         }
         avg = sum / n;
         P0 = avg / 2 + min;
         printf("%d",P0);
      }
    }

\получаю предупреждение 'rnd'' missing function-prototype

Автор: trainer 18.04.12, 04:13
Ты C сейчас изучаешь что ли?

Автор: hawk1 18.04.12, 06:20
Попросили сделать.

Автор: Мяут-Настоящий 19.04.12, 18:33
hawk1, на си надо явно указать, что данные живут во внешней ОЗУ.

В sdcc это делается так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    char __xdata mas[100500];


В Keil ЕМНИП оно так и называется xdata.

Автор: hawk1 23.04.12, 07:18
Программу написал, как теперь проверить ее правильность?

Автор: trainer 23.04.12, 07:35
Откомпилировать? Запустить под отладчиком? Залить в реальное устройство и посмотреть?

Автор: hawk1 23.04.12, 08:26
В лбщем задание такое. Написать программу на асм 51,выполняющую обработку массива, хранящегося во внешней памяти. Алгоритм avg/2+min. Результат выводится через последователдьный порт. На си сджелал, на асм никак

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)