搜索附件 |
這篇文章將讓你很快掌握如何擴(kuò)充Easy 51Pro對(duì)器件的支持。當(dāng)然首先你必須先了解Keil C(如果擴(kuò)充Easy 51Pro串行編程器)或VC(如果擴(kuò)充Easy Isp下載線(xiàn))。本文只介紹基本原理,至于串口通訊的細(xì)節(jié)和程序界面的制作請(qǐng)看源代碼,里面有詳細(xì)的注釋。如果你正在學(xué)習(xí)單片機(jī)與PC的串口通訊,那么這套資料將對(duì)你非常有用。
本人編程水平有限,如果你發(fā)現(xiàn)了任何問(wèn)題,歡迎指正。可以Email通知我(nie_zq@163.net)。常見(jiàn)問(wèn)題我會(huì)貼在留言版。如果你是真心的想擴(kuò)充器件,那么我們可以用QQ討論(QQ:3813420)。如果你想用它作為商業(yè)用途,請(qǐng)先與本人聯(lián)系。
首先介紹一下我常掛在嘴變的“FID”。FID=“Function IDentification”,我E文不是很好,所以只能取出個(gè)這樣的名字。它標(biāo)識(shí)一種器件的編程方法(包括讀,寫(xiě),擦等編程操作)。AT89C51和AT89C52,AT89C55的編程方法是一樣的,所以可以用同一個(gè)FID,我把他們的FID定義為0,還有AT89CS51與AT89S52的FID=2,AT89C2051的FID=1。編程方法實(shí)際上就是控制編程過(guò)程的程序吧,C語(yǔ)言里面的程序不是叫Function嗎?
Easy 51Pro串行編程器的擴(kuò)充
編程器和上位機(jī)能協(xié)調(diào)的工作肯定是要有個(gè)通訊協(xié)議的。Easy 51Pro的通訊協(xié)議很簡(jiǎn)單。每次編程操作,上位機(jī)發(fā)給編程器18個(gè)字節(jié),編程器完成編程操作后再回應(yīng)上位機(jī)18個(gè)字節(jié)(讀,寫(xiě)過(guò)程略有不同,請(qǐng)看源程序)。這18個(gè)字節(jié)是什么東西呢?
0 | 1 | 2-17 |
編程操作的標(biāo)識(shí) | FID | 該操作相關(guān)的數(shù)據(jù) |
編程操作標(biāo)識(shí)是如何定義的?可以從源程序找到答案。
switch( ComBuf[0] )
//根據(jù)操作ID跳到不同的操作函數(shù)
{
case 0x00:
RstPro();
//編程器復(fù)位
break;
case 0x01:
ReadSign();
//讀特征字
break;
case 0x02:
Erase();
//擦除器件
break;
case 0x03:
Write();
//寫(xiě)器件
break;
case 0x04:
Read();
//讀器件
break;
case 0x05:
Lock();
//寫(xiě)鎖定位
break;
default:
SendData();
break;
}
FID已經(jīng)解釋過(guò)的,但是如何通過(guò)FID調(diào)用到控制器件編程操作的子程序呢?還是用程序說(shuō)話(huà):
在e51pro.h中定義了這樣一個(gè)結(jié)構(gòu):
struct _prowork
//定義編程器的一般操作
{
void (*fpInitPro)();
//編程前的準(zhǔn)備工作
void (*fpReadSign)();
//讀特征字
void (*fpErase)();
//擦除器件
BOOL (*fpWrite)(BYTE);
//寫(xiě)器件
BYTE (*fpRead)();
//讀器件
void (*fpLock)();
//寫(xiě)鎖定位
void (*fpProOver)();
//編程結(jié)束后的工作
};
typedef struct _prowork ProWork;
ProWork
pw;
//編程器一般操作
看見(jiàn)沒(méi)有,里面都是一堆函數(shù)的指針。沒(méi)辦法,Keil C里面沒(méi)有class,在struct里面弄一堆函數(shù)指針也別有一方風(fēng)味。
在調(diào)用編程操作(就是最上面那一堆程序switch(ComBuf[0]){…})之前,還要先進(jìn)行這一堆程序:
switch( ComBuf[1] )
//根據(jù)FID設(shè)置 (ProWork)pw 中的函數(shù)指針
{
case 0:
//at89c51編程器
PreparePro00();//<<<<<<<<<<<<<<<<<<<<<<關(guān)鍵要看這里面的東西
break;
case 1:
//at89c2051編程器
PreparePro01();
break;
case 2:
//at89s51編程器
PreparePro02();
break;
//case 3:
//擴(kuò)充器件時(shí),請(qǐng)繼續(xù)向下添加
//
break;
default:
ComBuf[0]=0xff;
ComBuf[1]=0xff;
//表示無(wú)效的操作
break;
}
看看AT89C51PRO.C中的PreparePro00()函數(shù)里面搞了些什么?
void PreparePro00()
//設(shè)置pw中的函數(shù)指針,讓主程序可以調(diào)用上面的函數(shù)
{
pw.fpInitPro=InitPro00;
pw.fpReadSign=ReadSign00;
pw.fpErase=Erase00;
pw.fpWrite=Write00;
pw.fpRead=Read00;
pw.fpLock=Lock00;
pw.fpProOver=ProOver00;
}
其中InitPro00(),ReadSign00()…..ProiOver00()這些函數(shù)都寫(xiě)在了AT89C51PRO.C中,他們實(shí)現(xiàn)了控制編程器對(duì)AT89C51編程的具體細(xì)節(jié)。例如,再看看擦除AT89C51和插除AT89S51的Flash Rom是如何實(shí)現(xiàn)的。
void Erase00()//擦除AT89C51
{
InitPro00();
//-----------------------------------------------------------------------------
//根據(jù)器件的DataSheet,設(shè)置相應(yīng)的編程控制信號(hào)
P2_6=1;
P2_7=0;
P3_6=0;
P3_7=0;
Delay_ms(1);
SetVpp12V();
Delay_ms(1);
P3_2=0;
Delay_ms(10);
P3_2=1;
Delay_ms(1);
//-----------------------------------------------------------------------------
ProOver00();
}
就是根據(jù)這個(gè)來(lái)的:
再看看AT89S51PRO.C中的:
void Erase02()//擦除AT89S51
{
InitPro02();
//-----------------------------------------------------------------------------
//根據(jù)器件的DataSheet,設(shè)置相應(yīng)的編程控制信號(hào)
OutBuf[0]=0xac;//<<<<<<<<<<<<<<<看下表中的紅框
OutBuf[1]=0x80;//<<<<<<<<<<<<<<<看下表中的紅框
SendInstrc(4);
Delay_ms(500);
//-----------------------------------------------------------------------------
ProOver02();
}
根據(jù)這個(gè)來(lái)的:
在Erase02()中看到調(diào)用了SendInstrc(4)這樣一個(gè)函數(shù),有必要解釋一下
void SendInstrc(BYTE nByte)
//用MOSI串行發(fā)送命令的同時(shí)用MISO接收相關(guān)數(shù)據(jù)
{
BYTE n;
for(n=0;n<nByte;n++)
//發(fā)送nByte個(gè)字節(jié)
{
ACC=OutBuf[n];
SCK=0;
MOSI=A_7;
//SCK低電平時(shí)輸出一位
SCK=1;
B_7=MISO;
//SCK高電平時(shí)接收一位
SCK=0;
MOSI=A_6;
…
…
MOSI=A_1;
SCK=1;
B_1=MISO;
SCK=0;
MOSI=A_0;
SCK=1;
B_0=MISO;
SCK=0;
InBuf[n]=B;
}
}
貼個(gè)圖來(lái)解釋?zhuān)?/font>
最后來(lái)看一個(gè)擴(kuò)充器件的全過(guò)程:
1.
看懂器件手冊(cè)上Programming的原理和過(guò)程細(xì)節(jié)。
2.
評(píng)估一下Easy 51Pro的硬件是否可以實(shí)現(xiàn),包括編程電壓,編程控制信號(hào)。一般可以用Isp編程的都沒(méi)問(wèn)題。
3.
讓軟件能識(shí)別出器件,這就要用傳說(shuō)中的“ChipManager”編輯了。用這個(gè)程序打開(kāi)程序目錄下的ChipList.chip文件,然后“增加器件”。也可以在空白列表上直接“增加器件”,然后保存為*.chip文件,再把這個(gè)文件合并到ChipList.chip,這就是使用“從文件導(dǎo)入”。
如果你發(fā)現(xiàn)編程方法和列表中的某FID一樣,那么就直接用這個(gè)FID吧,這是最幸福的。注意:如果特征字沒(méi)有3個(gè)字節(jié),可以用ff補(bǔ)充。
4.
最關(guān)鍵的部分,要你編程解決問(wèn)題了。如果器件能ISP的盡量用ISP吧。建一個(gè)*.c文件,里面實(shí)現(xiàn)這些函數(shù):
#include <e51pro.h>
void InitProXX()
//編程前的準(zhǔn)備工作
{
…
}
void ProOverXX()
//編程結(jié)束后的工作,設(shè)置合適的引腳電平
{
…
}
void ReadSignXX()
//讀特征字
{
…
}
void EraseXX()
//擦除器件
{
…
}
BOOL WriteXX(BYTE Data)
//向器件寫(xiě)一個(gè)字節(jié)
{
…
}
BYTE ReadXX()
//從器件讀一個(gè)字節(jié)
{
…
}
void LockXX()
//寫(xiě)鎖定位
{
…
}
void PrepareProXX()
//設(shè)置pw中的函數(shù)指針,讓主程序可以調(diào)用上面的函數(shù)
{
pw.fpInitPro=InitProXX;
pw.fpReadSign=ReadSignXX;
pw.fpErase=EraseXX;
pw.fpWrite=WriteXX;
pw.fpRead=ReadXX;
pw.fpLock=LockXX;
pw.fpProOver=ProOverXX;
}
“XX”就是FID。其實(shí)你不必寫(xiě)太多程序,如果發(fā)現(xiàn)它的編程方法與AT89C51相似,那就直接復(fù)制AT89C51PRO.C中的源程序,修改一下即可。如果與AT89S51相似呢,那就更好辦了:
void Erase02()//擦除器件
{
InitPro02();
//-----------------------------------------------------------------------------
//根據(jù)器件的DataSheet,設(shè)置相應(yīng)的編程控制信號(hào)
OutBuf[0]=0xac;//<<<<<<<<<<<<<<<<<<修改這個(gè)
OutBuf[1]=0x80;//<<<<<<<<<<<<<<<<<<修改這個(gè)
SendInstrc(4);//<<<<<<<<<<<<<<<<<<<<注意要用幾個(gè)字節(jié)
Delay_ms(500);
//-----------------------------------------------------------------------------
ProOver02();
}
最后把PrepareProXX()添交到e51Pro.C中:
///////////////////////////////////////////////////////////////////////////////////////////////////
//所支持的FID,請(qǐng)?jiān)谶@里繼續(xù)添加
///////////////////////////////////////////////////////////////////////////////////////////////////
extern void PreparePro00();//FID=00:AT89C51編程器
extern void PreparePro01();//FID=01:AT89C2051編程器
extern void PreparePro02();//FID=02:AT89S51編程器
extern void PrepareProXX();//<<<<<<<<<<<<<<<<<<<<<<<<<<<添加到末尾
還有:
switch(ComBuf[1])
//根據(jù)FID設(shè)置(ProWork)pw中的函數(shù)指針
{
case 0:
//at89c51編程器
PreparePro00();
break;
case 1:
//at89c2051編程器
PreparePro01();
break;
case 2:
//at89s51編程器
PreparePro02();
break;
//case 3:
//擴(kuò)充器件時(shí),請(qǐng)繼續(xù)向下添加
//
PrepareProXX();<<<<<<<<<<<<<<<<<<<<<<<<添加到末尾
//
break;
default:
ComBuf[0]=0xff;
ComBuf[1]=0xff;//表示無(wú)效的操作
break;
}
5.測(cè)試你的程序,成功后把它貼出來(lái)與大家分享,可以先發(fā)個(gè)Email給我。
如果你看完了《Easy 51Pro編程器的原理與擴(kuò)充》,那么你看這篇文章將更加容易。你會(huì)發(fā)現(xiàn)ProWork和class CIsPro的原理完全一樣,其實(shí)ProWork就是模仿了CIsPro。我管CIsPro叫“ISP編程方法類(lèi)”。
看本文,你可能需要一點(diǎn)C++的基礎(chǔ)知識(shí)。本文主要是幫助用戶(hù)掌握對(duì)EasyISP進(jìn)行擴(kuò)充的原理和方法,所以討論重點(diǎn)將放在CParlPro和CIsPro,需要了解其他細(xì)節(jié)可以去看源程序。另外附VC源代碼,在VC6.0上就可以編譯出一個(gè)EPro.exe的可執(zhí)行文件。不過(guò)本程序使用了Code Jock的Xtreme Toolkit界面解決方案,需要先下載安裝(至少要裝15分鐘)。如果編譯時(shí)提示找不到dll,請(qǐng)把winio.dll,winio.sys,hook.dll,XT2000Lib.dll拷貝到程序所在的目錄
Easy 51Pro的應(yīng)用程序框架:
CEProDlg:對(duì)話(huà)框界面接收用戶(hù)操作,把用戶(hù)操作轉(zhuǎn)換成對(duì)CPro對(duì)象中的函數(shù)調(diào)用 | |
CPro:根據(jù)用戶(hù)的選擇,建立CParlPro對(duì)象(如果使用并口下載線(xiàn))或CSerialPro對(duì)象(如果使用串行編程器);管理CParlPro對(duì)象和CSerialPro對(duì)象,為它們提供與用戶(hù)界面的通訊;建立兩快64k的緩沖1和緩沖2,提供一些管理緩沖的函數(shù);管理器件列表,可以通過(guò)特征字查詢(xún)到與之匹配的器件。 | |
CParlPro派生自CParallelPort CParallelPort:負(fù)責(zé)安裝驅(qū)動(dòng)程序,提供豐富的函數(shù)方便對(duì)并口進(jìn)行操作。 CParlPro:封裝了ISP編程的一般流程,通過(guò)CIsPro的派生類(lèi)對(duì)象控制并口對(duì)器件進(jìn)行編程。 | CSerialPro派生自CSerialPort CSerialPort:提供豐富的函數(shù)方便串口通訊 CSerialPort:把CPro傳遞過(guò)來(lái)的用戶(hù)操作信息轉(zhuǎn)換成編程命令按照協(xié)議發(fā)送給編程器 |
由于CParallelPort中設(shè)計(jì)了這樣一些函數(shù):
BOOL SetPinLogic(int nPin,BOOL bLogic);
//設(shè)置指定引腳,bLogic=1高電平,bLogic=0低電平
BOOL GetPinLogic(int nPin);
//得到指定引腳的電平
BOOL SetPinL(int nPin);
//設(shè)置指定引腳為低電平
BOOL SetPinH(int nPin);
//設(shè)置指定引腳為高電平
他們可以通過(guò)并口引腳號(hào)對(duì)并口的某個(gè)引腳進(jìn)行操作,這就使Easy ISP天生具備支持任何下載線(xiàn)的能力。看看是怎么支持的:
int
m_nPinMosi;
//控制MOSI所用的并口引腳
int
m_nPinMiso;
//控制MISO所用的并口引腳
int
m_nPinRst;
//控制RST所用的并口引腳
int
m_nPinSck;
//控制SCK所用的并口引腳
int
m_nPinLe;
//控制器件鎖存所用的并口引腳
int
m_nPinOe;
//控制器件OE所用的并口引腳
int
m_nPinR1;
//保留引腳1
int
m_nPinR2;
//保留引腳2
BOOL m_bLe;
//鎖存有效時(shí)的電平
BOOL m_b2Le;
//鎖存無(wú)效時(shí)的電平
BOOL m_bOe;
//OE有效時(shí)的電平
BOOL m_b2Oe;
//OE無(wú)效時(shí)的電平
上面這一些變量保存了下載線(xiàn)用到的所有并口引腳號(hào)。這么多引腳資源,應(yīng)該夠用了吧。要知道MOSI,MISO,SCK這些引腳的用途可以看《Easy 51Pro編程器的原理與擴(kuò)充》。在初始化的時(shí)候會(huì)把這些變量賦予設(shè)定的值。
if(nProType==1)//Easy ISP下載線(xiàn)
{
CString strEasyIspIni;
strEasyIspIni=m_strAppPath+"EasyIsp.ini";//從EasyIsp.ini文件獲得引腳配置信息
//如果不存在"EasyIsp.ini"文件,則使用默認(rèn)的下載線(xiàn)配置(老版本的)
m_nPinMosi=GetPrivateProfileInt("引腳控制","MOSI",14,strEasyIspIni);
m_nPinMiso=GetPrivateProfileInt("引腳控制","MISO",15,strEasyIspIni);
m_nPinSck=GetPrivateProfileInt("引腳控制","SCK",1,strEasyIspIni);
m_nPinRst=GetPrivateProfileInt("引腳控制","RST",16,strEasyIspIni);
m_nPinLe=GetPrivateProfileInt("引腳控制","LE",17,strEasyIspIni);
m_nPinOe=GetPrivateProfileInt("引腳控制","OE",2,strEasyIspIni);
m_nPinR1=GetPrivateProfileInt("引腳控制","R1",3,strEasyIspIni);
m_nPinR2=GetPrivateProfileInt("引腳控制","R2",4,strEasyIspIni);
m_bLe=GetPrivateProfileInt("鎖存控制(LE)","Enable",1,strEasyIspIni);
m_b2Le=GetPrivateProfileInt("鎖存控制(LE)","Disable",0,strEasyIspIni);
m_bOe=GetPrivateProfileInt("輸出控制(OE)","Enable",0,strEasyIspIni);
m_b2Oe=GetPrivateProfileInt("輸出控制(OE)","Disable",1,strEasyIspIni);
}
如果在設(shè)置“編程器”中,選擇了EasyISP,那么程序?qū)?/font>EasyIsp.ini中載入引腳的配置信息。
如果程序目錄不存在該文件呢?那就是支持默認(rèn)的下載線(xiàn),這個(gè)下載線(xiàn)是原來(lái)設(shè)計(jì)的,這樣就解決了程序向上兼容的問(wèn)題。如果設(shè)置“編程器”中選擇了Atmel ByteBlaster下載線(xiàn)或Altera ByteBlaster下載線(xiàn),那么就會(huì)進(jìn)行下面這些配置。
else if(nProType==2)
//Atmel ByteBlaster下載線(xiàn)
{
m_nPinRst=PIN_SELIN;
//PIN_SELIN這些在ParllelPort.h中做了定義,這是并口引腳的功能號(hào)
m_nPinMosi=PIN_D0;
m_nPinMiso=PIN_ACK;
m_nPinSck=PIN_STROBE;
m_nPinLe=PIN_D2;
//不用LE,為了延時(shí)假定一個(gè)不起作用的引腳
m_bLe=0;
m_b2Le=0;
m_nPinOe=0;
//不用OE
m_nPinR1=m_nPinAf=PIN_AUTO;
//保留
m_nPinR2=m_nPinIni=PIN_INIT;
//保留
}
else if(nProType==3)
//Altera ByteBlaster下載線(xiàn)
{
m_nPinRst=3;
m_nPinMosi=8;
m_nPinMiso=11;
m_nPinSck=2;
m_nPinLe=14;
//控制74244的LE
m_bLe=0;
m_b2Le=0;
//LE常置低電平
SetPinL(14);
//先預(yù)置74244'LE為低電平
m_nPinOe=0;
//沒(méi)有OE
m_nPinR1=0;
m_nPinR2=0;
//無(wú)保留引腳
}
有些東西要提示一下。m_nPinOe是控制器件鎖存的并口引腳號(hào),但74244沒(méi)有OE怎么辦呢,那就把m_nPinOe賦為0吧,并口是沒(méi)有PIN 0的。還有就是對(duì)器件LE的控制。m_bLe表示鎖存有效時(shí)的電平,例如74373的LE高電平有效,所以m_bLe=1,
m_b2Le表示鎖存無(wú)效時(shí)的電平,所以74373的m_b2Le=0;如果需要74373的LE常開(kāi)啟怎么辦呢?m_bLe=1,m_b2Le=1不就解決問(wèn)題了嗎!同樣還有m_bOe,m_b2Oe。看看m_nPinLe主要用在了哪里吧。
void CParallelPro::SetSck(BOOL bLogic)
//設(shè)置SCK引腳的電平
{
if(bLogic)
SetPinH(m_nPinSck);
else
SetPinL(m_nPinSck);
if(m_nIspSpd==2)
//如果性能設(shè)置為“最快”
{
return;
}
else if(m_nIspSpd==1)
//如果性能設(shè)置為“較快”
{
SetPinLogic(m_nPinLe,m_bLe);
//開(kāi)啟鎖存
return;
}
else
//如果性能設(shè)置為“一般”
{
SetPinLogic(m_nPinLe,m_bLe);
//開(kāi)啟鎖存
for(int n=0;n<=1000;n++)
//延時(shí),在LE產(chǎn)生脈沖寬度
{
}
SetPinLogic(m_nPinLe,m_b2Le);
//關(guān)閉鎖存
}
}
這段程序的意思是如果性能設(shè)置為“一般”,SCK上的信號(hào)改變一次,就鎖存一次。如果性能設(shè)置為“較快”則把LE開(kāi)啟,但不關(guān)閉。你肯定要問(wèn)為什么每次都要開(kāi)啟呢,即使LE重來(lái)沒(méi)有關(guān)閉過(guò)?因?yàn)檫@樣可以多一次對(duì)并口的訪(fǎng)問(wèn),訪(fǎng)問(wèn)一次并口的會(huì)消耗一定的時(shí)間,這樣就可以當(dāng)作極短的延時(shí)。所以即使器件沒(méi)有LE,或者74244的LE接到了GND,也可以假定一個(gè)嗎!如果設(shè)置為“最快”呢,就不用鎖存了。性能設(shè)置為“一般”時(shí),有一個(gè)鎖存過(guò)程,鎖存后可以增強(qiáng)抗干擾。
下面這段程序可以參照一下《Easy 51Pro的原理與擴(kuò)充》中對(duì)void SendInstrc(BYTE nByte)的解釋?zhuān)矶际且粯樱贿^(guò)這里的程序要獲得“位”就沒(méi)有單片機(jī)里那么容易了。
void CParallelPro::SckBytes(int nBytes)
//通過(guò)下載線(xiàn)與器件通信
{
for(int n=0;n<nBytes;n++)
//要輸出的字節(jié)數(shù)
{
SetSck(0);
SetMosi((OutBuf[n] & 0x80));
//SCK為低電平時(shí),發(fā)送一位
SetSck(1);
if(GetMiso())
//SCK為高電平時(shí),接收一位
{
InBuf[n]=InBuf[n] | 0x80;
}
else
{
InBuf[n]=InBuf[n] & 0x7f;
}
SetSck(0);
SetMosi((OutBuf[n] & 0x40));
SetSck(1);
…
…
}
上面那些程序主要是關(guān)于對(duì)并口控制的,主要是方便你應(yīng)用。下面介紹一下CParlPro控制編程的主思路。先介紹一下CIsPro是什么?剛說(shuō)過(guò)CIsPro是“ISP編程方法類(lèi)”。它是一個(gè)純虛類(lèi),只有函數(shù)定義,沒(méi)有函數(shù)實(shí)現(xiàn),就像還沒(méi)填數(shù)額的支票,當(dāng)然兌不到錢(qián)。
class CIsPro
{
public:
BYTE FID;
//該類(lèi)所支持的FID
CParallelPro* m_pParlPro;
//方便調(diào)用到CParallelPro中的資源
virtual void InitIsPro(CParallelPro* pParlPro);
virtual void PreparePro()=0;
//編程前的工作
virtual void ReadSign(BYTE* pBuf)=0;
//讀特征字
virtual void Erase()=0;
//擦除器件
virtual BOOL Write(BYTE Data,int nAddr)=0;
//寫(xiě)一個(gè)單元
virtual BYTE Read(int nAddr)=0;
//讀一個(gè)單元
virtual BOOL LockBit(int nBit)=0;
//寫(xiě)鎖定位
virtual void ProOver()=0;
//編程結(jié)束后的工作
CIsPro();
virtual ~CIsPro();
};
這個(gè)類(lèi)定義了對(duì)器件編程的一般操作,是不是和串行編程器中的ProWork很相似?從這個(gè)類(lèi)派生出對(duì)器件編程的具體方法。再看看這個(gè)CIsPro類(lèi)是怎么被應(yīng)用的。以AT89S51為例(因?yàn)槲沂诸^上只有這種芯片)。現(xiàn)在就是給支票填數(shù)額了。
//At89s51Isp.h
class CAt89s51Isp : public CIsPro
{
public:
CAt89s51Isp();
virtual ~CAt89s51Isp();
virtual void InitIsPro(CParallelPro* pParlPro);
virtual void PreparePro();
//編程前的工作
virtual void ReadSign(BYTE* pBuf);
//讀特征字
virtual void Erase();
//擦除器件
virtual BOOL Write(BYTE Data,int nAddr);
//寫(xiě)一個(gè)單元
virtual BYTE Read(int nAddr);
//讀一個(gè)單元
virtual BOOL LockBit(int nBit);
//寫(xiě)鎖定位
virtual void ProOver();
//編程結(jié)束后的工作
};
還是挑幾個(gè)出來(lái)看看究竟吧,最好對(duì)照一下DataSheet上的那個(gè)表。
//At89s51Isp.cpp
void CAt89s51Isp::Erase()//擦除器件
{
m_pParlPro->OutBuf[0]=0xac;
//根據(jù)器件手冊(cè)上規(guī)定的命令協(xié)議
m_pParlPro->OutBuf[1]=0x80;
m_pParlPro->SckBytes(4);
//向器件發(fā)編程命令,4個(gè)字節(jié)
Sleep(500);
//擦除器件要500ms
}
BOOL CAt89s51Isp::Write(BYTE Data,int nAddr)
//寫(xiě)一個(gè)單元
{
int nTimeOut=0;
m_pParlPro->OutBuf[0]=0x40;
//根據(jù)器件手冊(cè)上規(guī)定的命令協(xié)議
m_pParlPro->OutBuf[1]=((BYTE*)&nAddr)[1];
//高地址
m_pParlPro->OutBuf[2]=((BYTE*)&nAddr)[0];
//低地址
m_pParlPro->OutBuf[3]=Data;
m_pParlPro->SckBytes(4);
//向器件發(fā)編程命令
while(Read(nAddr)!=Data)
//效驗(yàn):循環(huán)讀,直到讀出與寫(xiě)入的數(shù)相同
{
nTimeOut++;
if(nTimeOut>=1000)
//如果超時(shí)了,寫(xiě)入失敗
return FALSE;
}
return TRUE;
}
BYTE CAt89s51Isp::Read(int nAddr)
//讀一個(gè)單元
{
m_pParlPro->OutBuf[0]=0x20;
//根據(jù)器件手冊(cè)上規(guī)定的命令協(xié)議
m_pParlPro->OutBuf[1]=((BYTE*)&nAddr)[1];
//高地址
m_pParlPro->OutBuf[2]=((BYTE*)&nAddr)[0];
//低地址
m_pParlPro->SckBytes(4);
//向器件發(fā)編程命令
return m_pParlPro->InBuf[3];
//該單元的數(shù)據(jù)
}
void CAt89s51Isp::PreparePro()
//編程前的準(zhǔn)備工作
{
m_pParlPro->SetRst(0);
//RST置低電平
m_pParlPro->SetMosi(0);
//MOSI置低電平
m_pParlPro->SetSck(0);
//SCK置低電平
Sleep(10);
m_pParlPro->SetRst(1);
//編程前RST要置高點(diǎn)平
Sleep(10);
m_pParlPro->OutBuf[0]=0xac;
//注意這里,按照ATMEL DataSheet的規(guī)定,任何編程操作前
m_pParlPro->OutBuf[1]=0x53;
//必須先發(fā)送Programming Enable的命令,安排在這里最合適
m_pParlPro->SckBytes(4);
}
還是貼那個(gè)出表來(lái)看一下吧!
還有一個(gè)函數(shù)千萬(wàn)別忘了:
CAt89s51Isp::CAt89s51Isp()
{
m_pParlPro=NULL;
FID=0x02;
//該類(lèi)所支持的FID
}
最后再看看CParlPro是如何使用CIsPro的:
CParlPro有個(gè)這樣的東西:
CArray<CIsPro*,CIsPro*> m_arIsp;
//Isp編程方法隊(duì)列
在CParlPro的構(gòu)造函數(shù)中:
CParallelPro::CParallelPro()
{
m_arIsp.Add(new CAt89s51Isp);
//把所有的Isp編程方法對(duì)象加入到隊(duì)列
}
當(dāng)用戶(hù)對(duì)選擇的某器件編程時(shí)須要先得到該器件的編程方法
CIsPro* CParallelPro::GetIsPro(BYTE FID)
//查找支持該FID的"Isp編程方法對(duì)象"
{
for(int n=0;n<m_arIsp.GetSize();n++)
if(m_arIsp.GetAt(n)->FID==FID)
//從隊(duì)列中找出支持該器件FID的編程方法
return m_pIsPro=m_arIsp.GetAt(n);
//設(shè)置當(dāng)前"Isp編程方法對(duì)象"指針
return NULL;
}
例如用戶(hù)發(fā)出擦除AT89S51的命令后:
void CParallelPro::Erase(BYTE FID)
{
if(m_bThread)
//如果上一次操作線(xiàn)程還沒(méi)結(jié)束
{
m_pPro->Notify(PRO_INVALID);
return;
}
if(GetIsPro(FID)==NULL)
//查詢(xún)是否支持該FID,并獲得編程方法
{
m_pPro->Notify(PRO_WORK_INVALID);
return;
}
m_nCurWork=2;
//當(dāng)前操作標(biāo)識(shí)
AfxBeginThread(ProWorkThread,this);
}
獲得編程方法后當(dāng)然是要使用該編程方法了,使用編程方法是在ProWorkThread線(xiàn)程中進(jìn)行的,創(chuàng)建另外一個(gè)線(xiàn)程就是為了避免在讀,寫(xiě)這些編程過(guò)程中,窗口界面停止響應(yīng)。ProWorkThread是如何使用這些編程方法的,你一看源代碼就知道了。
最后再總結(jié)一下擴(kuò)充Easy ISP的步驟:
步驟1,2,3,和《Easy 51Pro的原理與擴(kuò)充》中介紹的一樣。
4.從CIsPro中派生出一個(gè)類(lèi),實(shí)現(xiàn)這個(gè)類(lèi)中的所有函數(shù)。最好以CAt89s51Isp為模板,修改一下就可以了。還有記得這里:
CParallelPro::CParallelPro()
{
m_arIsp.Add(new CAt89s51Isp);
//把所有的Isp編程方法對(duì)象加入到隊(duì)列
m_arIsp.Add(new 你的Isp方法類(lèi));
//<<<<<<<<<<<<<<<<<<<<<<<
}
5.測(cè)試你的程序,成功后把它貼出來(lái)與大家分享,可以先發(fā)個(gè)Email給我。
Easy 51Pro v2.0 制作及使用說(shuō)明
Easy 51Pro的第一個(gè)版本由于制作簡(jiǎn)單,操作方便一發(fā)布就受到了大家的熱烈歡迎。很多網(wǎng)友自制成功后已經(jīng)感受到了ISP編程技術(shù)是如何的爽,看到他們這么爽我也感到無(wú)比的高興和興奮,這也成了我開(kāi)發(fā)第2個(gè)版本的動(dòng)力。
努力奮斗一個(gè)月終于設(shè)計(jì)出了第2版。這個(gè)版本的設(shè)計(jì)目標(biāo):更好用,容易自制,容易擴(kuò)充,更穩(wěn)定,更靈活。
V2.0的新特性:
支持hex文件了
用戶(hù)自己可以擴(kuò)充器件
重載的文件對(duì)話(huà)框,讓你不必到處找文件
熱鍵支持,讓你調(diào)試程序時(shí)效率更高
靈活的程序設(shè)計(jì),甚至可以讓整套軟件在其他編程器硬件上運(yùn)行
可以支持任何下載線(xiàn),讓你有更多選擇
設(shè)計(jì)了串行通訊超時(shí)程序,減少了掉線(xiàn)現(xiàn)象
下載線(xiàn),編程器都有相關(guān)的調(diào)試程序,讓你制作時(shí)更輕松,提高了成功率
開(kāi)放源代碼和詳細(xì)的原理說(shuō)明,用戶(hù)可以根據(jù)自己的要求進(jìn)行修改
別看界面和上一個(gè)版本差不多,里面的東西可全部換了,使用還是一樣。點(diǎn)擊“自動(dòng)完成”后,就會(huì)一項(xiàng)一項(xiàng)的往下進(jìn)行。最優(yōu)的設(shè)置就像上面這個(gè)圖。緩沖1會(huì)自動(dòng)刷新上一次你打開(kāi)的文件,所以你不必每燒一次芯片就去打開(kāi)一次文件。你也可以不點(diǎn)擊“自動(dòng)完成”,在該界面下“回車(chē)”就是的。不在該界面下時(shí)可以用“熱鍵”,所以每當(dāng)編譯完程序后,直接按熱鍵就可以了(默認(rèn)熱鍵Ctrl+Shift+P)。在調(diào)試中頻繁燒片時(shí)這個(gè)功能顯得很重要。要把按鈕設(shè)置成“自動(dòng)”很簡(jiǎn)單,用“鼠標(biāo)右鍵”點(diǎn)一下就可以了。操作成功或失敗會(huì)有不同的聲音提示。成功的聲音提示可能會(huì)讓你編程時(shí)更興奮,效率更高。如果你覺(jué)得聲音聽(tīng)起來(lái)不爽,就在設(shè)置里“False”它吧。
這個(gè)下面有提示,一看就知道怎么做了吧。有4個(gè)編程器選擇。Easy 51Pro串行編程器也是新設(shè)計(jì)的,原來(lái)的那個(gè)
電路中12v/5v切換電路改成了12v/5v/0v切換電路,這樣就可以燒AT89C2051了。不過(guò)還要使用一對(duì)跳線(xiàn)或開(kāi)關(guān)切換(詳細(xì)內(nèi)容在《自制Easy 51Pro串行編程器》)。
Easy ISP下載線(xiàn)可以是任何一種并口下載線(xiàn),因?yàn)槲矣袀€(gè)這樣的設(shè)計(jì):
打開(kāi)程序目錄下的EasyIsp.ini文件可以編輯控制ISP時(shí)所用到的并口引腳。文件下面有詳細(xì)的說(shuō)明。編輯這個(gè)文件就可以支持你手中現(xiàn)有的下載線(xiàn)了,同時(shí)也解決了軟件向上兼容的問(wèn)題,如果你是老版本的用戶(hù)請(qǐng)把這個(gè)文件刪除。但我還是推薦一款我新設(shè)計(jì)的下載線(xiàn),就是用的上面這個(gè)配置(其實(shí)每根線(xiàn)接個(gè)電阻比接根導(dǎo)線(xiàn)更容易焊,那就和Atmel的圖一樣了):
其實(shí)這個(gè)電路就是從Altera
下載線(xiàn)和Atmel
下載線(xiàn)中抄來(lái)了一點(diǎn)。我覺(jué)得使用74373的OE很有必要,編程完畢后可以設(shè)置為高阻,這樣就不會(huì)影響單片機(jī)的那幾個(gè)引腳。使用LE可以保持當(dāng)前的信號(hào)狀態(tài),增加了抗干擾。R1,R2是為以后擴(kuò)充其他器件而保留的。這個(gè)電路在我的電腦上運(yùn)行得很穩(wěn)定了,如果你對(duì)電路的穩(wěn)定性還存在懷疑,那么你可以去抄一份適合你的電路,不過(guò)要記得特別關(guān)照一下SCK這個(gè)引腳,不然下載線(xiàn)就會(huì)不穩(wěn)定了。
Altera ByteBlaster下載線(xiàn)用來(lái)下載AT89S51的原理圖:
下載線(xiàn)輸出插頭恰好與Atmel規(guī)定的一致。
注意:本軟件設(shè)置中新增了一個(gè)“下載線(xiàn)性能”,里面有3個(gè)選擇“一般”,“較快”,“最快”。選擇“一般”改變一次信號(hào)就會(huì)有一次控制LE的操作(一個(gè)脈沖,開(kāi)啟,關(guān)閉);“較快”則每改變一次信號(hào)就開(kāi)啟一次LE,但不會(huì)關(guān)閉,這是因?yàn)閷?duì)并口訪(fǎng)問(wèn)一次可以延時(shí),即使器件沒(méi)有LE或LE接了高電平;“最快”則不使用LE。請(qǐng)根據(jù)你自制下載線(xiàn)的穩(wěn)定性設(shè)置。
下載線(xiàn)做完后,還要對(duì)其進(jìn)行調(diào)試。我為大家開(kāi)發(fā)了一個(gè)線(xiàn)路調(diào)試軟件“IspTest”,功能比上一個(gè)版本更強(qiáng),使用更方便。
同樣它也共享了EasyIsp.ini中的配置。點(diǎn)擊按鈕后用萬(wàn)用表量那個(gè)引腳的電平是否可以控制到位。
雖讓這個(gè)東西整個(gè)是免費(fèi)的,但我的服務(wù)算做到無(wú)微不至了吧。做Easy 51Pro串行編程器也有個(gè)調(diào)試程序,那是我以前寫(xiě)的,主要是方便當(dāng)時(shí)學(xué)CPLD,測(cè)試邏輯是否可以實(shí)現(xiàn)。不過(guò)后來(lái)又添加了調(diào)試單片機(jī)子程序的功能,做編程器時(shí)可以用它來(lái)測(cè)試線(xiàn)路是否都接好,12v/5v/0v是否可以控制。
這次軟件設(shè)計(jì)的非常Flexible,從上面對(duì)下載線(xiàn)的支持就可以看得出,但最主要的還是對(duì)器件的支持。一個(gè)人做這個(gè)東西不可能做到支持很多器件,沒(méi)時(shí)間,也沒(méi)錢(qián)搞。所以我就設(shè)計(jì)了這樣一個(gè)東西:
這上面顯示的器件和Easy 51Pro中下拉列表中的一樣。Easy 51Pro每次啟動(dòng)都會(huì)從一個(gè)“ChipList.chip”中載入器件信息,用這個(gè)軟件打開(kāi)“ChipList.chip”就會(huì)像上圖這樣。如果列表中沒(méi)有你期望的器件也不必著急,自己DIY一個(gè)就是。這個(gè)DIY的過(guò)程已經(jīng)被我簡(jiǎn)化的不能再容易了。
你可以直接向這個(gè)列表添加新器件,填入一些器件的信息就可以了,也可以“從文件導(dǎo)入”,就是把另外一個(gè)“*.chip”文件中的列表合并到一起。器件列表是給Easy 51Pro軟件識(shí)別器件的,光有這個(gè)還不行,還必須讓它知道該器件編程的方法。
這個(gè)就要你編程序了。Easy 51Pro串行編程器的控制器單片機(jī)程序是用Keil C寫(xiě)的,詳細(xì)的注釋?zhuān)勺x性很高,而且我建立了一種框架讓程序可以分層設(shè)計(jì),模塊化設(shè)計(jì)。要支持其他器件可以以我寫(xiě)好的AT89C51,AT89C0251,AT89S51編程器程序?yàn)槟0逍薷募纯伞H绻獢U(kuò)充Easy Isp下載線(xiàn)的功能,也不難,只要你懂得一點(diǎn)C++就可以了。擴(kuò)充器件的具體細(xì)節(jié)請(qǐng)看《Easy 51Pro的原理與擴(kuò)充》。
最后當(dāng)然是祝你成功了。沒(méi)成功也不要著急,可以在我的留言板提出問(wèn)題,還有你的好建議。特別歡迎那些幫忙擴(kuò)充器件的同行網(wǎng)友,還要特別感謝幫忙測(cè)試和提供建議的網(wǎng)友們。
可以發(fā)郵件給我:nie_zq@163.net
或者用QQ:3813420
|手機(jī)版|MCU資訊論壇
( 京ICP備18035221號(hào)-2 )|網(wǎng)站地圖
GMT+8, 2025-5-1 06:56 , Processed in 0.043668 second(s), 10 queries , Redis On.
Powered by Discuz! X3.5
© 2001-2025 Discuz! Team.