перевод с языка на язык может либо исказить мысль больше, чем "правильный" перевод, либо выглядеть коряво. А тут мы переводим текст с чего-то типа бейсик-программы, записанной словами С на собственно С
Тем более, что изменён только набор кода с клавиатуры, оставлено даже его поведение таким, как было, просто антидребезг и проверка нажатия новой клавиши реализованы несколько по-другому - гибче и расширяемее. Заодно убрана эту ужасающая задержка через wait() с "магическими числами". Всё остальное просто переписано без goto.
/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.4 Standard
Automatic Program Generator
© Copyright 1998-2004 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.come-mail:office@hpinfotech.com
Project : Пример 10
Version : 1
Date : 07.03.2006
Author : Belov
Company : Home
Comments:
Кодовый замок
Chip type : ATtiny2313
Clock frequency : 4,000000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 32
*****************************************************/
#include <tiny2313.h>
#define klfree 0x77F // Код состояния при полностью отпущеных кнопках
#define kzad 3000 // Код задержки при сканировании
#define kandr 30 // Константа антидребезга
#define bsize 30 // Размер буфера для хранения кода
unsigned char flz; // Флаг задержки
unsigned int bufr[bsize]; // Буфер в ОЗУ для хранения кода
#pragma warn-
eeprom unsigned char klen; // Ячейка для хранения длины кода
eeprom unsigned int bufe[bsize]; // Буфер в EEPROM для хранения кода
#pragma warn+
// Прерывание по переполнению Таймера 1
interrupt[TIM1_OVF]
void timer1_ovf_isr(void)
{
flz = 1; // Устанавливаем флаг задержки
}
// Прерывание по совпадению в канале A Таймера 1
interrupt[TIM1_COMPA]
void timer1_compa_isr(void)
{
flz = 1; // Устанавливаем флаг задержки
}
// Функция опроса клавиатуры и антидребезга
unsigned int incod(void)
{
unsigned int cod0 = 0; // Локальные переменные
unsigned int cod1;
unsigned char k;
for (k = 0; k < kandr; k++) { // Цикл антидребезга
cod1 = PINB & 0x7; // Формируем первый байт кода
cod1 = (cod1 << 8) + (PIND & 0x7F); // Формируем полный код состояния клавиатуры
if (cod0 != cod1) { // Сравниваем со старым кодом
k = 0; // Если не равны, сбрасываем счетчик
cod0 = cod1; // И присваиваем новое значение старому коду
}
}
return cod1;
}
// Процедура формирования задержки
void wait(unsigned char kodz)
{
if (kodz == 1)
TIMSK = 0x40; // Выбор маски прерываний по таймеру
else
TIMSK = 0x80;
TCNT1 = 0; // Обнуление таймера
flz = 0; // Сброс флага задержки
#asm("sei"); // Разрешаем прерывания
if (kodz != 2)
while (flz == 0); // Цикл задержки
}
// Основная функция
void main(void)
{
unsigned char ii; // Указатель массива
unsigned char i; // Вспомогательный указатель
unsigned int codS; // Старый код
PORTB = 0xE7; // Порт B
DDRB = 0x18;
PORTD = 0x7F; // Порт D
DDRD = 0x00;
TCCR1A = 0x00; // Таймер/Счетчик 1
TCCR1B = 0x03;
TCNT1 = 0;
OCR1A = kzad;
ACSR = 0x80; // Аналоговый компаратор
while (1) { // Главный цикл
while (incod() != klfree); // Ожидание отпускания кнопок
while (incod() == klfree); // Ожидание нажатия кнопок
ii = 0;
// набор кода до конца буфера либо до таймаута между клавишами
while(1) {
#asm("cli"); // Запрещаем прерывания
wait(1); // Задержка 1-го типа
codS = incod(); // Ввод кода и запись, как старого
bufr[ii++] = codS; // Запись очередного кода в буфер
if (ii >= bsize) // Проверка конца буфера
break;
wait(2); // Задержка 2-го типа
while( flz == 0) { // пока не закончился интервал
if (incod() != codS) // Проверка не изменилось ли состояние
continue; // переход на набор кода
}
break; // таймаут - конец набора
}
// реакция на набранный код
if (PINB.7 == 1) { // Проверка переключателя режимов
//------------------------------ Проверка кода
if (klen != ii) // Проверка длины кода
continue; // главный цикл
for (i = 0; i < ii; i++)
if (bufe[i] != bufr[i]) // Проверка самого кода
continue; // главный цикл
} else { //------------------------------ Запись кода в EEPROM
klen = ii; // Запись длины кода
for (i = 0; i < ii; i++)
bufe[i] = bufr[i]; // Запись всех байтов кода
}
//------------------------------ Открывание замка
PORTB .4 = 1;
// Открываем замок
wait(3); // Задержка 3-го типа
PORTB .4 = 0; // Закрываем замок
}
}
p.s. сам я к этому вопросу не отношусь "религиозно" - goto применяю, но только если он действительно улучшает ситуацию.