Таблица
6.
|
|
Байты сигнатуры
|
Микросхема
|
|
(Hex)
|
|
|
1
|
2
|
3
|
АТ89С1051
|
1Е
|
11
|
Нет
|
AT89C1051U
|
1Е
|
12
|
Нет
|
АТ89С2051
|
1Е
|
21
|
Нет
|
AT89C2051x2
|
1Е
|
22
|
Нет
|
АТ89С4051
|
1Е
|
41
|
Нет
|
АТ89С51
|
1Е
|
51
|
FF
|
АТ89С51-ХХХХ-5
|
1Е
|
51
|
05
|
AT89LV51
|
1Е
|
61
|
FF
|
АТ89С52
|
1Е
|
52
|
FF
|
АТ89С52-хххх-5
|
1Е
|
52
|
05
|
AT89LV52
|
1Е
|
62
|
FF
|
AT89S53
|
1Е
|
53
|
Нет
|
AT89LS53
|
1Е
|
63
|
Нет
|
АТ89С55
|
1E
|
55
|
FF
|
АТ89С55-ХХХХ-5
|
1E
|
55
|
05
|
AT89LV55
|
1Е
|
65
|
FF
|
AT89S8252
|
1Е
|
Нет
|
AT89LS8252
|
1Е
|
82
|
Нет
|
Программа автоматически определяет тип
установленного в одну из панелей микроконтроллера, анализируя для этого его
сигнатуру – два или три байта, специально записанные в постоянной памяти.
Перечень сигнатур микроконтроллеров семейства АТ89 приведен в таблице 6. Если
все байты сигнатуры равны 0FFH, отсутствует в панели или неисправен микроконтроллер,
а возможно – не включено питание программатора.
Рекомендуемая операционная среда – MS
DOS. Пользователям Windows следует запускать программу, предварительно перезагрузив
компьютер в режиме MS DOS или установить такой режим в свойствах файла. Иначе
программирование микросхем придется повторять по три-четыре раза подряд, пока
не прекратятся сообщения об ошибках верификации.
Весь процесс программирования занимает
не более одной-двух минут, а собственно загрузка FLASH-памяти – максимум
10...15 с. Команды, список которых выведен на экран монитора, подают, нажимая
клавиши с буквами латинского алфавита. Регистр (верхний или нижний) не имеет
значения.
Имя двоичного файла, данные из которого
должны быть загружены в память микроконтроллера, вводят после подачи команды
"Чтение файла". Содержимое этой памяти можно предварительно
прочитать и сохранить в аналогичном файле (команда "Запись в файл").
При сверке содержимого памяти с данными из файла (команда "Сверка с файлом")
возможно появление на экране сообщений, подобных такому:
В ячейке FLASH 039A = FF ?! 6В
Это означает, что а ячейке FLASH-памяти
(памяти программ) микроконтроллера по адресу 39АН записан код 0FFH вместо 6ВН,
указанного в файле.
6.2. Исходный текст программы.
Программа написана на языке
программирования Borland C++
// Программа для AT89C51/C52/C1051/C1052
программатора.
#include <stdio.h>
#include <string.h>
#include <graph.h>
#include <dos.h>
#define FALSE 0
#define TRUE -1
//#define PBASE 0x378 //
LPT1 базовый адрес
//#define PBASE 0x278 //
LPT2 базовый адрес
//#define PDATA (PBASE+0)
//#define PSTAT (PBASE+1)
//#define PCTRL (PBASE+2)
#define CHIPSIZE 2048 //
AT89C1052 размер FLASH-памяти
#define TCVT (1.19318) //
постоянная преобразования времни
//
частота порядка 1E6
// Коды четырехбитных функций (передача
в P3.6; P3.5; P3.4; P3.3).
#define WRITE_DATA 0xe
#define READ_DATA 0xc
#define WRITE_LOCK_1 0xf
#define WRITE_LOCK_2 0x3
#define CHIP_ERASE 0x1
#define READ_SIGNATURE 0x0
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned int BOOLEAN;
typedef unsigned long int BIGINT;
BOOLEAN load_data( char *, BYTE *, int *
);
BOOLEAN save_data( char *, BYTE *, int );
void erase( BYTE * );
void program( BYTE *, BYTE *, int );
void xread( BYTE *, BYTE *, int );
BOOLEAN verify( BYTE *, BYTE *, int );
BOOLEAN blank( BYTE * );
void signature( BYTE * );
void lock( BYTE *, int );
void reset( BYTE * );
void set_function( BYTE );
void set_data( BYTE );
BYTE get_data( void );
void enable_address( BYTE * );
void disable_address( BYTE * );
void enable_data( BYTE * );
void disable_data( BYTE * );
void enable_RST( BYTE * );
void disable_RST( BYTE * );
void pulse_RST( BYTE*, int );
void pulse_XTAL1( BYTE*, int );
void pulse( BYTE *, int );
void delay( BIGINT );
extern void tinit( void );
extern void tend( void );
extern void tread( void );
extern void disable_traps( void );
extern void enable_traps( void );
WORD pctrl, pdata; // Адреса регистра
данных и регистра управления //LPT-порта
BIGINT tcount = 0L; //
счет таймера
main(argc, argv)
int argc;
char *argv[];
{
FILE *fptr;
int fsize;
BYTE pgmdata[CHIPSIZE], control
= 0;
char *pch, fname[20];
WORD far *p_lpt1 = (WORD far
*)0x00400008;
WORD far *p_lpt2 = (WORD far
*)0x0040000a;
if ((argc > 1) &&
((pch = strpbrk( argv[1], "12" )) != NULL)) {
switch (*pch) {
case '1': //
LPT1
pdata =
*p_lpt1;
pctrl =
*p_lpt1 + 2;
break;
case '2': //
LPT2
pdata =
*p_lpt2;
pctrl =
*p_lpt2 + 2;
break;
}
if (pdata == 0) { //
порт неопределен
puts(
"SPP параллельный порт не установлен." );
exit( 255 );
}
} else {
puts(
"Параллельный порт 1 или 2 должен быть определен в командной строке."
);
puts( "
Использование: <fname> <LPT1 | LPT2>" );
exit( 255 );
}
tinit(); //
запускаем таймер
disable_traps(); //
запрещаем ctl-C и ctl-break
while (TRUE) {
_clearscreen(
_GCLEARSCREEN );
puts( "Стирание
чипа\t\tD\n" );
puts( "Программа
из файла \tF" );
puts( "Сравнение
данных на чипе с файлом\tG" );
puts( "Запись в
файл\t\tH\n" );
puts( "Проверка:
чистый чип или нет\t\tI\n" );
puts( "Чтение
сигнатуры\t\tJ\n" );
puts( "Запись
Lock Bit 1\tL" );
puts( "Запись
Lock Bit 2\tN\n" );
puts(
"Выход\t\t\tX\n\n" );
printf( "Ваш
выбор: " );
gets( pch );
*pch |= 0x20;
//конвертируем первый символ в нижний регистр
switch (*pch) {
case 'd': //
стирание чипа
erase(
&control );
break;
case 'f': //
запись чипа из файла
printf(
"Введите имя файла: " );
gets(
fname );
fsize
= CHIPSIZE;
if
(load_data( fname, pgmdata, &fsize ))
program(
&control, pgmdata, fsize );
else
{
_clearscreen(
_GCLEARSCREEN );
puts(
"Ошибка открытия или чтения входного файла данных." );
puts(
"\nНажмите Enter для продолжения..." );
gets(
pch );
}
break;
case 'g': //
сравнивание содержимого чипа с файлом
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;
{
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;
{
outp( pdata, ((func << 5)
| 0x1f) );
//
Установка 3-х младших бит функции
outp( pctrl, 0x00 ); //
выбираем старший адрес latch
outp( pctrl, 0x01 ); //
latch data
outp( pctrl, 0x00 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Запись указанного значения в
программатор.
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;
{
outp( pdata, (*cptr |= 0x10) ); //
установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Запрещение выводов
программатора: 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;
{
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 ); //
очистка данных
}
// Запрещение вывода данных
программатора.
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;
{
outp( pdata, (*cptr |= 0x80) ); //
установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Возвращение 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;
{
outp( pdata, (*cptr |= 0x40) ); //
установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
delay( (BIGINT)(time * TCVT) ); //
ждем указанное количество
outp( pdata, (*cptr &=
~0x40) ); // установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Генерируем высоко идущий
импульс на XTAL1 указанной
// продолжительности. Время должно
быть определено в микросекундах.
void pulse_XTAL1( cptr, time )
BYTE *cptr;
int time;
{
outp( pdata, (*cptr |= 0x02) ); //
установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
delay( (BIGINT)(time * TCVT) ); //
ждем указанное количество
outp( pdata, (*cptr &=
~0x02) ); // установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Генерируем низко идущий импульс
на PROG* указанной
// продолжительности. Время должно
быть определено в микросекундах.
void pulse( cptr, time )
BYTE *cptr;
int time;
{
outp( pdata, (*cptr |= 0x04) ); //
установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
delay( (BIGINT)(time * TCVT) ); //
ждем указанное количество
outp( pdata, (*cptr &=
~0x04) ); // установка данных
outp( pctrl, 0x08 ); //
выбор control latch
outp( pctrl, 0x09 ); //
latch data
outp( pctrl, 0x08 );
outp( pctrl, 0x04 ); //
сигналы управления неактивны
outp( pdata, 0 ); //
очистка данных
}
// Задержка на указанную
продолжительность. Каждый тик равен
// 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. Платы
печатные. Основные параметры и размеры.