Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Универсальный программатор

Предлагаю вашему вниманию небольшой проект универсального Лего-программатора. Всем нам известно, что из конструктора Лего можно собрать все, что угодно. Во многом все зависит только от вашей фантазии.

Иногда в практике электронщика появляется проблема, связанная с программированием какой нибудь микросхемы флеш памяти. Как поступить? Покупать программатор – дорого, да, и пройдет время и он не поймет какую нибудь новую микросхему. Отдать кому нибудь – но кому  и опять деньги платить надо. Думаю, что в данной ситуации лучше всего собрать универсальный программатор самому. Ведь на самом деле задача программирования микросхемы памяти является достаточно примитивной. Необходимо на определенные выводы микросхемы подать определенные сигналы в определенной последовательности. То есть надо создать цифровой автомат. Если у вас есть минимальный опыт в работе с микроконтроллерами, то потратив не особенно много времени на реализацию это проекта, вы сделаете устройство, которое с легкостью сможете использовать для программирования чего угодно, внося при этом лишь небольщие изменения в конструкцию и программы. Необходимо лишь взглянуть на документацию по микросхеме, которую вы хотите запрограммировать.  А для управления программатором будем использовать компьютер. Что для этого надо – сущие пустяки.

  1. Колодка в которую можно вставить микросхему для программирования (самый важный компонент нашей системы).
  2. То, к чему подключим колодку – любой микроконтроллер, имеющий достаточное количество выводов для подключения, и с которым вы имеете достаточный опыт работы.
  3. Макетная плата, кому какая будет удобней.
  4. Несколько всяких деталек.
  5. Компьютер, имеющий последовательный порт, с подключенным интернетом  для  управления программатором и развлечения, пока идет процесс программирования.
  6. Установленная на компьютере система программирования.
  7. Конечно же, комплект документации на все эти штуки, который вы найдете в интернете.

В моем случае была необходимость запрограммировать микросхему SST49LF004B. Эта микросхема используется в качестве BIOS на многих системных платах. Для реализации проекта были выбраны:

Колодка от старой системной платы, выпаяная феном. К колодке аккуратно припаяна гребенка проводов, взятых из шлейфа жесткого диска. В качестве микроконтроллера использован 40- выводной корпус AVR микроконтроллера  ATMEGA16 c кварцевым резонатором на 11.0592 МГц. Макетная плата для монтажа без пайки. Несколько навесных компонентов, таких как резисторы, конденсаторы, регулятор напряжения.

Схема программатора

При монтаже особое внимание надо уделить качеству разводки питания и установке блокирующих конденсаторов. Настоятельно рекомендую распаять один керамический конденсатор непосредственно на колодке для программирования микросхемы. Да, еще понадобится переходник для коммуникационного порта. Я использовал готовый, оставшийся от бог знает, какого разобранного устройства. Его можно собрать на паре транзисторов  или на микросхеме типа MAX232. Стабилизатор напряжения, собранный на регуляторе, имеет перемычку, определяющую выходное напряжение 3.3 В или 5.0 В. Микроконтроллер программируется на 5 В, затем работает и программирует  SST49LF004B на 3.3 В. Собираем все собранные штучки на монтажной плате и, соблюдая полярность, подключаем питание. Полную принципиальную схему не привожу, ибо макет, показанный на фотографии достаточно нагляден и собирается из того, что есть в наличии. Обращаю внимание лишь на то, что в соединении коммуникационных портов используются линии GND, RXD, TXD , а также RTS со стороны программатора (CTS со стороны компьютера). Ниже привожу фотографии готового программатора, не правда ли, простенько выглядит?

Готовый программатор

Собственно программатор ...

Готовый программатор

                                             ...и то, что к нему еще надо добавить.

Программное обеспечение создавалость по принципу Copy – Paste для решения конкретной задачи в кратчайшее время, поэтому отнестесь к качеству кода с пониманием. Программа для микроконтроллера писалась на Си в среде WinAVR под AVR Studio 4. При компиляции использовался ключ оптимизации –О1. Если вы используете другой кварц, необходимо изменить соответствующие значения, в зависимости от скорости обмена по последовательному интерфейсу.

#define F_CPU 11059200UL
UBRRH = 0; // Baud rate 38400 (for CPU clock 11.0592 MHz)
UBRRL = 17;

Запуск программатора происходит при посылке на последовательный порт (USART) соответствующего байта:

            1 - прочитать идентификатор микросхемы (для SST49LF004B два байта)

            2 - считать данные

            3 – стереть данные

            4 – записать данные

            5 -  прочитать 1к байт (для отладки)

Процедура wait1() используется для внесения небольшой дополнительной задержки, уж больно длинные проводочки использовались в схеме программатора. Звуковой сигнал используется как индикатор готовности,  да и просто прикольно. Все остальное закоментировано в тексте программы или достаточно очевидно. Далее, полный исходный текст программы, реализующий алгоритм программирования микросхемы SST49LF004B. Такой алгоритм имеют многие микросхемы, например W39V040A, 49LF040A, firmwsre hub SST49LF004A и др. Чаще всего они используются для реализации BIOS или Firmware различных устройств. Извиняюсь за коменты на английском языке, просто у меня тут все на английском.

/*
-----------------------------------------------------------------------
 Flash programming for SST49LF004B in parallel Programming mode
  
 Version	 1.0	
Date 		12-nov-2011
MCU		 AVR ATMEGA16
 MCU clock 	11.0592 MHz, Communication - Baud rate 38400, 8-N-1

 Pins
 Port A - address A7-A0
 Port C - Address A10-A8
 Port B - data
 Port D - control
-----------------------------------------------------------------------
*/
#define F_CPU 11059200UL
#define BytesQty 524288

#include 
//#include 
//#include 
#include 
#include 
#include 

//control pins (PortD)
#define SPEAKER 7
#define RTS_ 6
#define RST_ 5
#define RC_ 4
#define OE_ 3
#define WE_ 2
// TXD 1
// RXD 0

//old my frienfs from assembler - sbi and cbi
#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))

#ifndef NULL
#define NULL    ((void *)0)
#endif

uint32_t Haddr = 0x3FFFF;  //0x3FFFF high address for SST49LF004B
uint32_t _Address;
uint32_t Address;
uint32_t Address1;
uint8_t data;
uint8_t j=0;
uint8_t i;
uint8_t tmp;
uint8_t tmp1;
uint8_t buff[4];

//MCU init
static void MCUInit(void)
{
	ACSR =   0b10000000; // Analog comparator is OFF
	MCUCSR = 0b10000000; // JTAG desabled

	UCSRB = (1<<RXEN)|(1<<TXEN); // USART enabled
	UCSRC = 0b10000110; 	// Mode 8-N-1
	UBRRH = 0;		// Baud rate 38400 (for CPU clock 11.0592 MHz)
	UBRRL = 17;

	DDRB =   0b00000000; // Data 
	PORTB =  0b11111111; // Pullup rezistors are on
	DDRA = 	 0b11111111; // Address A7-A0
	DDRC =	 0b11111111; // Address A10-A8
	DDRD =	 0b11111110; // Output
	PORTD =  0b11111111; // Control outputs
	
	_delay_ms(1);
	cbi(PORTD, RST_); //reset
	_delay_ms(1);
	sbi(PORTD, RST
	_delay_ms(10);
	cli();	//all interrupts desabled
}

//------------------------------------------
//a little wait ;)
static void wait1() {
for(j=0;j<2;j++){}
}

//------------------------------------------
// Be..e..ee..p
static void beep() {
	for( i=0;i<100;i++){
	cbi(PORTD, SPEAKER);
	_delay_ms(1);
	sbi(PORTD, SPEAKER);
	_delay_ms(1);
	}
}

//------------------------------------------
static void USART_Receive(){
	while (!(UCSRA & (1<<RXC))); // Wait for data to be received 
	tmp = UDR;  // Get and return received data from buffer 
}

//------------------------------------------
static void USART_SendByte(uint8_t Data){
	while((UCSRA&(1<<UDRE)) == 0); // Wait if a byte is being transmitted
	UDR = Data; // Transmit data 
}

//------------------------------------------
static void WriteByte(uint32_t A, uint8_t d){
	_Address = A;
	DDRB = 0b11111111;
		PORTA = (uint8_t) _Address;
		PORTC = (uint8_t)( _Address>>8);
		wait1();
		cbi(PORTD, RC_); //Lock Row address
		wait1();
		PORTA = (uint8_t)( _Address>>11);
		PORTC = (uint8_t)( _Address>>19);
		wait1();
		cbi(PORTD, WE_);
		wait1();
	PORTB = d;
		wait1();
		sbi(PORTD, RC_); //Lock Column address
		wait1();
		sbi(PORTD, WE_);
	DDRB = 0b00000000;
		wait1();
}

//------------------------------------------
uint8_t ReadByte(uint32_t A){
	_Address = A;
	PORTB = 0b11111111;
	DDRB = 0b00000000;
		PORTA = (uint8_t) _Address;
		PORTC = (uint8_t)( _Address>>8);
		wait1();
		cbi(PORTD, OE_); //Flash Output enable
		cbi(PORTD, RC_);
		wait1();
		PORTA = (uint8_t)( _Address>>11);
		PORTC = (uint8_t)( _Address>>19);
		wait1();
		sbi(PORTD, RC_);
		wait1();
		sbi(PORTD, OE_); //Flash Output desable
		return PINB;
}

//------------------------------------------
//Reading of data block
static void ReadBlock (uint32_t bytes){
 for (Address=0; Address<bytes; Address++) {
	buff[0] = ReadByte(Address);
	USART_SendByte(buff[0]);
	}
}

//------------------------------------------
//Chip erase
static void ChipErase () {
	WriteByte(0x5555,0xAA); 
	WriteByte(0x2AAA,0x55);
	WriteByte(0x5555,0x80);
	WriteByte(0x5555,0xAA); 
	WriteByte(0x2AAA,0x55);
	WriteByte(0x5555,0x10); 
	for (i=0; i<3; i++) _delay_ms(100); //Chip-Erase Time < 100 ms
}

//------------------------------------------
// Reading of two ID bytes
static void SoftwIde() {
	sbi(PORTD, OE_);
	DDRB = 0b11111111;
	wait1();

	//Enter to software ID Entry
	WriteByte(0x5555,0xAA); 
	WriteByte(0x2AAA,0x55);
	WriteByte(0x5555,0x90);
	_delay_ms(1);
	//Read ID bytes
	buff[0] = ReadByte(0x0000);
	buff[1] = ReadByte(0x0001);

	USART_SendByte(buff[0]);
	USART_SendByte(buff[1]);

	//Leave software ID Entry
	WriteByte(0x5555,0xAA); 
	WriteByte(0x2AAA,0x55);
	WriteByte(0x5555,0xF0);
}

//------------------------------------------
// Byte-Program
static void ProgrammByte(uint32_t A1, uint8_t d1){
	WriteByte(0x5555,0xAA); 
	WriteByte(0x2AAA,0x55);
	WriteByte(0x5555,0xA0);
	wait1();
	WriteByte(A1,d1); //maximum Byte-Program time < 20 usec for SST49LF004B
	wait1(); //additional wait is time of waiting of the next byte
}

//------------------------------------------
int main(void){

	MCUInit();

	beep();
	beep();

	for (;;){

	cbi(PORTD, RTS_); //RTS ON for COM Port

	USART_Receive();

	if (tmp == 0x31) {	//Chip Id reading, output - 2 bytes
		SoftwIde();
		beep();
		}
	if (tmp == 0x32) {	//Reading data block (arg. is bytes q-ty)
		ReadBlock (BytesQty);
		beep();
		}
	if (tmp == 0x33) {  //Chip erase,It's clear ;)
		ChipErase ();
		beep();
		}
	if (tmp == 0x34) {  //Writing data block
		for (Address1 = 0; Address1 < BytesQty; Address1++){
			cbi(PORTD, RTS_); //RTS ON for COM Port
			wait1();
			USART_Receive();
			tmp1 = tmp;
			sbi(PORTD, RTS_); //RTS OFF for COM Port
			Address = Address1;
			ProgrammByte(Address, tmp1);
			}
		beep();
		}
	if (tmp == 0x35) {  //Reading 1K data block
		ReadBlock (1024);
		beep();
		}
	}
}

Теперь перейдем к компьютеру. Для управления программатором используется компьютер с программой, написанной на С++ в среде Microsoft Visual C++ 2010 Express под операционкой Windows 7. На самом деле, подойдет любой компьютер с любой операционкой, а программу можно написать хоть на Паскале. Главное, чтобы у вас был опыт в этом. А если опыта нет, то для электронщика, не очень желаюшего стать программистом, рекомендую освоить Visual Вasic.  Освоив, вы поймете, какой мощный у вас появится помощник. 

Программа для компьютера написана достаточно небрежно. Просто была взята форма, туда были набросаны кнопки и текстовые окошки и по событию «щелчок на левой кнопке» писались соответствующие процедуры.

Так это выглядит программный интерфейс после прочтения ID и блока данных в 1 кБ:

Lego

 Здесь приведу лишь  некоторые важные процедуры из программы.

Инициализация коммуникационного порта (COM1):

HANDLE hCom;
DCB dcb;
DWORD d;
DWORD EvtMask = 0;

void CommPortInit() {

if( hCom != NULL) CloseHandle( hCom );

hCom = CreateFile( L"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING ,0, NULL);

GetCommState (hCom, &dcb);
dcb.BaudRate = CBR_38400;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
SetCommState (hCom, &dcb);

SetCommMask (hCom,  EV_RLSD );

COMMTIMEOUTS cto;
cto.ReadIntervalTimeout = 0;
cto.ReadTotalTimeoutMultiplier = 100;
cto.ReadTotalTimeoutConstant = 0;
cto.WriteTotalTimeoutMultiplier = 0;
cto.WriteTotalTimeoutConstant =0;
SetCommTimeouts (hCom, &cto);

Чтение блока данных (SIZE – количество байт для чтения):

#define SIZE 524288  //512 kB
char buff[SIZE];
char buff1[SIZE];
HANDLE hFile;
HANDLE hFile1;

void ReadComPort(int lng){
				 for (i=0; i< SIZE; i++){
				 ReadFile( hCom, buff1, 1, &d, NULL );
				 buff[i] = buff1[0];
				 }
Чтение данных из микросхемы и запись в файл "flash_r.bin", :
private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
				 textBox1 -> Text = "Reading ...";
				PurgeComm (hCom, PURGE_RXCLEAR);
				TransmitCommChar(hCom, 2); //Transmit command "2"
				Sleep(10);

				ReadComPort(SIZE);  //512kB

			 hFile = CreateFile( L"flash_r.bin", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			 SetFilePointer( hFile, 0, NULL, FILE_END ); //Continue..
			 WriteFile( hFile, buff, SIZE, &d, NULL );
			 CloseHandle( hFile );

			 textBox1 -> Text = "File flash_r.bin is written";

			 }

Чтение  данных из микросхемы и  запись в файл "flash_r.bin",  :

private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
				 textBox1 -> Text = "Reading ...";
				PurgeComm (hCom, PURGE_RXCLEAR);
				TransmitCommChar(hCom, 2); //Transmit command "2"
				Sleep(10);

				ReadComPort(SIZE);  //512kB

			 hFile = CreateFile( L"flash_r.bin", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			 SetFilePointer( hFile, 0, NULL, FILE_END ); //Continue..
			 WriteFile( hFile, buff, SIZE, &d, NULL );
			 CloseHandle( hFile );

			 textBox1 -> Text = "File flash_r.bin is written";

			 }

Чтение данных из файла и запись в микросхему: Сравнение двух файлов:

private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {
			  hFile = CreateFile( L"flash.bin", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			  //SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
			  ReadFile( hFile, buff, SIZE, &d, NULL );

			 	textBox1 -> Text = "Writing...";
				textBox1 -> Refresh();
				PurgeComm (hCom, PURGE_TXCLEAR);
				TransmitCommChar(hCom, Command[4]);
				Sleep(50);
				
			for (i=0;i<524288;i++){
					TransmitCommChar(hCom, buff[i]);

					textBox1 -> Text = "Writing...";
					textBox1 -> Refresh();
					textBox1 -> Text = "Writing";
					textBox1 -> Refresh();
					textBox1 -> Text = "Writing.....";
					textBox1 -> Refresh();
					textBox1 -> Text = "Writing.";
					textBox1 -> Refresh();

					String^ clistr;
					sprintf_s( buff1, "%d ", i );
					clistr = gcnew String(buff1);
					richTextBox1 -> Text = clistr;  //Counter
					richTextBox1 -> Refresh();
				 }
					textBox1 -> Text = "Data to flash is writen";
		 }

Сравнение двух файлов:

private: System::Void button6_Click(System::Object^  sender, System::EventArgs^  e) {
			  hFile = CreateFile( L"flash.bin", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			  ReadFile( hFile, buff, SIZE, &d, NULL );

			  hFile1 = CreateFile( L"flash_r.bin", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			  ReadFile( hFile1, buff1, SIZE, &d, NULL );

			  j=1;
			  for (i=0;i< SIZE;i++){
			  	if (buff1[i] != buff[i]) j=0;
			  }
			  if (j==0) textBox1 -> Text = "Error";
			  else textBox1 -> Text = "OK";
			  CloseHandle( hFile);
			  CloseHandle( hFile1);
		 }
    

Самое важное это правильно сконфигурировать коммуникационный порт. Обратите внимание на RTS_CONTROL_HANDSHAKE , а также на то, что для передачи и приема данных используются разные процедуры: TransmitCommChar(hCom, buff[i]) ReadFile( hFile, buff, SIZE, &d, NULL ). Компьютер передаст байт в порт только тогда, когда установится линия RTS со стороны программатора. При программировании не происходит ни каких проверок. Мы просто устанавливаем правильные временные задержки. Для проверки мы просто считываем данные из запрограммированной микросхемы и сверяем с оригиналом. Вот, пожалуй и все. Да здравствуют микроконтроллеры и визуальные средства программирования!

Visual Studio Express 2010 C++
AVR Studio 4.19
WinAVR

Скачать файлы проекта

Автор: Андрей Романов

Список радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот
U1 Микросхема интерфейса RS232SP232ACN1 Поиск в магазине ОтронВ блокнот
U2 МК AVR 8-бит
ATmega16
1 Поиск в магазине ОтронВ блокнот
U3 Линейный регулятор
LM317
1 Поиск в магазине ОтронВ блокнот
С1-С4, С9-С12 Конденсатор100 нФ8 Поиск в магазине ОтронВ блокнот
С5 Электролитический конденсатор100 мкФ 25В1 Поиск в магазине ОтронВ блокнот
С6 Электролитический конденсатор10 мкФ 25В1 Поиск в магазине ОтронВ блокнот
С7, С8 Конденсатор15 пФ2 Поиск в магазине ОтронВ блокнот
XTAL1 кварцевый резонатор11.0592 МГц1 Поиск в магазине ОтронВ блокнот
R1 Резистор
430 Ом
1 Поиск в магазине ОтронВ блокнот
R2, R3, R5 Резистор220 Oм3 Поиск в магазине ОтронВ блокнот
R4 Резистор
1 кОм
1 Поиск в магазине ОтронВ блокнот
SP Малогабаритный динамик1 Поиск в магазине ОтронВ блокнот
J1 DB-9F1 Поиск в магазине ОтронВ блокнот
J2 коннектор AVR ISP-101 Поиск в магазине ОтронВ блокнот
Добавить все

Скачать список элементов (PDF)

Теги:

Романов Андрей Опубликована: 2011 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (3) | Я собрал (0) | Подписаться

0
Volter5000 #
Тема еще актуальна? Собрал программатор но не работает ничего, только пик при включении... я так понимаю это под LPC микрухи или же и под FWH тоже? Помогите разобраться.
Ответить
0
Drug #
Сможет ли прошить Pm49FL004T?
Ответить
0
rought #
Было бы странно, если бы это изделие ещё и работало. Очевидно, что для автора "накидать" на макетную плату деталей в произвольном порядке и так же произвольно соединить их, согласно его же принципиальной схеме, да ещё выставить это на всеобщее обозрение, в порядке вещей.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

AVR-программатор USB ASP
AVR-программатор USB ASP
FM-модуль RDA5807M Катушка Тесла
вверх