//#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;
}
if (pdata == 0) { // порт неопределен
puts( "SPP параллельный порт не установлен." );
exit( 255 );
} else
puts(
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; //конвертируем первый символ в нижний регистр
case 'd': // стирание чипа
erase( &control );
case 'f': // запись чипа из файла
printf( "Введите имя файла: " );
gets( fname );
fsize = CHIPSIZE;
if (load_data( fname, pgmdata, &fsize ))
program( &control, pgmdata, fsize );
else {
puts( "Ошибка открытия или чтения входного файла данных." );
puts( "\nНажмите Enter для продолжения..." );
case 'g': // сравнивание содержимого чипа с файлом
printf( " Введите имя файла: " );
if (load_data( fname, pgmdata, &fsize )) {
if (!verify( &control, pgmdata, fsize )) {
} else {
puts( " Ошибка открытия или чтения входного файла данных." );
case 'h': // запись содержимого чипа в файл
xread( &control, pgmdata, CHIPSIZE );
if (!save_data( fname, pgmdata, CHIPSIZE )) {
puts("Ошибка открытия или чтения выходного файла данных.");
puts( "\Нажмите Enter для продолжения..." );
case 'i': // проверка: пустой чип или нет
if (blank( &control ))
puts( "Устройство чистое" );
else
puts( " Устройство не чистое " );
case 'j': // чтение байтов сигнатуры
signature( &control );
case 'l': // запись Lock Bit 1
lock( &control, 1 );
case 'n': // запись Lock Bit 2
lock( &control, 2 );
case 'x': // выход из программы
default:
tend(); // выключаем таймер
enable_traps();
exit( 0 );
// Чтение данных из введенного файла в указанный массив. Если
// файл меньше чем указанное количество байт, читаем полный файл
// и изменяем количество байт, чтобы отразить меньший размер файла.
// Сталкиваясь с концом файла раньше, чем удовлетворено количество
// байт – не ошибка. Если файл больше чем указанное количество байт
// читаем только указанное количество байт.
BOOLEAN load_data( fname, store, sptr )
char fname[];
BYTE store[];
int *sptr;
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 )
int bcount;
if ((fptr = fopen( fname, "wb" )) == NULL)
if (fwrite( store, 1, bcount, fptr ) != bcount)
return( FALSE ); // не удается записать в файл
// Полная очистка памяти предложенная перед программированием.
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
delay( (BIGINT)(15000 * TCVT) ); // задержка 15 мс для спада RST
// Программируем чип содержанием указанного массива данных.
// Указанное количество байт может быть меньше чем количество
// байт в массиве или чипе. Программирование всегда начинается с
// нулевого адреса.
void program( cptr, data, count )
BYTE *cptr, data[];
int count;
WORD addr;
pulse_RST( cptr, 10 ); // сброс счетчика адресов
set_function( WRITE_DATA ); // выбор функции
enable_address( cptr ); // разрешение function, PROG*
enable_data( cptr ); // разрешение шины перед записью
delay( (BIGINT)(10 * TCVT) ); // задержка function->RST
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 ); // увеличиваем счетчик адресов
// Чтение содержимого чипа в указанный массив данных
// байтов в чипе. Чтение всегда начинается с нулевого адреса.
void xread( cptr, data, count )
BYTE tmp;
set_function( READ_DATA ); // выбор функции
delay( (BIGINT)(10 * TCVT) ); // задержка address->data
data[addr] = get_data();
// Сравнение содержания чипа с указанным массивом данных.
// Указанное количество байт может быть меньше количества
// байт в чипе. Сравнение всегда начинается с нулевого адреса.
// Различия отображаются адресом несовпадающих значений и
// два байта: один – из памяти микроконтроллера, другой – тем,
// что ожидали. Возвращенное булево значение показывает
// было ли успешным сравнение.
BOOLEAN verify( cptr, data, count )
BOOLEAN flag=TRUE;
if ((tmp = get_data()) != data[addr]) {
if (flag) {
printf("Несовпадение в %.4X is %.2X sb %.2X\n", addr, tmp, data[addr] );
flag = FALSE;
return( flag );
// Определяем, стерт ли чип. Расположение отказов не определяется.
// Возвращенное булево значение указывает чистый чип или нет.
BOOLEAN blank( cptr )
BOOLEAN flag = TRUE; // значение по умолчанию – чистый
enable_address( cptr ); // разрешаем function, PROG*
for (addr=0; addr<CHIPSIZE; addr++) {
if (get_data() != 0xff) // сравнение со стертым значением
flag = FALSE; // не чистый
// Читаем байты сигнатуры.
// Первый байт в нулевом адресе, второй в первом. Когда установлены в
// 1Еh и 11h соответственно они идентифицируют АТ89С1051 контроллер.
// Третий байт во втором адресе указывает программирование 12 вольтами,
// когда установлен в FFh.
void signature( cptr )
BYTE tmp1, tmp2, tmp3;
set_function( READ_SIGNATURE ); // выбор функции
enable_address( cptr ); // разрешаем func, PROG*
tmp1 = get_data(); // чтение первого байта
tmp2 = get_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 );
// Запись указанных Lock Bits.
void lock( cptr, lbit )
int lbit;
switch (lbit) { // выбор функции
case 1:
set_function( WRITE_LOCK_1 );
case 2:
set_function( WRITE_LOCK_2 );
enable_RST( cptr ); // RST=12В
// Возвращение программатора в пассивное состояние.
void reset( 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, 0x04 );
// outp( pctrl, 0x04 ); // сигналы управления неактивны
// Данные возврата подают на линии данных программатора.
// Сначала нельзя запретить latch выходных данных программатора.
// Некоторые платы параллельного интерфейса позволяют заблокировать
// буфер выходных данных устанавливая 5-й бит в регистре управления.
BYTE get_data( void )
outp( pdata, 0xff ); // установка данных LPT порта в высокое состояние
outp( pctrl, 0x24 ); // запрещение передачи данных LPT порта
outp( pctrl, 0x26 ); // разрешение чтения буфера данных
delay( (BIGINT)(10 * TCVT) ); // задержка 10 мкс
tmp = inp( pdata ); // получение данных
return( tmp );
// Разрешение выводов программатора: address and function latches.
// PROG* (P3.2) также разрешен.
void enable_address( cptr )
// Запрещение выводов программатора: address and function latches.
// PROG* (P3.2) также запрещен.
void disable_address( cptr )
outp( pdata, (*cptr &= ~0x10) ); // установка данных
outp( pctrl, 0x08 ); // выбор control latch
// Разрешение вывода данных программатора.
void enable_data( cptr )
// Запрещение вывода данных программатора.
void disable_data( cptr )
outp( pdata, (*cptr &= ~0x20) ); // set up data
// Разрешение 12 вольт на RST.
// Обратите внимание, что RST не сможет мгновенно достигнуть
// указанного значения.
void enable_RST( cptr )
сигналы управления неактивны
// Возвращение RST к 5 вольтам.
void disable_RST( cptr )
outp( pdata, (*cptr &= ~0x80) ); // установка данных
// Генерируем низко идущий импульс на RST указанной продолжительности. // Время должно быть определено в микросекундах.
void pulse_RST( cptr, time )
int time;
// Генерируем высоко идущий импульс на XTAL1 указанной
// продолжительности. Время должно быть определено в микросекундах.
void pulse_XTAL1( cptr, time )
// Генерируем низко идущий импульс на PROG* указанной
void pulse( cptr, 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
Рис 7.1. Схема электрическая принципиальная
Все элементы схемы были выбраны командой Place/Part. Для симуляции сигналов нужно создать правило с помощью команды Pspice/New Simulation Profile, далее настроив его можно приступать к симуляции процесса. Также нужно поставить маркеры напряжения, тока в том месте в котором хотелось бы видеть процесс. В данном случае на базу транзистора должен подаваться логический сигнал с микроконтроллера, который мы создали в редакторе сигналов Stimulus Editor. Для перехода в него нужно выделить элемент DigStim, нажать на правую кнопку и выбрать Edit Pspice Stimulus. При
Рис 7.3. Главное окно Pspice A/D
В данном окне видно изменение напряжения в том месте нашей схемы в которой мы поставили маркер. Для общей видимости зависимости сигнала на коллекторе транзистора от сигнала с микроконтроллера можно вывести сигнал последнего, нажатием на 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