📄 ispl20.c
字号:
#pragma CD DB SB OE OT(8,SPEED) OR
#include <reg52.h>
#include <absacc.h>
#include <intrins.h>
#include <string.h>
#include <ctype.h>
sfr CHPCON=0xBF;
sfr CHPENR=0xF6;
sfr SFRAL =0xC4;
sfr SFRAH =0xC5;
sfr SFRFD =0xC6;
sfr SFRCN =0xC7;
#define uchar unsigned char
#define uint unsigned int
//------常量
#define TIMEL_1MS 0X67//1ms低字节
#define TIMEH_1MS 0XFC//1ms高字节
#define BAUD_RATE 0XFD//波特率9.6k
static uchar code ascii[]={"0123456789ABCDEF"};
static uchar code hex[80]=
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
0,10,11,12,13,14,15};//ASCII码转16进制表
#define EOC '<'//帧头
#define EOF '>'//帧尾
sbit bIspEnIn=P1^2;//ISP使能 0进入ISP
sbit bLed=P1^6;//灯
sbit bKillDogOut=P1^7;
static bit g_bInt;//中断发生标志1表示发生过中断
static bit bRcv;//串口接收标志 1收到一帧
static bit bLoad;//代码下载标志 1下载中
static union
{
uchar a[2];//a[0]存高字节,a[1]存低字节
uint ui;
} CLOCK;//系统时钟1ms
static struct
{
uchar aucA[64];
uchar ucAind;
} RE_BUFF;
static enum
{
NONE=0,//没有错误
BLANK_CHECK_ERR,
PROG_FAIL,
OVERFLOW
}enError;
static void initializtion(void);
static uint read_clock(void);
static void my_printf(uchar *p);
static void isp_exit(void);
static void isp_erase(void);
static void isp_prog(uchar sfrah,uchar sfral,uchar len);
static void process_comm_data(void);
static void asc_to_hex(uchar *p1,uchar *p2,uchar len);
static void hex_to_asc(uchar *p1,uchar *p2,uchar len);
static bit verify_sum(uchar *p,uchar len);//返回1表示正确,0错误
//-----------主程序
void main(void)
{
void initializtion(void);
static uint uiTLed;
initializtion();
while(1)
{
bKillDogOut=!bKillDogOut;
//if(bIspEnIn)isp_exit();
//else led();
if( (read_clock()-uiTLed)>500 )
{
uiTLed=read_clock();
bLed=!bLed;
}
process_comm_data();
}
}
//------------------------------------------------
void initializtion(void)//初始化
{
uchar t;
uchar a[5];
CHPENR =0;
IE=0;TCON=0;
TMOD=0X21;//定时器0模式1定时器1模式2
TL1=TH1=BAUD_RATE;
T2CON=0;//定时器2模式:自动重装载定时器
RCAP2L=TIMEL_1MS;RCAP2H=TIMEH_1MS;
SCON=0X50;PCON=0;//串行通讯模式1,SM2=0,REN=1,波特率不倍增
TR1=1;TR2=1;//启动定时器1,2
my_printf("4k LDROM program V2.0\r");
//=====================================================
//MOV CHPENR, #87H ; CHPENR = 87H, CHPCON WRITE ENABLE.
//MOV CHPENR, #59H ; CHPENR = 59H, CHPCON WRITE ENABLE.
//MOV A, CHPCON
CHPENR = 0x87;
CHPENR = 0x59;
t=CHPCON;
//ANL A, #80H
//CJNE A, #80H, UPDATE_32K ; CHECK F04KBOOT MODE ?
my_printf("CHPCON=");
a[0]=ascii[t>>4];a[1]=ascii[t&0x0f];
a[2]='\r';a[3]=0;
my_printf(a);
t&=0x80;
if(t==0x80)
{
//MOV CHPCON, #03H ; CHPCON = 03H, ENABLE IN-SYSTEM PROGRAMMING.
//MOV CHPENR, #00H ; DISABLE CHPCON WRITE ATTRIBUTE
CHPCON =0x03;
CHPENR=0;
//MOV TCON, #00H ; TCON = 00H, TR = 0 TIMER0 STOP
//MOV TMOD, #01H ; TMOD = 01H, SET TIMER0 A 16BIT TIMER
//MOV IP, #00H ; IP = 00H
//MOV IE, #82H ; IE = 82H, TIMER0 INTERRUPT ENABLED
IP=0;
EA=1;ET0=1;
//MOV R6, #F0H
//MOV R7, #FFH
//MOV TL0, R6
//MOV TH0, R7
TL0=0xf0;TH0=0xff;
//MOV TCON, #10H ; TCON = 10H, TR0 = 1, GO
//MOV PCON, #01H ; ENTER IDLE MODE
TR0 = 1;
PCON=0x01;
}
//=====================================================
EA=1;ET2=1;ES=1;//开定时器2中断 开串口中断
/*isp_erase();
switch(enError)
{
case NONE:
break;
case BLANK_CHECK_ERR:
enError=NONE;
my_printf("Error1:Blank check err\r");
break;
default:enError=NONE;break;
}
*/
my_printf("Waiting download Hex file...\r");
}
//---------------------初始化程序结束
//------------------------------------
void my_printf(uchar *p)//串口输出
{
//TI=1;
while( (*p)!='\0' )
{
//while(!TI);
//TI=0;
SBUF=(*p);p++;
while(!TI);TI=0;
}
//while(!TI);TI=0;
}
//--------------------------------------
static uint read_clock(void)
{
uint tt;
do
{
g_bInt=0;
tt=CLOCK.ui;
}
while(g_bInt);
return(tt);
}
//--------------------------------------
/*PC通讯协议
1.9600 Baud Rate,主从方式,PC主;
2.命令用ASCII码通讯,非定长帧,最长64;
3.帧头<,帧尾>,无校验和;
4.帧格式:帧头+命令+参数+帧尾;
5.代码用16进制下载,进入下载用Prog命令,退出用长度=64;
6.单片机4k程序模式时PC发命令:
1)Handshake 握手 应答4k LDROM program+程序版本号
2)Erase 擦除 应答Erase
擦除错误应答Error1:Blank check err
3)Prog 下载代码 应答Prog,准备接收代码
代码格式:长度(1byte)+首地址(2byte)+类型(1byte)+代码(nbyte)+校验和(1byte)
如果长度=59 表示下载结束
应答:
校验错误应答Error2:Verify err
编程失败应答Error3:Prog fail
长度错误应答Error4:Overflow 16
超时应答Error5:Load over time
编程继续应答Next
编程结束应答Prog end
4)Exit ISP 退出ISP 系统软复位,应答Be going to exit ISP mode...
7.单片机32k程序模式时PC发命令:
1)Handshake 握手 应答32k ADROM program+程序版本号
2)Enter ISP 进入ISP 应答Be going to ISP mode...
*/
static void process_comm_data(void)
{
//uchar i;
//uchar a[3];
static uint uiTLoad;
static enum {ORIGIN,LOADING}enStp;
switch(enStp)
{
case ORIGIN:
if(bRcv)
{
bRcv=0;//允许串口接收
if( strncmp(RE_BUFF.aucA,"Handshake",9)==0 )my_printf("4k LDROM program V2.0\r");
else if( strncmp(RE_BUFF.aucA,"Prog",4)==0 )
{
bLoad=1;
uiTLoad=read_clock();enStp=LOADING;
my_printf("Prog\r");
//isp_erase();
}
else if( strncmp(RE_BUFF.aucA,"Erase",5)==0 )
{
my_printf("Erase\r");isp_erase();
}
else if( strncmp(RE_BUFF.aucA,"Exit ISP",8)==0 )isp_exit();
else;
}
break;
case LOADING:
if( (read_clock()-uiTLoad)>3000 )//下载超时
{
bLoad=0;
enStp=ORIGIN;
my_printf("Error5:Load over time\r");
}
else if(bRcv)
{
/*for(i=0;i<RE_BUFF.aucA[0]+5;i++)
{
hex_to_asc(&RE_BUFF.aucA[i],a,1);
a[2]=0;
my_printf(a);
}
my_printf("\r");*/
bRcv=0;
if( !verify_sum(RE_BUFF.aucA,RE_BUFF.aucA[0]+5) )
{
bLoad=0;
enStp=ORIGIN;
my_printf("Error2:Verify err\r");
}
else if( RE_BUFF.aucA[0]==59 )
{
bLoad=0;
enStp=ORIGIN;
my_printf("Prog end\r");
}
else
{
isp_prog(RE_BUFF.aucA[1],RE_BUFF.aucA[2],RE_BUFF.aucA[0]);//编程
if(enError==NONE)my_printf("Next\r");
}
uiTLoad=read_clock();
//bRcv=0;
}
else;
break;
default:enStp=ORIGIN;break;
}
//=====================
switch(enError)
{
case NONE:
break;
case BLANK_CHECK_ERR:
enError=NONE;
my_printf("Error1:Blank check err\r");
break;
case PROG_FAIL:
enError=NONE;
my_printf("Error3:Prog fail\r");
break;
case OVERFLOW:
enError=NONE;
my_printf("Error4:Overflow 16\r");
break;
default:enError=NONE;break;
}
}
//--------------------------------------
/*static void asc_to_hex(uchar *p1,uchar *p2,uchar len)
{
uchar i;
uchar t,t1;
for(i=0;i<len;i++)
{
t=hex[(*p1)];t=t<<4;
p1++;
t1=hex[(*p1)];
p1++;
(*p2)=t|t1;p2++;
}
}*/
//--------------------------------------
/*static void hex_to_asc(uchar *p1,uchar *p2,uchar len)
{
uchar i;
for(i=0;i<len;i++)
{
(*p2)=ascii[(*p1)>>4];p2++;
(*p2)=ascii[(*p1)&0x0f];
p1++;
}
}*/
//--------------------------------------
static bit verify_sum(uchar *p,uchar len)//校验和程序
{
uchar i,sum=0;
for(i=0;i<len;i++)
{
sum+=*p;
p++;
}
if(sum==0)return(1);
else return(0);
}
//--------------------------------------
void timer2_int() interrupt 5//1ms定时器2中断
{
g_bInt=1;
CLOCK.ui++;
TF2=0;
}
//--------------------------------------
void timer0() interrupt 1//
{
TR0=0;
TL0=0;
TH0=0;
}
//--------------------------------------
void uart_int() interrupt 4 using 3//串口中断
{
static uchar ucCodeLong;
static enum {ORIGIN,ORDER,LOADING}enStp;
g_bInt=1;
if(TI);
else if(RI)
{
RI=0;
switch(enStp)
{
case ORIGIN:
if( bLoad&&(!bRcv) )//代码?
{
ucCodeLong=SBUF;
RE_BUFF.aucA[0]=ucCodeLong;
ucCodeLong+=5;
//长度: 长度(1byte)+首地址(2byte)+类型(1byte)+代码(nbyte)+校验和(1byte)
if(ucCodeLong<=64)
{RE_BUFF.ucAind=1;enStp=LOADING;}
else bLoad=0;//错误复位
}
else if( (SBUF==EOC)&&(!bRcv) )//命令?
{
RE_BUFF.ucAind=0;
enStp=ORDER;
}
else;
break;
case ORDER://收命令
if(SBUF==EOF){bRcv=1;enStp=ORIGIN;}
else
{
RE_BUFF.aucA[RE_BUFF.ucAind]=SBUF;
RE_BUFF.ucAind++;
RE_BUFF.ucAind&=0x3f;
}
break;
case LOADING://收代码
RE_BUFF.aucA[RE_BUFF.ucAind]=SBUF;
RE_BUFF.ucAind++;
if(RE_BUFF.ucAind>=ucCodeLong)
{
bRcv=1;enStp=ORIGIN;
}
break;
default:enStp=ORIGIN;break;
}
}
else TI=RI=0;
}
//--------------------------------------
void isp_erase(void)
{
uchar i,j;
uchar t0;
uchar a[9];
IE=0;
TR0=0;
//===========擦除=============
//MOV CHPENR, #00H ; DISABLE CHPCON WRITE-ATTRIBUTE
CHPENR=0;
//MOV TCON, #00H ; TCON = 00H , TR = 0 TIM0 STOP
//MOV IP, #00H ; IP = 00H
IP=0;
//MOV IE, #82H ; IE = 82H, TIMER0 INTERRUPT ENABLED
EA=1;ET0=1;
//MOV TMOD, #01H ; TMOD = 01H, MODE1
//MOV R6, #E0H ; SET WAKE-UP TIME FOR ERASE OPERATION, ABOUT 15 mS. DEPENDING
//; ON USER'S SYSTEM CLOCK RATE.
//MOV R7, #B1H
//MOV TL0, R6
//MOV TH0, R7
TL0=0xe0;TH0=0x61;//TH0=0xb1;
//ERASE_P_4K:
//MOV SFRCN, #22H ; SFRCN(C7H) = 22H ERASE 32K
SFRCN=0x22;
//MOV TCON, #10H ; TCON = 10H, TR0 = 1,GO
TR0 = 1;
//MOV PCON, #01H ; ENTER IDLE MODE (FOR ERASE OPERATION)
PCON=0x01;
//===========查空=============
//;* BLANK CHECK
//MOV SFRCN, #0H ; READ 32KB APROM MODE
SFRCN=0;
//MOV SFRAH, #0H ; START ADDRESS = 0H
//MOV SFRAL, #0H
//MOV R6, #FEH ; SET TIMER FOR READ OPERATION, ABOUT 1.5 uS.
//MOV R7, #FFH
//MOV TL0, R6
//MOV TH0, R7
//BLANK_CHECK_LOOP:
//SETB TR0 ; ENABLE TIMER 0
//MOV PCON, #01H ; ENTER IDLE MODE
//MOV A, SFRFD ; READ ONE BYTE
//CJNE A, #FFH, BLANK_CHECK_ERROR
for(i=0;i<=0x7f;i++)
{
bKillDogOut=!bKillDogOut;
SFRAH=i;
//for(j=0;j<0xff;j++)
j=0;
do
{
SFRAL=j;
TL0=0xfe;TH0=0xff;//1.5us
TR0=1;PCON=0x01;
t0=SFRFD;
if(t0!=0xff)
{
a[0]=ascii[i>>4];a[1]=ascii[i&0x0f];
a[2]=ascii[j>>4];a[3]=ascii[j&0x0f];
a[4]='-';
a[5]=ascii[t0>>4];a[6]=ascii[t0&0x0f];
a[7]='\r';a[8]=0;
my_printf(a);
enError=BLANK_CHECK_ERR;break;
}
j++;
}while(j>0);
if(enError==BLANK_CHECK_ERR)break;
}
//INC SFRAL ; NEXT ADDRESS
//MOV A, SFRAL
//JNZ BLANK_CHECK_LOOP
//INC SFRAH
//MOV A, SFRAH
//CJNE A, #80H, BLANK_CHECK_LOOP ; END ADDRESS = 7FFFH
//JMP PROGRAM_32KROM
//=====================
EA=1;ET2=1;ES=1;//恢复定时器2中断 串口中断
}
//--------------------------------------
static void isp_prog(uchar sfrah,uchar sfral,uchar len)
{
uchar i;
IE=0;TR0=0;
if(len>16){len=0;enError=OVERFLOW;}//最长16byte
/*
PROGRAM_32KROM:
MOV DPTR, #0H ; THE ADDRESS OF NEW ROM CODE
MOV R2, #00H ; TARGET LOW BYTE ADDRESS
MOV R1, #00H ; TARGET HIGH BYTE ADDRESS
MOV DPTR, #0H ; EXTERNAL SRAM BUFFER ADDRESS
MOV SFRAH, R1 ; SFRAH, TARGET HIGH ADDRESS
MOV SFRCN, #21H ; SFRCN(C7H) = 21 (PROGRAM 32K)
MOV R6, #BEH ; SET TIMER FOR PROGRAMMING, ABOUT 50 uS.
MOV R7, #FFH
MOV TL0, R6
MOV TH0, R7
PROG_D_32K:
MOV SFRAL, R2 ; SFRAL(C4H) = LOW BYTE ADDRESS
MOVX A, @DPTR ; READ DATA FROM EXTERNAL SRAM BUFFER. BY ACCORDING USER?
; CIRCUIT, USER MUST MODIFY THIS INSTRUCTION TO FETCH CODE
MOV SFRFD, A ; SFRFD(C6H) = DATA IN
MOV TCON, #10H ; TCON = 10H, TR0 = 1,GO
MOV PCON, #01H ; ENTER IDLE MODE (PRORGAMMING)
INC DPTR
INC R2
CJNE R2, #0H, PROG_D_32K
INC R1
MOV SFRAH, R1
CJNE R1, #80H, PROG_D_32K
*/
EA=1;ET0=1;
SFRCN=0x21;
/*SFRAH=sfrah;SFRAL=sfral;
for(i=0;i<=0x7f;i++)
{
bKillDogOut=!bKillDogOut;
SFRAH=i;
j=0;
do
{
SFRAL=j;
TL0=0xbe;TH0=0xff;//50us
SFRFD=j;
TR0=1;PCON=0x01;
j++;
}while(j>0);
}*/
for(i=0;i<len;i++)
{
SFRAL=sfral+i;
if( (sfral+i)>255 )SFRAH=sfrah+1;
else SFRAH=sfrah;
SFRFD=RE_BUFF.aucA[4+i];
TL0=0xbe;TH0=0xff;//50us
TR0=1;PCON=0x01;
}
SFRCN=0;//校验
for(i=0;i<len;i++)
{
SFRAL=sfral+i;
if( (sfral+i)>255 )SFRAH=sfrah+1;
else SFRAH=sfrah;
TL0=0xfe;TH0=0xff;//1.5us
TR0=1;PCON=0x01;
if(SFRFD!=RE_BUFF.aucA[4+i])
{enError=PROG_FAIL;break;}
}
EA=1;ET2=1;ES=1;//恢复定时器2中断 串口中断
}
//--------------------------------------
static void isp_exit(void)
{
my_printf("Be going to exit ISP mode...\r");
//MOV CHPENR, #87H ; CHPENR = 87H
CHPENR =0x87;
//MOV CHPENR, #59H ; CHPENR = 59H
CHPENR =0x59;
//MOV CHPCON, #83H ; CHPCON = 83H, SOFTWARE RESET.
CHPCON =0x83;
}
//--------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -