标题:
关于单片机iap程序地址跳转问题
[打印本页]
作者:
大幅度释放的
时间:
2021-11-29 10:35
标题:
关于单片机iap程序地址跳转问题
通过iap将用户程序写入eeprom读出也是正确的,但是程序并没有跳转,请各位大佬帮忙看看,谢谢各位!!!单片机型号:stc8f1k17s2 EEPROM:自定义大小为4k flash:17k
#include "reg51.h"
#include "intrins.h"
//测试工作频率为 11.0592MHz
#define FOSC 11059200UL//晶振值
//#define baud 9600
#define BRT (65536 - FOSC / baud / 4)//重载值
#define APP 0x3400//用户程序地址
sfr WDT_CONTR = 0xC1;
sfr AUXR = 0x8e;
sfr T2H = 0xd6;
sfr T2L = 0xd7;
sfr P3M0 = 0xb2;
sfr P3M1 = 0xb1;
sbit rts=P3^3;
sfr P_SW1 = 0xa2;
sfr P1M0=0x92;
sfr P1M1=0x91;
sbit red=P1^7;
sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
#define WT_30M 0x80
#define WT_24M 0x81
#define WT_20M 0x82
#define WT_12M 0x83
#define WT_6M 0x84
#define WT_3M 0x85
#define WT_2M 0x86
#define WT_1M 0x87
unsigned char xdata buf2[1024];
//unsigned char buf[34];//接收
unsigned char buft[32];//={0x75,0x92,0x80,0xe4,0xf5,0x91,0xd2,0x97,0x80,0xfe};
bit flagtxd=0;
int rlen=0;
int z=0,z1=0,z2=0;
char k=0,s=0,y=0;
unsigned char w=0,g=0;
int data_len=0;
char flagrxd=0,flagrxd_end=0;
int addr=0x0000,add=0x0000,add3=0x0000;
bit cnt88=0,cnt99=0;
int j=0;
void IapIdle();//iap初始化
char IapRead(unsigned int addr);//iap读数据
void IapProgram(unsigned int addr, unsigned char dat);//iap写数据
void IapErase(unsigned int addr);//iap擦除页
void ea_on();//开总中断
void ea_off();//关总中断
void configuart(int baud);//串口配置,baud为波特率
void uartinit();//串口初始化配置
void uart_interrupt_on();//串口中断打开
void uart_interrupt_off();//串口中断关闭
void uart_t(unsigned char *buft,char len);//串口发送
void uart_rt(unsigned char *buf,char len);
char uart_len(char *bufr,char len);//读取串口数据的长度
void max485(bit x);//max485x为0接收为1发送
void (*isp)()=APP;//指向用户函数
void iapwrite(unsigned char *buf,char len);//iap写程序
void iapr(unsigned char *buft,char len);
void main()
{
P3M0=0x08;
P3M1=0x00;
P1M0=0x00;
P1M1=0x00;
red=0;
// for(g=0;g<=200;g++)
// {
// _nop_();
// }
ea_on();//开总中断
max485(0); //max485为接收
//max485(1);//max485为发送
uartinit();//串口初始化
configuart(9600);//波特率
uart_interrupt_on();//串口中断开
// iapr(buf,12);
// EA=1;
// red=1;
// uart_t(buft,3);
IapErase(0x0000);
_nop_();
_nop_();
_nop_();
IapErase(0x0200);
_nop_();
_nop_();
_nop_();
IapErase(0x0400);
_nop_();
_nop_();
_nop_();
// z=0x0000;
// for(s=0;s<=data_len;s++)
// {
// w=IapRead(z);
// buft[s]=w;
// z++;
// }
uart_t(buft,10);
while(1)
{
if(cnt99==1)
{
if(cnt88==1)
{
add=0x0000;
for(j=1;j<data_len;j++)
{
// if((add%512)==0)
// {
// IapErase(addr);
// _nop_();
// _nop_();
// addr=addr+512;
// }
z=buf2[j];
IapProgram(add,z);
_nop_();
_nop_();
add++;
}
z=0x0000;
for(k=0;k<100;k++)
{
for(s=0;s<10;s++)
{
w=IapRead(z);
buft[s]=w;
z++;
}
uart_t(buft,10);
}
cnt99=0;
cnt88=0;
isp();
}
}
}
}
void IapIdle()
{
IAP_CONTR = 0; //关闭 IAP 功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非 IAP 区域
IAP_ADDRL = 0;
}
char IapRead(unsigned int addr)
{
char dat;
IAP_CONTR = WT_12M; //使能 IAP
IAP_CMD = 1; //设置 IAP 读命令
IAP_ADDRL = addr; //设置 IAP 低地址
IAP_ADDRH = addr >> 8; //设置 IAP 高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
dat = IAP_DATA; //读 IAP 数据
IapIdle(); //关闭 IAP 功能
return dat;
}
void IapProgram(unsigned int addr,unsigned char dat)
{
IAP_CONTR = WT_12M; //使能 IAP
IAP_CMD = 2; //设置 IAP 写命令
IAP_ADDRL = addr; //设置 IAP 低地址
IAP_ADDRH = addr >> 8; //设置 IAP 高地址
IAP_DATA = dat; //写 IAP 数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
IapIdle(); //关闭 IAP 功能
}
void IapErase(unsigned int addr)
{
IAP_CONTR = WT_12M; //使能 IAP
IAP_CMD = 3; //设置 IAP 擦除命令
IAP_ADDRL = addr; //设置 IAP 低地址
IAP_ADDRH = addr >> 8; //设置 IAP 高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IapIdle(); //关闭 IAP 功能
}
void ea_on()//开总中断
{
EA=1;
}
void ea_off()//关总中断
{
EA=0;
}
void configuart(int baud)//串口配置,baud为波特率
{
T2L =(65536 - FOSC / baud / 4);
T2H =(65536 - FOSC / baud / 4)>> 8;
AUXR = 0x15;//定时器2作波特率发生器
}
void uartinit()//串口初始化配置
{
P_SW1 = 0x40; //RXD_2/P3.6, TXD_2/P3.7
SCON = 0x50;//设置串口为模式1可变波特率8位数据方式
}
void uart_interrupt_on()//串口中断打开
{
ES=1;
}
void uart_interrupt_off()//串口中断关闭
{
ES=0;
}
void uart_t(unsigned char *buft,char len)//发送
{
int i;
max485(1);
for(i=0;i<len;i++)
{
flagtxd=0;
SBUF=*buft++;
while(!flagtxd);
// {
// if(flag0_5s==1)
// {
// flag0_5s=0;
// break;
// }
// }
}
max485(0);
}
void uart_rt(unsigned char *buf,char len)//发送
{
int i;
max485(1);
for(i=0;i<len;i++)
{
flagtxd=0;
SBUF=*buf++;
while(!flagtxd);
// {
// if(flag0_5s==1)
// {
// flag0_5s=0;
// break;
// }
// }
}
max485(0);
}
void max485(bit x)
{
rts=x;
}
void iapwrite(unsigned char *buf,char len)
{
IapErase(0x0000);
_nop_();
_nop_();
_nop_();
// IapErase(0x1005);
// _nop_();
// _nop_();
// _nop_();
if((buf[0]==0x99))//&&(buf[1]=0x03))
{
unsigned char i=0,k=0;
unsigned int j=APP;
for(i=1;i<=len;i++)
{
k=buf[i];
IapProgram(j,k);
_nop_();
_nop_();
j++;
}
}
}
void iapr(char *buft,char len)
{
char i=0,x=0;
int j=APP;
for(i=0;i<=len;i++)
{
x=IapRead(j);
buft[i]=x;
j++;
}
}
void uart_interrupt() interrupt 4//串口中断
{
if(RI) //接收到字节
{
RI=0;//软件清零接收中断标志位
buf2[rlen]=SBUF;
if(rlen<1000)
{
if(buf2[rlen]==0x99)
{
if(buf2[rlen-1]==0x99)
{
if(buf2[rlen-2]==0x99)
{
cnt99=1;
rlen=0;
}
}
}
if(buf2[rlen]==0x88)
{
if(buf2[rlen-1]==0x88)
{
if(buf2[rlen-2]==0x88)
{
cnt88=1;
data_len=rlen-2;
// rlen=0;
}
}
}
rlen++;
}
else
rlen=0;
}
if(TI)//发送字节
{
TI=0;//软件清零发送中断标志位
flagtxd=1;//发送完成标志
}
}
复制代码
作者:
AUG
时间:
2021-11-29 11:56
STC的IAP我没用过,STM的我试过,说说我的看法,你首先确定你的数据没错,其次是确实程序有跑到跳转的函数那里。先确定数据正确了,然后确定程序跑到了跳转的位置,然后再考虑跳转后程序不跑的问题。
作者:
人工置顶员
时间:
2021-11-29 22:25
顶一下
作者:
188610329
时间:
2021-11-29 22:33
通过iap将用户程序写入eeprom读出也是正确的,但是程序并没有跳转,
eeprom 读写正确, 和 程序跳转 有什么关联? 从你的代码中看不出来。
另外,C语言有 跳转 这个操作么? 我一直以为 汇编才有 跳转。
作者:
shumivan
时间:
2021-11-30 17:15
跳转前是需要吧硬件看门狗关闭的,而且跳转前你需要检测栈顶信息是否正确,数据包数和字节数是否校验通过。跳转偏移量是否与你的KEIL里设置的一致(如果不一致,那么跳过去不是你写入新APP的首地址那也肯定运行不起来)。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1