Заметки на полях
В оформлении процедуры заложен один потенциальный баг: между выполнением приема байта (процедура in_com) и его анализом (cpi temp…) может «вклиниться» прерывание, и содержимое temp будет, скорее всего, испорчено. Чтобы избежать этой ошибки, можно поступить двояко: либо запретить на время все прерывания (по крайней мере, пока идет анализ), либо каждый обработчик прерывания начинать с команды push temp и заканчивать командой pop temp (что в больших программах может быть довольно сложно осуществить на практике). Между тем, учитывая относительную редкость обращения через UART, вероятность такого совпадения чрезвычайно мала (в данном случае ее можно оценить, как отношение среднего времени выполнения цикла анализа к промежутку между прерываниями Timer 0, что составит величину порядка 0,1 % — один шанс из 1000). И за все время работы по подобной схеме автор ни разу не получил такого сбоя. Потому я не стал усложнять программу, но, строго говоря, это неправильно, и грамотный преподаватель программирования обязательно сделал бы замечание. Чтобы соблюсти все правила, можно, например, в процедуру in_com вставить команду запрещения прерываний cli сразу по выходу из цикла опроса (перед оператором out udr, temp), а команду разрешения прерываний sei — в текст основной программы сразу после метки Gcykle. Только в этом случае следует помнить, что использование процедуры in_com (например, для отладки) всегда должно сопровождаться командой sei, иначе МК просто «сдохнет» в какой-то момент (зависнет). Кроме того, прерывания будут тогда запрещены и при выполнении команд, поступающих с компьютера, а это в общем случае не всегда желательно. Чтобы освободить себя от подобных размышлений, я и отказался от этой возможности. В крайнем случае команда с компьютера пропадет, ничего страшного — то же самое может быть при простом сбое обмена. Тем не менее помнить о том, что подобные баги возможны, следует всегда, в других случаях это может оказаться очень критичным.
В данном случае мы договариваемся, что значение $Е0 означает команду на перезапись коэффициентов в памяти, а значение $Е2 — чтение ранее записанных значений. Естественно, в первом случае программа обязана ожидать «сверху» дополнительно еще 8 байт значений, а во втором — наоборот, прочесть записанные в EEPROM коэффициенты и выдать их «наверх». Если же принятый байт не равен ни одной из этих величин, то программа спокойно возвращается по метке Gcykle и продолжает опрос бита RXC до следующего отправленного ей байта.
Для единообразия записи текста процедуры приема и отправки не вызываются напрямую, а дополнительно структурированы. Процедура приема организуется так:
рrос_Е0: ;записать коэффициенты +8 байт
rcall WriteKoeff
rjmp Gcykle