Видя вашу ошибку ERROR L121: IMPROPER FIXUP, эта проблема очень типична для Keil при работе с большими номерами прерываний (свыше 31) у микроконтроллеров STC.
Простыми словами: компилятор C51 в Keil изначально поддерживает только номера прерываний от 0 до 31. Вы используете STC8A8K64D4, где некоторые прерывания (например, UART2, UART3, UART4 или PCA) часто имеют номер больше 31 — и если указать их напрямую, возникает данная ошибка.
Вы упомянули, что уже использовали «программу расширения номеров прерываний» с официального сайта, но ошибка всё ещё появляется. Обычно это происходит потому, что процедура выполнена не полностью. Ниже я предложу два решения. Рекомендую сначала попробовать решение 1 (если вы уже устанавливали программу, вероятнее всего, вы просто неправильно её вызвали).
Решение 1: Правильное использование официального инструмента STC для расширения номеров прерываний
В программе STC-ISP есть встроенный инструмент. Многие считают, что достаточно просто «установить», но на самом деле перед каждой компиляцией нужно либо запускать Keil через этот инструмент, либо заменять системные файлы.
- Найдите инструмент: Откройте STC-ISP, перейдите во вкладку справа «Настройки моделирования Keil», там найдите кнопку «Добавить модель и заголовочные файлы в Keil».
- Примечание: Эта операция добавляет не только модель, но и автоматически устанавливает плагин для расширения номеров прерываний.
- Повторно добавьте: Независимо от того, делали ли вы это ранее, ещё раз нажмите эту кнопку и выберите путь установки Keil (например,
C:\\Keil_v5), затем подтвердите.
- Проверьте плагин: После успешного добавления перейдите в папку проекта Keil, найдите каталог
\\Keil\\C51\\BIN. В нём должен быть файл C51.EXE. Если расширение установлено успешно, STC фактически заменил или исправил C51.EXE на версию, поддерживающую большие номера прерываний.
- Пересоберите проект: Закройте Keil, снова откройте свой проект и нажмите Rebuild (не просто Build). Проверьте, исчезла ли ошибка.
Решение 2: Ручной переход через ассемблер (самый надёжный «жёсткий» способ)
Если после выполнения первого решения ошибка остаётся, возможно, инструмент расширения не сработал из-за прав системы и т.п. В этом случае рекомендуется использовать переход через ассемблер — самый надёжный метод, не зависящий от патчей компилятора.
Пример кода:
Допустим, ваша функция прерывания изначально была такой (предположим, номер прерывания 46):
void UART4_ISR(void) interrupt 46
{
// Ваш код обработки прерывания
}
Измените на следующее:
// 1. Основная функция прерывания: без ключевого слова interrupt, обычная функция
void UART4_ISR(void)
{
// Ваш код обработки прерывания (без изменений)
}
// 2. В области ассемблера задайте переход: направьте вектор прерывания на эту функцию
void UART4_ISR_Entry(void) interrupt 46
{
// Встроенный ассемблер: переход к реальной функции
__asm
LJMP _UART4_ISR
__endasm;
}
Ключевые моменты:
- Имя функции в ассемблере должно начинаться с подчёркивания:
_UART4_ISR (компилятор C51 автоматически добавляет подчёркивание перед именами функций в ассемблере).
- Если используется линковщик
LX51, синтаксис немного отличается, но приведённый выше способ универсален для Keil.
Рекомендации
- Сначала зайдите в STC-ISP и повторно нажмите «Добавить модель и заголовочные файлы», убедитесь, что путь указан правильно (должен вести в корневую папку Keil).
- Если ошибка сохраняется, не тратьте время на диагностику инструмента, сразу переходите к решению 2 (переход через ассемблер). Да, этот способ требует на несколько строк кода больше, но он гарантированно избавит вас от ошибки L121, отлично переносится между проектами, и именно его используют многие опытные разработчики STC.