Руководство · Начальный · 30 min
Архитектура 8051: выводы, карта памяти и регистры
Что на самом деле содержит 8051: гарвардское ядро, четыре порта с разными свойствами, 256 байт ОЗУ и машинный цикл, который можно подсчитать.
Введение
Большинство курсов по микроконтроллерам начинается с 8051, и большинство студентов знакомится с ним как со списком фактов для запоминания: четыре порта, 128 байт ОЗУ (RAM), два таймера, шесть прерываний. Запомнить его таким образом бесполезно. Если понять его как набор осознанных компромиссов, сделанных в 1980 году — когда ОЗУ стоило реальных денег, а кристалл должен был поместиться в 40 выводов, — оно объясняет почти все принципы работы современных небольших микроконтроллеров.
Это экскурсия по архитектуре: что находится внутри корпуса, как разделена память и почему расчёт времени здесь особенно прост. В двух следующих материалах рассматриваются управление выводами и формирование PWM с помощью таймера.
«8051» — это семейство, а не кристалл
Intel представила MCS-51 в 1980 году, а затем широко лицензировала ядро, поэтому сегодня никто не покупает Intel 8051. Покупают совместимый компонент — чаще всего AT89S52 от Atmel (ныне Microchip), в котором к исходной ROM, стираемой ультрафиолетом (UV), добавлена flash-память, перепрограммируемая через четыре вывода.
Различия, о которых стоит знать:
| 8051 (оригинал) | AT89S52 (то, что у вас) | |
|---|---|---|
| Память программ | 4 KB ROM | 8 KB flash-памяти |
| Внутреннее ОЗУ | 128 байт | 256 байт |
| Таймеры | 2 | 3 |
| Источники прерываний | 5 | 6 |
| Программирование | Масочная ROM на заводе | В системе, через выводы SPI |
Всё остальное — набор команд, порты, расположение регистров и расчёт времени — идентично. Учебные материалы, написанные для 8051, без изменений применимы к кристаллу на вашем столе.
Что находится внутри корпуса
В одном 40-выводном DIP-корпусе находится полноценный компьютер: 8-разрядный ЦП (CPU), flash-память программ, ОЗУ данных, три таймера/счётчика, полнодуплексный последовательный порт, контроллер прерываний и четыре 8-разрядных порта ввода-вывода. Операционной системы нет, и ничего не работает, кроме вашего кода.
Четыре вывода вообще не являются вводами-выходами, и все четыре должны быть подключены правильно, прежде чем что-либо заработает: XTAL1 и XTAL2 для кварца, RST для цепи сброса и EA для выбора внутренней или внешней памяти программ. Если EA подключён неверно, кристалл молча ничего не делает.
Гарвардская архитектура: код и данные — разные миры
8051 хранит память программ и память данных в отдельных адресных пространствах. Адрес 0x0030 означает одно для выборки команды и совершенно другое для обращения к данным: это разные виды памяти, к которым обращаются разными командами.
Именно поэтому компиляторы C для 8051 заставляют задуматься о классах памяти, которые другие платформы скрывают. Строковый литерал, который вы никогда не изменяете, должен находиться в памяти code, где есть запас в килобайты. Если по ошибке поместить его в data, он съест часть тех 256 байт, которые нужны для всего остального:
// In code (flash) — costs nothing from your 256 bytes of RAM.
const char code banner[] = "Line follower v1";
// In RAM — 17 of your 256 bytes, gone, for a string that never changes.
const char banner_bad[] = "Line follower v1";
В Arduino это различие и есть причина существования PROGMEM. В 8051 это не оптимизация, а разница между программой, которая помещается, и программой, которая не помещается.
Карта внутреннего ОЗУ
256 байт внутреннего ОЗУ — не единая область временной памяти. Они разделены на области с разными возможностями, и знание того, где какая область находится, составляет большую часть смысла карты памяти.
00h–1Fh — четыре банка регистров. R0–R7 не являются фиксированными адресами: это окно в один из четырёх 8-байтовых банков, выбранный двумя битами (RS0 и RS1) в слове состояния программы. Переключение банков — запись двух битов, поэтому это очень дешёвый способ выделить собственные регистры обработчику прерывания вместо сохранения и восстановления восьми регистров.
20h–2Fh — побитовая адресация. Эти 16 байтов также адресуются как 128 отдельных битов, от 00h до 7Fh. В 8051 есть настоящие команды работы с одним битом — SETB, CLR, JB, JNB, — поэтому флаг здесь занимает один бит и одну команду, а не байт и маску. Поэтому компиляторы C для 8051 предлагают тип bit, которого нет больше нигде.
30h–7Fh — временные данные и стек. Восемьдесят байт для переменных и стека вызовов, и именно этот ресурс реально заканчивается.
80h–FFh — две памяти, один диапазон адресов. Прямая адресация здесь обращается к специальным функциональным регистрам; косвенная адресация (через R0 или R1) обращается к верхним 128 байтам ОЗУ. Номера одинаковы, памяти разные, а выбор задаётся формой используемой команды. У исходного 8051 с 128 байтами верхнего ОЗУ просто нет.
Специальные функциональные регистры — это просто память
Каждое периферийное устройство 8051 управляется записью байтов по адресам прямого диапазона 80h–FFh. API нет — есть регистр, и установка бита в нём меняет работу микросхемы.
| Регистр | Адрес | Что управляет |
|---|---|---|
P0 P1 P2 P3 |
80h, 90h, A0h, B0h | Четыре порта ввода-вывода |
TMOD |
89h | Выбор режима таймеров 0 и 1 |
TCON |
88h | Биты запуска таймеров и флаги переполнения |
TH0 TL0 TH1 TL1 |
8Ch, 8Ah, 8Dh, 8Bh | Регистры счёта таймеров |
SCON SBUF |
98h, 99h | Управление последовательным портом и данные |
IE IP |
A8h, B8h | Разрешение и приоритет прерываний |
PSW |
D0h | Флаги и биты выбора банка регистров |
SP |
81h | Указатель стека |
Запись P1 = 0x0F; в C — это запись по адресу 90h, и восемь выводов меняют состояние. Именно в этой непосредственности заключается весь интерес к кристаллу как учебному устройству.
Расчёт времени
Один машинный цикл на классическом ядре 8051 составляет двенадцать периодов генератора, а большинство команд занимает один или два машинных цикла. Это фиксированное отношение позволяет точно рассчитать время выполнения, а не измерять его:
machine cycle = 12 / f_osc
at 11.0592 MHz : 12 / 11 059 200 = 1.085 µs
at 12 MHz : 12 / 12 000 000 = 1.000 µs
Цикл из трёх команд, выполняемых за один машинный цикл, на частоте 11.0592 MHz каждый раз занимает 3.26 µs: без кэша, конвейера и нестабильности из-за прерываний, кроме той, которую вы включаете сами. Немногие современные процессоры позволяют рассуждать так, и именно поэтому 8051 до сих пор встречается в критичных по времени периферийных устройствах.
Почему частота кварца равна 11.0592 MHz
Это число кажется произвольным, но это не так. Последовательный порт получает скорость передачи делением тактового сигнала машинного цикла, и 11.0592 MHz делится на стандартные скорости передачи точно:
baud = f_osc / (12 × 32 × (256 − TH1))
11.0592 MHz, TH1 = 253 : 11 059 200 / (12 × 32 × 3) = 9600.0 ✓ exact
12 MHz, TH1 = 253 : 12 000 000 / (12 × 32 × 3) = 10416.7 ✗ 8.5% off
UART допускает несколько процентов ошибки; ошибка 8.5% портит каждый кадр. Если ваша плата 8051 выводит по последовательному порту мусор, сначала проверьте кварц, а не код.
Чего у 8051 нет
Две отсутствующие возможности определяют каждый проект на 8051, и ни одна из них не очевидна из списка функций:
- Нет аналого-цифрового преобразователя. Для чтения потенциометра, термистора или аналогового датчика линии нужен внешний аналого-цифровой преобразователь (ADC), например ADC0804. Функции
analogRead()здесь нет. - Нет аппаратного PWM. Ничто на кристалле не создаёт сигнал с переменным рабочим циклом. Для затемнения светодиода (LED) или задания скорости двигателя нужно самостоятельно построить PWM из прерывания таймера и заплатить за это временем ЦП.
В Arduino Uno есть обе возможности. Честное сравнение такое: 8051 — не худший Arduino, а нижний слой под ним, из которого убрали удобства, чтобы увидеть, что именно они делали.
Когда всё идёт не так
- Плата не подаёт признаков жизни и ничего не греется. Проверьте, что EA (вывод 31) находится на +5 V. Если он плавает или заземлён, кристалл выбирает код из внешней памяти, которой нет, и не выполняет ничего, без каких-либо симптомов.
- Он постоянно сбрасывается или вообще не запускается. Сброс в 8051 активен по высокому уровню. Цепь включения питания — конденсатор 10 µF от +5 V к RST и резистор 10 kΩ от RST к земле. Если подключить её как сброс с активным низким уровнем, кристалл останется в постоянном сбросе.
- Последовательный вывод содержит мусор. Почти всегда виноват кварц. Кристалл на 12 MHz не может получить стандартные скорости передачи.
- Переменные повреждают друг друга без причины. Скорее всего, закончились 80 байт по адресам 30h–7Fh или стек вырос вниз до переменных. Проверьте карту памяти, которую выводит компилятор.
- Регистры неожиданно меняются внутри прерывания. Указатель стека сбрасывается в 07h, поэтому стек начинается с 08h — это и есть банк регистров 1. Либо измените SP в коде запуска, либо не используйте банк 1.
Исследуйте граф
Входит в эти сборки
Проекты и учебные пути, в которые входит это руководство.
Дополнительные материалы