初级会员
- 积分
- 160
- 金钱
- 160
- 注册时间
- 2014-5-23
- 在线时间
- 0 小时
|
5金钱
这是在线升级程序
/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC IAP 系列单片机实现用户ISP 演示程序 ----------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-755-82944243 ----------------------------------------*/
/* --- Tel: 86-755-82948412 ----------------------------------------*/
/* --- Web: www.STCMCU.com -----------------------------------------*/
/* 如果要在程序中使用或者在文章中引用该程序,请在程序中或文章中注明 */
/* 使用了宏晶科技的资料或程序 */
/*------------------------------------------------------------------*/
#include<STC12C5A.h>
#include "absacc.h"
sbit en=P3^2; //MAX485使能控制IO
sbit led1=P4^1;
sbit seg5=P2^4;
sbit seg6=P2^5;
sbit seg7=P2^6;
#define seg_duan P0
char code seg_yang[]={0x40, 0xf9, 0x24, 0xa0, 0x91, 0x82, 0x02, 0xf8, 0x00, 0x80};//共阳
/*定义常数*/
#define FOSC 11059200L //系统时钟频
#define BAUD (256 - FOSC/32/19200) //定义串口波特率
#define MAX_SIZE 118 //用户程序最大的可用扇区数
#define ENABLE_IAP 0x82 //系统工作频率<20MHz
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef struct
{
BYTE cmd;
WORD addr;
WORD len;
BYTE chk;
} CBW;
void Isp_Check(BYTE *p);
BYTE Isp_RecvUart();
void Isp_RecvBlock(BYTE *p, BYTE n);
void Isp_SendUart(BYTE dat);
void Isp_SoftReset();
BYTE cnt7f; //Isp_Check内部使用的变量,接收7F的计数器,当连续接收到16次7F后进入ISP下载模式
CBW cbw; //串口命令块
BYTE sum; //校验和变量
BYTE buf[64]; //数据缓冲区
/*------------------------------------------------
串口中断服务程序
------------------------------------------------*/
void uart() interrupt 4
{
if (TI) TI = 0; //发送完成中断
if (RI) //接收完成中断
{
Isp_Check(&cnt7f); //ISP检测
RI = 0; //清接收完成标志
}
}
void delayms(int xms)//延时函数
{
for(;xms>0;xms--);
}
void main()
{
SCON = 0x50; //定义串口模式为8bit可变,无校验位
AUXR = 0x15; //波特率发生器12倍速,并启动波特率发生器定时器
BRT = BAUD; //初始化波特率发生器定时器的定时初值
ES = 1; //使能串口中断
EA = 1; //打开全局中断开关
en=0;
while (1)
{
led1=~led1;
delayms(5000);
}
}
/*------------------------------------------------
串口ISP命令序列检测模块
------------------------------------------------*/
void Isp_Check(BYTE *p)
{
BYTE i;
WORD j;
if (SBUF != 0x7f) //检测串口数据是否为7F
{
*p = 0; //若不是7F,则清7F计数值
// Isp_SoftReset(); //接收到非法命令时,复位系统
}
else
{
(*p)++; //若是7F,则7F计数值+1
if (*p>=16) //判断7F是否已连续接收到16次
{ //若>=16次,则进入ISP下载模式
IE = 0; //关闭所有中断
PSW = 0; //ISP模块使用第0组寄存器
SP = 0x5f; //重置ISP模块的堆栈指针
RI = 0; //清除串口接收标志
TI = 0; //置串口发送标志
Isp_SendUart(0x5a); //返回5A 69到PC,表示ISP模块已准备就绪
Isp_SendUart(0x69); //返回5A 69到PC,表示ISP模块已准备就绪
while (1) //ISP下载模式,主循环
{
sum = 0; //清校验和 //若命令出错,则程序复位
if((Isp_RecvUart()==0x5a)&&(Isp_RecvUart()==0x69))
{
Isp_RecvBlock((BYTE *)&cbw, 6); //接收6字节的命令序列
if (sum != 0) //判断命令序列是否正确
{
Isp_SoftReset(); //若命令出错,则程序复位
}
switch (cbw.cmd)
{
case 0: //0号命令为擦除命令
IAP_ADDRL = 0; //从第0扇区开始擦除
IAP_ADDRH = 0;
IAP_CONTR = ENABLE_IAP; //使能IAP功能
IAP_CMD = 3; //擦除命令
if (cbw.len > MAX_SIZE) //判断擦除扇区数是否超出范围
{
cbw.len = MAX_SIZE;
}
while (cbw.len--) //判断是否擦除完成
{
WDT_CONTR = 0x17; //清看门狗
IAP_TRIG = 0x5a; //触发ISP命令
IAP_TRIG = 0xa5;
IAP_ADDRH += 2; //目标地址+512
}
Isp_SendUart(0); //正确返回
break;
case 1: //1号命令为编程命令
sum = 0; //清除校验和值
Isp_RecvBlock(buf, 64); //接收64字节的编程数据
Isp_RecvUart(); //接收校验和
if (sum != 0) //判断数据是否正确
{
Isp_SoftReset(); //若数据出错,则程序复位
}
IAP_CONTR = ENABLE_IAP; //使能IAP功能
IAP_CMD = 2; //编程命令
j = cbw.addr; //编程目标地址
for (i=0; i<64; i++) //编程64字节数据
{
WDT_CONTR = 0x17; //清看门狗
IAP_DATA = buf; //将当前数据送IAP数据寄存器
IAP_ADDRL = j; //目标地址送IAP地址寄存器
IAP_ADDRH = j >> 8;
IAP_TRIG = 0x5a; //触发ISP命令
IAP_TRIG = 0xa5;
j++; //目标地址+1
}
j = cbw.addr; //校验目标地址
for (i=0; i<64; i++) //校验64字节数据
{
WDT_CONTR = 0x17; //清看门狗
if (buf != CBYTE[j]) //源数据与目标数据进行比较
break; //不相等,则编程出错
j++; //校验下一个字节
}
Isp_SendUart(!(i == 64)); //校验成功返回0; 否则返回1
break;
default:
Isp_SoftReset(); //接收到非法命令时,复位系统
break;
}
}
}
}
}
}
/*------------------------------------------------
接收一块串口数据
入口参数: R0 (数据缓冲区地址)
R7 (缓冲区长度)
------------------------------------------------*/
void Isp_RecvBlock(BYTE *p, BYTE n)
{
while (n--) //检测长度
{
*p = Isp_RecvUart(); //接收1字节,并保存到缓冲区
p++; //缓冲区地址+1
}
}
/*------------------------------------------------
接收1字节串口数据
出口参数: ACC (接收到的数据)
------------------------------------------------*/
BYTE Isp_RecvUart()
{
BYTE dat;
RI = 0; //清除串口接收标志
en=0;
while (!RI) //等待接收完成
{
WDT_CONTR = 0x17; //清看门狗
}
dat = SBUF; //读取串口数据
RI = 0; //清除标志
sum += dat; //计算校验和
return dat; //返回接收到的串口数据
}
/*------------------------------------------------
发送1字节串口数据
入口参数: ACC (待发送的数据)
------------------------------------------------*/
void Isp_SendUart(BYTE dat)
{
en=1;
TI = 0; //清除标志
SBUF = dat; //发送当前数据
while (!TI) //等待前一个数据发送完成
{
WDT_CONTR = 0x17; //清看门狗
}
en=0;
}
/*------------------------------------------------
软件复位
------------------------------------------------*/
void Isp_SoftReset()
{
IAP_CONTR = 0x20; //用户程序区复位
}
想问下这段
“
Isp_SendUart(0x5a); //返回5A 69到PC,表示ISP模块已准备就绪
Isp_SendUart(0x69); //返回5A 69到PC,表示ISP模块已准备就绪
while (1) //ISP下载模式,主循环
{
sum = 0; //清校验和 //若命令出错,则程序复位
if((Isp_RecvUart()==0x5a)&&(Isp_RecvUart()==0x69))
”为什么这两个返回值可以进行与操作啊?不是先发送0x5a,再发送0x69么?按理说返回值应该没有0x5a了啊,不是因该被后者顶替掉了么,我是把那两个子函数当作变量来理解的,希望大神帮我解惑。。。万分感谢
|
|