printf(
" Введите имя файла: " );
gets(
fname );
fsize
= CHIPSIZE;
if
(load_data( fname, pgmdata, &fsize )) {
if
(!verify( &control, pgmdata, fsize )) {
puts(
"\nНажмите Enter для продолжения..." );
gets(
pch );
}
}
else {
_clearscreen(
_GCLEARSCREEN );
puts( "
Ошибка открытия или чтения входного файла данных." );
puts(
"\nНажмите Enter для продолжения..." );
gets(
pch );
}
break;
case 'h': //
запись содержимого чипа в файл
printf(
" Введите имя файла: " );
gets(
fname );
xread(
&control, pgmdata, CHIPSIZE );
if
(!save_data( fname, pgmdata, CHIPSIZE )) {
_clearscreen(
_GCLEARSCREEN );
puts("Ошибка
открытия или чтения выходного файла данных.");
puts(
"\Нажмите Enter для продолжения..." );
gets(
pch );
}
break;
case 'i': //
проверка: пустой чип или нет
_clearscreen(
_GCLEARSCREEN );
if
(blank( &control ))
puts(
"Устройство чистое" );
else
puts(
" Устройство не чистое " );
puts(
"\nНажмите Enter для продолжения..." );
gets(
pch );
break;
case 'j': //
чтение байтов сигнатуры
_clearscreen(
_GCLEARSCREEN );
signature(
&control );
puts(
"\nНажмите Enter для продолжения..." );
gets(
pch );
break;
case 'l': //
запись Lock Bit 1
lock(
&control, 1 );
break;
case 'n': //
запись Lock Bit 2
lock(
&control, 2 );
break;
case 'x': //
выход из программы
default:
_clearscreen(
_GCLEARSCREEN );
tend(); //
выключаем таймер
enable_traps();
exit(
0 );
}
}
}
// Чтение данных из введенного
файла в указанный массив. Если
// файл меньше чем указанное
количество байт, читаем полный файл
// и изменяем количество байт,
чтобы отразить меньший размер файла.
// Сталкиваясь с концом файла
раньше, чем удовлетворено количество
// байт – не ошибка. Если файл
больше чем указанное количество байт
// читаем только указанное
количество байт.
BOOLEAN load_data( fname, store, sptr )
char fname[];
BYTE store[];
int *sptr;
{
FILE *fptr;
int nbytes;
if ((fptr = fopen( fname,
"rb" )) == NULL)
return( FALSE ); //
не удается открыть файл
nbytes = fread( store, 1,
*sptr, fptr );
if (ferror( fptr ))
return( FALSE ); //
не удается прочитать файл
if (feof( fptr )) //
проверка на конец файла
*sptr = nbytes; //
уменьшаем количество байт
fclose( fptr );
return( TRUE );
}
// Запись данных из указанного
массива в обозначенный файл.
// Возвращает булево значение,
обозначающее успех или неудачу.
BOOLEAN save_data( fname, store, bcount )
char fname[];
BYTE store[];
int bcount;
{
FILE *fptr;
if ((fptr = fopen( fname,
"wb" )) == NULL)
return( FALSE ); //
не удается открыть файл
if (fwrite( store, 1, bcount,
fptr ) != bcount)
return( FALSE ); //
не удается записать в файл
fclose( fptr );
return( TRUE );
}
// Полная очистка памяти
предложенная перед программированием.
void erase( cptr )
BYTE *cptr;
{
reset( cptr ); //
сброс по умолчанию
set_function( CHIP_ERASE ); //
выбор функции
enable_address( cptr ); //
разрешение func, PROG*
delay( (BIGINT)(10 * TCVT) ); //
задержка 10мкс
enable_RST( cptr ); //
RST=12v
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс фронт RST ->PROG*
pulse( cptr, 10000 ); //
применение 10 мс импульса PROG*
delay( (BIGINT)(10 * TCVT) ); //
задержка PROG*->adr/data
reset( cptr ); //
сброс по умолчанию
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс для спада RST
}
// Программируем чип содержанием
указанного массива данных.
// Указанное количество байт может
быть меньше чем количество
// байт в массиве или чипе.
Программирование всегда начинается с
// нулевого адреса.
void program( cptr, data, count )
BYTE *cptr, data[];
int count;
{
WORD addr;
reset( cptr ); //
сброс по умолчанию
pulse_RST( cptr, 10 ); //
сброс счетчика адресов
set_function( WRITE_DATA ); //
выбор функции
enable_address( cptr ); //
разрешение function, PROG*
enable_data( cptr ); //
разрешение шины перед записью
delay( (BIGINT)(10 * TCVT) ); //
задержка function->RST
enable_RST( cptr ); //
RST=12v
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс фронт RST ->PROG*
for (addr=0; addr<count;
addr++) {
set_data( data[addr]
); // применение data
delay( (BIGINT)(10 *
TCVT) ); // задержка data->PROG*
pulse( cptr, 100 ); //
применение 100 мкс импульса PROG*
delay( (BIGINT)(1500 *
TCVT) ); // задержка 1.5 мс для записи
pulse_XTAL1( cptr, 10
); // увеличиваем счетчик адресов
}
reset( cptr ); //
сброс по умолчанию
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс для спада RST
}
// Чтение содержимого чипа в
указанный массив данных
// Указанное
количество байт может быть меньше чем количество
// байтов в чипе. Чтение всегда
начинается с нулевого адреса.
void xread( cptr, data, count )
BYTE *cptr, data[];
int count;
{
BYTE tmp;
WORD addr;
reset( cptr ); //
сброс по умолчанию
pulse_RST( cptr, 10 ); //
сброс счетчика адресов
set_function( READ_DATA ); //
выбор функции
enable_address( cptr ); //
разрешение function, PROG*
for (addr=0; addr<count;
addr++) {
delay( (BIGINT)(10 *
TCVT) ); // задержка address->data
data[addr] =
get_data();
pulse_XTAL1( cptr, 10
); // увеличиваем счетчик адресов
}
reset( cptr ); //
сброс по умолчанию
}
// Сравнение содержания чипа с
указанным массивом данных.
// Указанное количество байт может
быть меньше количества
// байт в чипе. Сравнение всегда
начинается с нулевого адреса.
// Различия отображаются адресом
несовпадающих значений и
// два байта: один – из памяти
микроконтроллера, другой – тем,
// что ожидали. Возвращенное
булево значение показывает
// было ли успешным сравнение.
BOOLEAN verify( cptr, data, count )
BYTE *cptr, data[];
int count;
{
BYTE tmp;
BOOLEAN flag=TRUE;
WORD addr;
reset( cptr ); //
сброс по умолчанию
pulse_RST( cptr, 10 ); //
сброс счетчика адресов
set_function( READ_DATA ); //
выбор функции
enable_address( cptr ); //
разрешение function, PROG*
for (addr=0; addr<count;
addr++) {
delay( (BIGINT)(10 *
TCVT) ); // задержка address->data
if ((tmp = get_data())
!= data[addr]) {
if (flag) {
_clearscreen(
_GCLEARSCREEN );
}
printf("Несовпадение в
%.4X is %.2X sb %.2X\n", addr, tmp, data[addr] );
flag =
FALSE;
}
pulse_XTAL1( cptr, 10
); // увеличиваем счетчик адресов
}
reset( cptr ); //
сброс по умолчанию
return( flag );
}
// Определяем, стерт ли чип.
Расположение отказов не определяется.
// Возвращенное булево значение
указывает чистый чип или нет.
BOOLEAN blank( cptr )
BYTE *cptr;
{
BYTE tmp;
BOOLEAN flag = TRUE; //
значение по умолчанию – чистый
WORD addr;
reset( cptr ); //
сброс по умолчанию
pulse_RST( cptr, 10 ); //
сброс счетчика адресов
set_function( READ_DATA ); //
выбор функции
enable_address( cptr ); //
разрешаем function, PROG*
for (addr=0; addr<CHIPSIZE;
addr++) {
delay( (BIGINT)(10 *
TCVT) ); // задержка address->data
if (get_data() !=
0xff) // сравнение со стертым значением
flag =
FALSE; // не чистый
pulse_XTAL1( cptr, 10
); // увеличиваем счетчик адресов
}
reset( cptr ); //
сброс по умолчанию
return( flag );
}
// Читаем байты сигнатуры.
// Первый байт в нулевом адресе,
второй в первом. Когда установлены в
// 1Еh и 11h соответственно они
идентифицируют АТ89С1051 контроллер.
// Третий байт во втором адресе
указывает программирование 12 вольтами,
// когда установлен в FFh.
void signature( cptr )
BYTE *cptr;
{
BYTE tmp1, tmp2, tmp3;
reset( cptr ); //
сброс по умолчанию
pulse_RST( cptr, 10 ); //
сброс счетчика адресов
set_function( READ_SIGNATURE ); //
выбор функции
enable_address( cptr ); //
разрешаем func, PROG*
delay( (BIGINT)(10 * TCVT) ); //
задержка address->data
tmp1 = get_data(); //
чтение первого байта
pulse_XTAL1( cptr, 10 ); //
увеличиваем счетчик адресов
delay( (BIGINT)(10 * TCVT) ); //
задержка address->data
tmp2 = get_data(); //
чтение второго байта
pulse_XTAL1( cptr, 10 ); //
увеличиваем счетчик адресов
delay( (BIGINT)(10 * TCVT) ); //
задержка address->data
tmp3 = get_data(); //
чтение третьего байта
printf( "signature byte
1: %.2X\n", tmp1 );
printf( "signature byte
2: %.2X\n", tmp2 );
printf( "signature byte
3: %.2X\n", tmp3 );
reset( cptr ); //
сброс по умолчанию
}
// Запись указанных Lock Bits.
void lock( cptr, lbit )
BYTE *cptr;
int lbit;
{
reset( cptr ); //
сброс по умолчанию
switch (lbit) { //
выбор функции
case 1:
set_function(
WRITE_LOCK_1 );
break;
case 2:
set_function(
WRITE_LOCK_2 );
break;
}
enable_address( cptr ); //
разрешение function, PROG*
enable_RST( cptr ); //
RST=12В
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс фронт RST ->PROG*
pulse( cptr, 100 ); //
применение 100 мкс импульса PROG*
delay( (BIGINT)(10 * TCVT) ); //
задержка PROG*->adr/data
reset( cptr ); //
сброс по умолчанию
delay( (BIGINT)(15000 * TCVT)
); // задержка 15 мс для спада RST
}
// Возвращение программатора в
пассивное состояние.
void reset( cptr )
BYTE *cptr;
{
outp( pdata, 0 ); //
установка данных
outp( pctrl, 0x08 ); //
выбираем control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x0c ); //
выбираем нижний адрес latch
outp( pctrl, 0x0d ); //
latch data
outp( pctrl, 0x0c );
outp( pctrl, 0x00 ); //
выбираем верхний адрес latch
outp( pctrl, 0x01 ); //
latch data
outp( pctrl, 0x00 );
outp( pdata, 0xff ); //
установка данных
outp( pctrl, 0x04 ); //
выбираем data latch
outp( pctrl, 0x05 ); //
latch data
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
*cptr = 0; //
запись значения control latch
}
// Подпрограмма выбора функции.
// Записывается только 3 младших
значащих бита
void set_function( func )
BYTE func;
// Запись указанного значения в
программатор.
void set_data( outdata )
BYTE outdata;
{
outp( pdata, outdata ); //
установка выходных данных
outp( pctrl, 0x04 ); //
выбор data latch
outp( pctrl, 0x05 ); //
latch data
outp( pctrl, 0x04 );
// outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Данные возврата подают на линии
данных программатора.
// Сначала нельзя запретить latch
выходных данных программатора.
// Некоторые платы параллельного интерфейса
позволяют заблокировать
// буфер выходных данных
устанавливая 5-й бит в регистре управления.
BYTE get_data( void )
{
BYTE tmp;
outp( pdata, 0xff ); //
установка данных LPT порта в высокое состояние
outp( pctrl, 0x24 ); //
запрещение передачи данных LPT порта
outp( pctrl, 0x26 ); //
разрешение чтения буфера данных
delay( (BIGINT)(10 * TCVT) ); //
задержка 10 мкс
tmp = inp( pdata ); //
получение данных
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
return( tmp );
}
// Разрешение выводов
программатора: address and function latches.
// PROG* (P3.2) также разрешен.
void enable_address( cptr )
BYTE *cptr;
// Запрещение выводов
программатора: address and function latches.
// PROG* (P3.2) также запрещен.
void disable_address( cptr )
BYTE *cptr;
{
outp( pdata, (*cptr &=
~0x10) ); // установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Разрешение вывода данных
программатора.
void enable_data( cptr )
BYTE *cptr;
// Запрещение вывода данных
программатора.
void disable_data( cptr )
BYTE *cptr;
{
outp( pdata, (*cptr &= ~0x20)
); // set up data
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Разрешение 12 вольт на RST.
// Обратите
внимание, что RST не сможет мгновенно достигнуть
// указанного
значения.
void enable_RST( cptr )
BYTE *cptr;
сигналы управления неактивны
// Возвращение RST к 5 вольтам.
// Обратите
внимание, что RST не сможет мгновенно достигнуть
// указанного
значения.
void disable_RST( cptr )
BYTE *cptr;
{
outp( pdata, (*cptr &=
~0x80) ); // установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Генерируем низко идущий импульс
на RST указанной продолжительности. // Время должно быть определено в
микросекундах.
void pulse_RST( cptr, time )
BYTE *cptr;
int time;
// Генерируем высоко идущий
импульс на XTAL1 указанной
// продолжительности. Время должно
быть определено в микросекундах.
void pulse_XTAL1( cptr, time )
BYTE *cptr;
int time;
outp( pctrl, 0x08 );
// Генерируем низко идущий импульс
на PROG* указанной
// продолжительности. Время должно
быть определено в микросекундах.
void pulse( cptr, time )
BYTE *cptr;
int time;
// Задержка на указанную
продолжительность. Каждый тик равен
// 1/1193180 секунды (0,838мкс)
void delay( xcount )
BIGINT xcount;
{
BIGINT count0;
// printf( "Счет таймера=
%lu\n", xcount );
tread(); //
чтение счета таймера
count0 = tcount; //
установка начального значения
do //
повторение пока дельта >= указанного значения
tread(); //
чтение значения таймера
while (tcount - count0 <
xcount);
}
7. Моделирование схемы в системе
автоматизированного проектирования OrCAD
Для проведения моделирования части схемы использовался САПР OrCAD
версии 9.2. Моделировался ключ на транзисторе КТ815А. Так как в библиотеки
OrCAD-а не содержат отечественных элементов, то для моделирования был взят
аналогичный западный транзистор. На рисунке 4.1 изображена схема электрическая
принципиальная, подготовленная в схемном редакторе OrCAD Capture.
Рис 7.1. Схема
электрическая принципиальная
Все элементы схемы были выбраны командой
Place/Part. Для симуляции сигналов нужно создать правило с помощью команды
Pspice/New Simulation Profile, далее настроив его можно приступать к симуляции
процесса. Также нужно поставить маркеры напряжения, тока в том месте в котором
хотелось бы видеть процесс. В данном случае на базу транзистора должен подаваться
логический сигнал с микроконтроллера, который мы создали в редакторе сигналов
Stimulus Editor. Для перехода в него нужно выделить элемент DigStim, нажать на
правую кнопку и выбрать Edit Pspice Stimulus. При
выполнении этого действия мы переходим в Stimulus Editor в
котором создаем логический сигнал, например как показано на рисунке 4.1
Рис 7.2. Главное окно
Stimulus Editor`а с сигналам sig
Рис 7.3. Главное окно
Pspice A/D
Создав этот сигнал можно переходить к симуляции нашего процесса, при
нажатии Pspice/Run мы переходим в Pspice A/D (рис 4.3)
В
данном окне видно изменение напряжения в том месте нашей схемы в которой мы
поставили маркер. Для общей видимости зависимости сигнала на коллекторе
транзистора от сигнала с микроконтроллера можно вывести сигнал последнего,
нажатием на Trace/Add Trace… мы увидим цифровой сигнал который попадает на базу
транзистора.
Выводы.
В работе рассмотрено создание
программатора микроконтроллеров Atmel серии АТ89 с
подключением к LPT-порту компьютера. Была разработана электрическая
схема, печатная плата и сборочный чертеж, показывающие, что программатор
микроконтроллеров Atmel серии АТ89 может быть
спроектирован и после изготовлен на элементной базе,
выпускаемой предприятиями СНГ.
Требования технического задания выполнены
полностью.
Все выполненные
расчеты подтверждают работоспособность конструкции и позволяют сделать вывод об
успешном ее функционировании при воздействии на нее допустимых климатических и
механических воздействий.
Графическая часть и
приведенные в настоящем проекте результаты расчетов подтверждают, что задание
на курсовое проектирование выполнено в полном объеме.
Литература.
1.
Голубков А.
Программатор МК Atmel серии АТ89. – Радио, 2003, №9,
с. 24 – 25.
2.
Рюмик С.
“Параллельный” программатор для АТ89. – Радио, 2004, №2, с. 28 – 31.
3.
Мактас М. Я.
Восемь уроков по P-CAD - М.: солон-Пресс, 2003.-224с.:ил.
4.
AT89 Series
Programmer Interface <http://www.atmel.com/dyn/resources/
prod_documents/APCPGM.EXE >.
5.
Ханке Х.-И.,
Фабиан Х. Технология производства радиоэлектронной аппаратуры: Пер. с нем./ Под
ред. В. Н. Черняева. – М.: Энергия. 1980. – 464 с., ил.
6.
Ванін В. В., Бліок А. В.,
Гнітецька Г. О. Оформлення конструкторської документації. Навчальний посібник.
– К.: “Каравела”, 2003. – 160 с.
7.
Партала О.
Н. Радиокомпоненты и материалы: Справочник. – К.: Радіоаматор, М.: КУбК-а, 1998. – 720с.:
ил.
ГОСТ 23751-86. Платы
печатные. Основные параметры и размеры.
Страницы: 1, 2, 3, 4, 5, 6
|