📄 jbdlp.c
字号:
/***********************************************************
*
* 文件名: jbDlp.c
* 功 能: 下载过程主循环及中断服务
*
**********************************************************/
//#pragma SRC
//#pragma DEBUG
#include <jbDlp.h>
/**********************************************************
*
* 函数名: DlpProgram()
* 功 能: 下载过程主循环.
*
*********************************************************/
void DlpProgram(void)
{
bErrorCode=ERR_NO;
bStatusWord=S_DLP_INIT;
while(TRUE){
if(bStatusWord==S_DLP_INIT)
DlpInit();
else if(bStatusWord==S_DLP_UPCALL)
DlpUpCall();
else if(bStatusWord==S_DLP_DOWNCALL)
DlpDownCall();
else if(bStatusWord==S_DLP_UARTWAIT)
DlpUartWait();
else if(bStatusWord==S_DLP_COMM)
DlpComm();
else if(bStatusWord==S_DLP_EXIT)
DlpExit();
else if(bStatusWord==TO_INIT){
if(((bFailTimes>2)&&(bFailTimes<10))||(bDlpReason==4)){
if(CheckProgramSum()){
bDlpReason=TO_INIT; //
return;
}
bDlpReason=4;
bStatusWord=S_DLP_DOWNCALL;
}
else if((bFailTimes!=0)&&(bDlpReason==2))
bStatusWord=S_DLP_INIT;
else{
bDlpReason=TO_INIT; //
return;
}
}
else
break;
}
// 下载过程主循环
}
// End function: DlpProgram()
/******************************************************
*
* 函 数: DlpInit()
* 说 明: 下载硬件初始化过程.
*
*****************************************************/
void DlpInit(void)
{
byte bdata *Point;
byte i;
for(Point=0x20;Point<=0x2f;Point++) // 清除所有位标志区
*Point=0;
if(bDlpReason!=5){ // 进行变量初始化
TMOD=0x21;
TH0=L5MS_H;
TL0=L5MS_L;
SCON=0x40;
PCON=0x80;
cbDelay5MS=30; // 延时150MS,等待12887稳定
fDelay5MS=0;
IP=0x00; // 所有中断平级,无优先级
IT0=0;EX0=0; // 外部中断0,低电平触发,暂关闭
IT1=1;EX1=0; // 外部中断1,下降沿触发,暂关闭
TR0=1;ET0=1; // 定时器0启动,允许中断
TR1=0;ET1=0; // 定时器1停止,中断关闭
TR2=0;ET2=0; // 定时器2停止,中断关闭
REN=0;ES=0; // 串行口中断关闭
while(!fDelay5MS) IDLE;
cbDelay5MS=80;
fDelay5MS=FALSE;
DlpPage(6); // 12887 initial
XBYTE[RTC_CONTROLA]=0x27;
XBYTE[RTC_CONTROLB]=0x1a;
DlpPage(5);
DlpDispInit(); // 显示初始化
DlpDispClr();
DlpResetModem(); // CML644A初始化,并置于低功耗状态
}
EX0=1; // 开启秒定时中断
DlpReadData(1,PARA_47,1);
if(aDataBuf[0]==0x99)
fWorkMode=1;
// 依bDlpReason的值,设置bStatusWord状态:
EA=1;
iAddress=0;
cbFangDao=200;
for(i=0;i<20;i++)
aLargeBuf[i]=0;
DlpDispLP();
if(bDlpReason==2) // 拨号上呼申请程序
bStatusWord=S_DLP_UPCALL;
else if(bDlpReason==3) // 直接进入接收下载等待
bStatusWord=S_DLP_UARTWAIT;
else if(bDlpReason==4) // 多次重试呼失败,等待管理机呼入
bStatusWord=S_DLP_DOWNCALL;
else if(bDlpReason==5){ // 接收程序数据过程
cbFangDao=0;
bStatusWord=S_DLP_COMM;
}
}
// End function: DlpInit()
/***********************************************************
*
* 函数名: DlpExit()
* 功 能: 无错时将Page4中数据写入FLASH,完成后显示OK;
* 否则显示出错代码,并发出出错提示音
*
**********************************************************/
void DlpExit(void)
{
uint i;
uint iCheckSum0,iCheckSum1;
byte j,bTemp;
byte xdata *Point;
byte code *Point0;
while(TRUE){
if(bErrorCode!=ERR_NO){
if((bErrorCode>0x03)&&(bErrorCode<0x09))
DlpTxCmd(END);
DlpDispErrorCode(bErrorCode);
break;
}
DlpSpeaker(40);
while(!fDelay5MS) IDLE;
DlpOpen(POWER_ON);
// 先计算页面4数据缓冲区检验和:
DlpPage(4);
iCheckSum0=0;
for(i=0x2000,j=0;i!=0;i+=0x100){
Point=i+j;
iCheckSum0+=*Point;
j++;
}
// 写数据到FLASH过程:
Point=0x2000;
for(i=0;i<0x01c0;i++){
for(j=0;j<128;j++){ // 取出128字节
DlpPage(4);
bTemp=*Point;
DlpPage(5);
Point++;
aDataBuf[j]=bTemp;
}
DlpWriteData(0,Point-128,128);
iAddress--;
j=iAddress;
if((j&0x0f)==0x0f)
iAddress-=6;
j=iAddress;
if((j&0xf0)==0xf0)
iAddress-=0x60;
DlpDispLP();
}
// 写入FLASH完成后检验:
DlpPage(0);
iCheckSum1=0;
for(i=0x2000,j=0;i!=0;i+=0x100){
Point0=i+j;
iCheckSum1+=*Point0;
j++;
}
DlpPage(5);
if(iCheckSum0!=iCheckSum1){
bErrorCode=ERR_23;
DlpDispErrorCode(bErrorCode);
break;
}
aDataBuf[0]=(byte)(iCheckSum1>>8);
aDataBuf[1]=(byte)(iCheckSum1&0x00ff);
DlpWriteData(1,PROGRAM_CHECKSUM_ADDR,2);
DlpDelay5MS(50);
bDlpReason=TO_INIT;
bFailTimes=0;
DlpDispOK(3);
break;
}
DlpClose(MLD);
DlpOpen(RLY);
DlpResetModem();
//DlpWriteModem(SET_UP,0);
DlpClose(POWER_ON);
cbFangDao=200;
if((bErrorCode!=ERR_NO)&&(bDlpReason==2))
bFailTimes++;
if(bErrorCode==ERR_34)
bFailTimes=4;
bStatusWord=TO_INIT;
}
// End function: DlpExit()
/***************************************************************
*
* 函数名: DlpSecond() 12887的IRQ产生的秒中断
* DlpTime0() CPU内部定时器1中断
* DlpUart() CPU串行口中断
* DlpTime1() CPU内部定时器1中断
* DlpTime2() CPU内部定时器2中断
* 功 能: 中断服务函数
*
**************************************************************/
void DlpSecond(void) using 1
{
byte bTemp,bPage;
bPage=P1&0x07;
DlpPageInt(5); // 切换到页面5
if((cbDelaySecond!=0)&&(--cbDelaySecond==0))
fDelaySecond=1;
DlpPageInt(6);
bTemp=XBYTE[RTC_CONTROLC]; // 读控制寄存器C,取消中断低电平
DlpPageInt(bPage); // 恢复进中断时的页面状态
}
// End function: DlpSecond()
void DlpTime0(void) using 1
{
byte i,j;
byte bTemp,bPage;
byte xdata *Point0;
byte xdata *Point1;
TH0=L5MS_H;
TL0=L5MS_L;
bPage=P1&0x07;
if(cbFangDao<150){ // 防盗音发送过程
if(++cbFangDao<9)
OutBuf&=0x7f;
else if(cbFangDao<129)
OutBuf|=0x80;
else
cbFangDao=0;
}
else
OutBuf|=0x80;
DlpPageInt(6);
XBYTE[OUT_CE]=OutBuf; // 片选有效
if((cbDelay5MS!=0)&&(--cbDelay5MS==0))
{
fDelay5MS=1; // 设置时间到标志,并关闭12887发声
DlpPageInt(6);
XBYTE[RTC_CONTROLA]=0x25;
XBYTE[RTC_CONTROLB]=0x12;
}
DlpPageInt(5); // 切换到页面5
// 等待管理机呼入下载程序时:
if(bStatusWord==S_DLP_DOWNCALL)
{
DlpDetectOnOffHook(); // 检测摘挂机
DlpDetectRing(); // 检测振铃
}
if(fWriteFlashRequest) // 下载程序时,写入FALSH过程
{
fWriteFlashRequest=0;
TR0=0;
P1_3=0;
_nop_();
_nop_();
_nop_();
// 先取出目标地址的128字节数据
Point1=tWriteFlashAddr&0xff80;
Point0=&aWriteFlashBuf;
for(i=0;i<128;i++)
{
DlpPageInt(bWriteFlashPage);
bTemp=*Point1;
DlpPageInt(5);
*Point0=bTemp;
++Point0;
++Point1;
}
// 找到相对写入地址,更新缓冲区中欲修该部分数据
Point1=&sWriteFlashBuf;
Point0=&aWriteFlashBuf+(tWriteFlashAddr&0x007f);
for(i=0;i<bWriteFlashLen;i++,Point0++,Point1++)
*Point0=*Point1;
// 将整理好的缓冲区数据写入FLASH存储器中
Point1=tWriteFlashAddr&0xff80;
Point0=&aWriteFlashBuf;
DlpPageInt(0);
XBYTE[0x5555]=0xaa; // 打开FLASH写保护
XBYTE[0x2aaa]=0x55;
XBYTE[0x5555]=0xa0;
for(i=0;i<128;i++)
{
DlpPageInt(5);
bTemp=*Point0;
DlpPageInt(bWriteFlashPage);
*Point1=bTemp;
Point0++;
Point1++;
}
DlpPageInt(5);
// 延时10MS
i=10;j=50;
do
{
do
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--j!=0);
j=50;
}while(--i!=0);
P1_3=1;
_nop_();
_nop_();
_nop_();
TR0=1;
} // End if(fWriteFlashRequest)
DlpPageInt(bPage); // 恢复进中断时的页面状态
}
// End function: DlpTime0()
/******************************************************
*
* 函 数: DlpUart()
* 说 明: 串口中断服务程序.
*
*****************************************************/
void DlpUart(void) using 1
{
if(TI){
TI=0;
fTxDataReady=1;
}
else{
RI=0;
fRxDataReady=1;
bRecSBUF=SBUF;
}
}
// End function: DlpUart()
// 下面为两备用中断函数:
void DlpInt1(void) {}
void DlpTime1(void) {}
void DlpTime2(void) {}
// 主程序使用的页面切换函数:
void DlpPage(byte bPage)
{
EA=0;
P1=(P1&0xf8)|bPage;
EA=1;
}
// 中断使用的页面切换函数:
void DlpPageInt(byte bPage) using 1
{
P1=(P1&0xf8)|bPage;
}
// End function : DlpSetPageInt()
/*************************************************************
*
* 函数名: DlpDetectOnOffHook()
* 说 明: 下载程序部分检测挂摘机
* 出 口: cbLineState>(128+L0):线路处于挂机状态
* cbLineState<(128-L4):线路处于摘机状态
*
************************************************************/
void DlpDetectOnOffHook(void) using 1
{
byte bTemp;
DlpPageInt(6);
bTemp=XBYTE[IN_CE]&0x03; // 读输入口
DlpPageInt(5);
if(bTemp==0x00); // 不定状态,忽略
else if(bTemp==0x03)
{
if(cbLineState<128) // OH1、OH2=11 Hook Off
cbLineState=128;
else if(cbLineState>(128+L0)); // 线路挂机
else
++cbLineState;
}
else
{
if(cbLineState>128)
cbLineState=128;
else if(cbLineState<(128-L4)); // 线路摘机
else
--cbLineState;
}
}
// End function: DlpDetectOnOffHook()
/*************************************************************
*
* 函 数 名: DlpDetectRing()
* 说 明: 检测振铃
* 变量说明: cbRingTimes: 振铃次数;
* cbRingLow: OH1低计时,单位5MS,下同;
* ciRingHigh: OH1高计时,双字节宽度;
* cbRingPulseNum: 振铃脉冲个数 ;
*
*************************************************************/
void DlpDetectRing(void) using 1
{
byte bTemp;
DlpPageInt(6);
bTemp=XBYTE[IN_CE]&0x01;
DlpPageInt(5);
if(bTemp==0x01)
{ // 检测振铃,OH1=High ,摘机状态
cbRingLow=0;
if(++ciRingHigh<9);
else if(ciRingHigh<100)
{
if(cbRingPulseNum<5) // ciRingHigh==9,及40~45MS时间到
cbRingPulseNum=0;
}
else if(ciRingHigh<910)
{
if(cbRingPulseNum>=5)
{ // ciRingLow==100,及400MS时间到
++cbRingTimes;
cbRingPulseNum=0;
}
}
else
{
ciRingHigh=910; // HOOK ON
cbRingTimes=0;
cbRingPulseNum=0;
}
}
else
{ // OH1=LOW 挂机状态。
ciRingHigh=0;
if(++cbRingLow==2)
{
if(cbRingPulseNum<5)
++cbRingPulseNum;
}
else if(cbRingLow<9);
else
{
cbRingLow=9;
if(cbRingPulseNum<5)
cbRingPulseNum=0;
}
}
}
// End function: DlpDetectRing()
/***********************************************************
*
* 函数名:DlpReadData()
* 功 能:从FLASH存储器中读出指定参数
* 存入aDataBuf[].
* 入 口: bLen<=255;
*
**********************************************************/
void DlpReadData(byte bPage,uint sAddr, byte bLen)
{
byte i,bTemp;
byte xdata *tPoint;
tPoint=&aDataBuf;
for(i=0;i<bLen;i++,sAddr++,tPoint++)
{
DlpPage(bPage);
bTemp=XBYTE[sAddr];
DlpPage(5);
*tPoint=bTemp;
}
}
// End function: DlpReadData()
/**********************************************************************
*
* 函数名: DlpWriteData()
* 功 能: 将DataBuf中指定长度的数据写入FLASH存储器中
* 写入过程在DlpTime0中断中进行
* 入口参数: bPage:欲写入的页面
* tAddr:欲写入的目标地址
* bLen: 欲写入数据的长度(1-256)
* 全局变量: fWriteFlashRequest: 写入FLASH请求标志
* bWriteFlashPage: 欲写入的页面
* tWriteFlashAddr: 欲写入的目标地址
* sWriteFlashBuf[256]:欲写入FLASH数据缓冲区
* bWriteFlashLen: 欲写入数据的长度(1-256)
* 注 意: 在有严格时间要求的过程中不能调用本函数,执行时间约20MS
*
**********************************************************************/
// 暂按128字节页面(SST29EE010/SST29EE020)设计:
void DlpWriteData(byte bPage,uint tAddr, byte bLen)
{
byte i;
byte code *Point1;
byte xdata *Point0;
DlpPage(4); // 拷贝写FLASH过程到Page4
for(Point1=0,Point0=0;Point1<0x0300;Point1++,Point0++)
*Point0=*Point1;
DlpPage(5);
bWriteFlashPage=bPage; // 设置页面
tWriteFlashAddr=tAddr; // 设置目标地址
for(i=0;i<bLen;i++)
sWriteFlashBuf[i]=aDataBuf[i];
bWriteFlashLen=bLen; // 设置长度
fWriteFlashRequest=1; // 开始请求写入
while(fWriteFlashRequest) IDLE; // 等待写入完成
}
// End function: DlpWriteData()
//
// End file: jbDlp.c
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -