Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Микроконтроллеры > МК-51 массив |
Автор: hawk1 02.04.12, 18:22 |
Подскажите, как написать программу на асм 51, обрабатывающую массив хранящийся во внешней памяти. |
Автор: medved_68 02.04.12, 19:35 |
Цитата hawk1 @ Подскажите, как написать программу на асм 51, обрабатывающую массив хранящийся во внешней памяти. Внешняя память чего? Программ или данных? Обработка массива в чем заключается? Сортировка/изменение по маске/еще чего то там? |
Автор: hawk1 03.04.12, 06:56 |
Внешняя память данных я так понял. Обработка - суммирование и поиск минимального элемента, но мне хотя бы понять как объявить массив и обратиться к его элементу. |
Автор: medved_68 03.04.12, 16:58 |
На чем писать собрался? Добавлено За вопрос извиняюсь. В 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 |
Если я правильно тебя понял - то через директиву DB резервируешь память. |
Автор: hawk1 04.04.12, 18:46 |
А пример можно? |
Автор: medved_68 05.04.12, 18:54 |
А чем тебе пост 4 не понравился? Мнемоника по другому не напишется... Тем более, что тебе: |
Автор: 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 08.04.12, 05:37 |
Не сказано. |
Автор: medved_68 08.04.12, 07:01 |
Ну тогда в чем проблема? Есть два варианта: 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 байт. Как то так. Таким образом ты проинициализируешь свой массив данных, расположенный во внешней памяти данных, значениями, которые ты занесешь в ПЗУ контроллера при прошивке его памяти программ. |
Автор: 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. Результат выводится через последователдьный порт. На си сджелал, на асм никак |