⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 单相复费率MSP430硬件时钟参考代码,MSP413设计方案
💻 C
📖 第 1 页 / 共 2 页
字号:
    //0xC11B 设置有功电能起始读数的时间,年月日时分秒 6字节
    _save_time_to_e2prom_(ADDRESS_OF_STARTING_COUNT_TIME);
    return _NOWRITEE2PROM_;
}

//0xC33F,0xC34F,0xC35F,0xC36F,0xC37F,0xC38F,0xC39F,0xC3AF,0xC3BF,0xC3CF,0xC3DF,0xC3EF
static unsigned char _slvs_wr_proc4_(void)
{
    //DI1DI0=((FrameBuffer[DI0]>>4)-0x03)*3 +ADDRESS_OF_TIME_SECT;
    DI1DI0=ADDRESS_OF_TIME_SECT;
    ReadPeriodOfTimeCount(&FrameBuffer[FRM_DATALEN]);
    FrameBuffer[FRM_DATALEN]*=3;
    return _WRITEE2PROM_;
}

const unsigned char _slvs_wr_p6_addr_[] =
{
    ADDRESS_OF_PERIOD_OF_TIME_COUNT,//0xC312
    //PTL_ADDRESS_OF_CHECKTIME_RANGE,//0xC013
    //PTL_ADDRESS_OF_YEAR_TIME_ZONE_NUM,//0xC310
    //PTL_ADDRESS_OF_DAY_TIMESECTION_TABLE_NUM,//0xC311
    //PTL_ADDRESS_OF_CHARGE_TYPE_NUM,//0xC313
    //PTL_ADDRESS_OF_COMM_HOLIDAY_NUM,//0xC314
    ADDRESS_OF_SETTLEMENT_HOUR,//0xC117
    //PTL_ADDRESS_OF_POWER_LIMIT,//0xC214
    PTL_ADDRESS_OF_WATCH_NO,//0xC032
    PTL_ADDRESS_OF_USER_NO,//0xC033
    //PTL_ADDRESS_OF_DEVICE_NO,//0xC034
};

//
static unsigned char _slvs_wr_proc5_(void)
{
    FrameBuffer[FRM_DATALEN]=_slvs_read_p5_len_[SlvsWrDataLenIdx];
    DI1DI0=_slvs_wr_p6_addr_[SlvsWrDataAddrIdx];
    return _WRITEE2PROM_;
}

static unsigned char _slvs_wr_proc6_(void)
{
    DI1DI0=ADDRESS_OF_DEVICE_CONSTANT;
    FrameBuffer[FRM_DATALEN]=3;
    ReadPPC();
    if(PowerPulseConstant_==0)
    {
        PowerPulseConstant_=FrameBuffer[17];
        return _WRITEE2PROM_;
    }
    else
        return _NOWRITEE2PROM_;
}

const unsigned short _slvs_cmds_write_[]=
{
    0xC115,
    0,
    0xC010,0xC011,
    0,
    0xC119,
    0,
    0xC33F,//0xC34F,0xC35F,0xC36F,0xC37F,0xC38F,0xC39F,0xC3AF,0xC3BF,0xC3CF,0xC3DF,0xC3EF,
    0,
    0xF0F0,//Len=1
    0xC312,//0xC013,//0xC310,0xC311,0xC313,0xC314,
    0xF0F0,//Len=2
    0xC117,
    0xF0F0,//Len=3
    0xF0F0,//Len=4
    //0xC214,
    0xF0F0,//Len=6
    0xC032,0xC033,//0xC034,
    //0,
    //0xF0F0,
    //0xC32F,
    0,
    0xC030,
    0xFFFF
};

const COMM_PROC_PTR _slvs_process_write_ []=
{
    _slvs_wr_proc1_,
    _slvs_wr_proc2_,
    _slvs_wr_proc3_,
    _slvs_wr_proc4_,
    _slvs_wr_proc5_,
    _slvs_wr_proc6_
};

//电表清零
void _clear_power_data_(void)
{    
    unsigned char k;
	
    _memset0_and_write_e2prom_(PTL_ADDRESS_OF_START_POWER,LEN_ADDRESS_OF_POWER);  
    _memset0_and_write_e2prom_(ADDRESS_OF_MONTH_CURRENT,LEN_ADDRESS_OF_POWER);  
    for(k=0;k<12;k++)
    {
        _memset0_and_write_e2prom_(ADDRESS_OF_MONTH_LOG+k*40,40);  
    }

    _memset0_and_write_e2prom_(ADDRESS_OF_STARTING_COUNT,20);  
    _memset0_and_write_e2prom_(ADDRESS_OF_START_TIME_MINUS,37);
    ClearPowerPulseDataInRam();
    
    //写入E2PROM里面的内容为年月日时分秒
    _save_time_to_e2prom_(PTL_ADDRESS_OF_POWER_CLEAR_TIME);
    //清零次数累加,因为后面不需要DI1DI0的值了,所以这里借用一下
    _bcd_short_add1_and_write_e2prom_(PTL_ADDRESS_OF_POWER_CLEAR_COUNT);
    //写入最后一次编程时间,年月日时分秒
    _save_time_to_e2prom_(ADDRESS_OF_PROGRAM_TIME);
                
    // 累加 编程次数2字节
    _bcd_short_add1_and_write_e2prom_(ADDRESS_OF_PROGRAM_TIMES);
}

unsigned char FindCmdItem(const unsigned short *cmds)
{
    unsigned char i=0,Idx=0,cFlag=0;
    
    do{
        if(cmds[i]==DI1DI0)
            return Idx;
        if(cmds[i]==0)
        {
            Idx++;
            SlvsWrDataAddrIdx=0;
            SlvsWrDataLenIdx=0xFF;
            cFlag=0;
        }
        if(cmds[i]==0xF0F0)
        {
            SlvsWrDataLenIdx++;
            SlvsWrDataAddrIdx--;
            cFlag=1;
        }
        if(cFlag)
        {
            SlvsWrDataAddrIdx++;
        }
    }while(cmds[i++]!=0xFFFF);
    return 0xFF;
}

//校验密码
unsigned char CheckPassword(unsigned char *pucData)
{
    unsigned char ucaTemp[4];
    
    #ifdef SINGLE_PASSWORD_SCHEME
    E2promRead(PTL_ADDRESS_OF_DEVICE_PASSWORD_0, ucaTemp,4);
    #else
    E2promRead(PTL_ADDRESS_OF_DEVICE_PASSWORD_0 + pucData[0]<<2, ucaTemp, 4);
    #endif
    
    if(!IsEqual(&ucaTemp[1],pucData,3))  return ERROR;
    return OK;
}

unsigned char Read_SlaveStationData(void)
{
    unsigned char pIdx;
    
    pIdx=FindCmdItem(_slvs_cmds_read_);
    
    if(pIdx!=0xFF)
    {
        pIdx=(_slvs_process_read_[pIdx])();
        goto Read_Slave_E;
    }
    else
        pIdx=FindCmdItem(_slvs_cmds_write_);

    if(pIdx!=0xFF)
        pIdx=(_slvs_process_write_[pIdx])();
    else
        goto Read_Slave_Return_Error;
    
Read_Slave_E:
    if(pIdx==_NOREADE2PROM_)
        goto Read_Slave_Return_Ok;
//Read_Slave_Read_E2prom:
    E2promRead(DI1DI0,&FrameBuffer[FRM_DATA+2],FrameBuffer[FRM_DATALEN]);
//Read_Slave_No_Read_E2prom:
Read_Slave_Return_Ok:
    FrameBuffer[FRM_DATALEN]+=2;
    return OK;
Read_Slave_Return_Error:	
    return ERROR;
}

unsigned char Write_SlaveStationData(void)
{
    unsigned char pIdx;
    
    if(CheckPassword(&FrameBuffer[FRM_DATA+3]) != OK)
        goto Write_Slave_Return_Error;
    
    pIdx=FindCmdItem(_slvs_cmds_write_);

    if(pIdx!=0xFF)
        pIdx=(_slvs_process_write_[pIdx])();
    else
        goto Write_Slave_Return_Error;

    if(pIdx!=_WRITEE2PROM_)
        goto Write_Slave_Return_Ok;
    
//Write_Slave_Write_E2prom:    
    E2promWrite(DI1DI0, &FrameBuffer[16], FrameBuffer[FRM_DATALEN]);

//Write_Slave_No_Write_E2prom:    
Write_Slave_Return_Ok:

    FrameBuffer[FRM_DATALEN]=0;
    
    //写入最后一次编程时间,年月日时分秒
    _save_time_to_e2prom_(ADDRESS_OF_PROGRAM_TIME);
    
    // 累加 编程次数2字节
    _bcd_short_add1_and_write_e2prom_(ADDRESS_OF_PROGRAM_TIMES);
    
    return OK;
Write_Slave_Return_Error:	
    return ERROR;
}

unsigned char TestCLR(void)
{
    unsigned char i;

    for(i=0;i<100;i++)
    {
        if(CLR_IN&CLR)
        {
            return(0);
        }
        else
        {
            Delay(10);
            ClrWDT();
        }
    }
    return(1);
}

void ClearWholeE2prom(void)
{
    unsigned short ii;

    for(ii=0;ii<2048;ii+=32)
    {
        _memset0_and_write_e2prom_(ii, 32);
    }
    DeviceBasicInit();
}

unsigned char ChkPwdAndSend(void)
{
    if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) return ERROR;
    FrameBuffer[FRM_DATALEN]=0;
    Tx_FrameInfo();
    LcdLightOn(5);
    return OK;
}

//解析接收到的数据桢
void Parse_RxFrame(void)
{
    unsigned char ucAddressFlag;
    //unsigned char ucTemp,ucTemp1;
    //unsigned short usTemp;
    
    ucAddressFlag=CompareAddressArea();

    DI1DI0=FrameBuffer[DI0]|(FrameBuffer[DI1]<<8);
    if(ucAddressFlag==COMPARE_FLAG_SINGLE_NO)
    {
        if(FrameBuffer[FRM_COMMAND]!=0x01)
        {
            if((LcdDisplayChoose&0x1000)==0)
                goto Parse_Err_CMD;
        }
        
        switch(FrameBuffer[FRM_COMMAND])
        {
            case 0x01:
                if(Read_SlaveStationData()!=OK)
                    goto Parse_Err_CMD;
                break;
            	
            case 0x04://写数据
                if(Write_SlaveStationData()!=OK)
                    goto Parse_Err_CMD;
                break;
                
            case 0x0F://写密码
                if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) goto Parse_End;;
                
                #ifdef SINGLE_PASSWORD_SCHEME
                    //<<<<<<<<<<<<<<<<<<<<
                #else
                    //提供的密码权限比要设定的密码权限小,退出
                    if(FrameBuffer[FRM_DATA] > FrameBuffer[FRM_DATA+4]) return;
                #endif
                
                memcpy(&FrameBuffer[FRM_DATA],&FrameBuffer[FRM_DATA+4], 4);
                
                #ifdef SINGLE_PASSWORD_SCHEME
                    E2promWrite(PTL_ADDRESS_OF_DEVICE_PASSWORD_0, &FrameBuffer[FRM_DATA], 4);    //<<<<<<<<<<<<<<
                #else
                        //优化后的代码,去除了switch或者if语句,将密码顺序存放,所以可以顺序索引
                        ucTemp = PTL_ADDRESS_OF_DEVICE_PASSWORD_0 + pucData[0]<<2;
                        E2promWrite(ucTemp, pucData, 4);
                        //if() != OK)
                        //{
                        //    memset(&(strFrameInfo.g_ucaFrame_Data[1]), 0, 3);
                        //}
                #endif
                FrameBuffer[FRM_DATALEN]=4;
                break;
				
            case 0x09:// 电量清零
                FrameBuffer[FRM_COMMAND]=0x89;
                if(ChkPwdAndSend()==OK)
                {
                    _clear_power_data_();
                }
                goto Parse_End;

            case 0x10:// 电表总清零
                FrameBuffer[FRM_COMMAND]=0x8A;
                if(ChkPwdAndSend()==OK)
                {
                    _clear_power_data_();
                    _memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_NUMBER,64);
                    _memset0_and_write_e2prom_(ADDRESS_OF_SETTLEMENT_HOUR,46);
                }
               goto Parse_End;
            
            case 0x6F:// 清密码
            
                if(TestCLR()) 
                    _memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_PASSWORD1,12);  
                else
                    goto Parse_End;
				
                break;
				
            case 0x6E:// 清电表常数
            
                if(TestCLR()) 
                    _memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_CONSTANT,4);  
                else
                    goto Parse_End;
				
                break;
				
            case 0x6D:// 清E2prom
            
                if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) goto Parse_End;
            
                if(TestCLR()) 
                {
                    ClearWholeE2prom();
                    ClearPowerPulseDataInRam();
                    //TotleTimeOfMiuns=0;
                    LcdLightOn(5);
                }
                goto Parse_End;
				
            default:
                goto Parse_Err_CMD;
        }
    }
    else if(ucAddressFlag==COMPARE_FLAG_BROADCAST)
    {
        //广播校时
        if(FrameBuffer[FRM_COMMAND]==0x08)
        {
            unsigned char ucTemp;
#ifndef _HARDWARE_RTC
            unsigned char time_bcd[7];
#endif
            //unsigned short ucTemp1,ucTemp2;
            if(LcdDisplayChoose&0x1000)
                goto Set_Time;
            E2promRead(ADDRESS_OF_SUCCESSSETTIME_FLAG, &ucTemp, LEN_OF_SUCCESSSETTIME_FLAG); 
            //it doesn't use during Test
            if(ucTemp != 1) //如果对时标记=1,说明已经在周期内对过时了,退出
            {
                //如果年、月、日不对,则退出
#ifdef _HARDWARE_RTC
                if(!IsEqual(&g_time[SPACE_OF_DAY],&FrameBuffer[FRM_DATA+3], 3)) goto Parse_End;;
#else
                GetSystemTimeBcd(time_bcd);
                if(!IsEqual(&time_bcd[SPACE_OF_DAY],&FrameBuffer[FRM_DATA+3], 3)) goto Parse_End;;
#endif
                if (CheckSystemTime(&FrameBuffer[FRM_DATA])==1)
                {
                    goto Parse_End;
                }
Set_Time:

                //写入对时时间
#ifndef _HARDWARE_RTC
    _DINT();
#endif
                memcpy(g_time, &FrameBuffer[FRM_DATA], RTC_TIME_LEN);
                memcpy(g_time+4, &FrameBuffer[FRM_DATA+3], RTC_DATA_LEN);
                
                SetSystemTime(); //对时   
#ifndef _HARDWARE_RTC
    _EINT();
#endif
                _save_time_to_e2prom_(PTL_ADDRESS_OF_LASTSETTIME_TIME);
                ucTemp=0x01;
                E2promWrite(ADDRESS_OF_SUCCESSSETTIME_FLAG,&ucTemp,1);
                LcdLightOn(5);
            }
            goto Parse_End;
        }
        else if(FrameBuffer[FRM_COMMAND]==0x01)
        {
            if(Read_SlaveStationData()!=OK)
                goto Parse_Err_CMD;
        }
        //写设备地址
        else
        {
            if((LcdDisplayChoose&0x1000)==0)
                goto Parse_Err_CMD;

            if(FrameBuffer[FRM_COMMAND]==0x0A)
            {
                E2promWrite(PTL_ADDRESS_OF_WATCH_NO, &FrameBuffer[FRM_DATA], LEN_OF_WATCH_NO);
                FrameBuffer[FRM_DATALEN]=0;
            }
            else if(FrameBuffer[FRM_COMMAND]==0x04)
            {
                if(Write_SlaveStationData()!=OK)
                    goto Parse_Err_CMD;
            }
            else
            {
                goto Parse_End;
            }
        }
    }
    else
    {
        goto Parse_End;
    }

//Parse_Ok:
    FrameBuffer[FRM_COMMAND]|=0x80;
    LcdLightOn(5);
    goto Parse_SendFrame;
Parse_Err_CMD:
//Parse_Err:
    FrameBuffer[FRM_COMMAND]=0xCC;
    FrameBuffer[FRM_DATALEN]=1;
    FrameBuffer[FRM_DATA]=ERROR_DATA;
Parse_SendFrame:
    Tx_FrameInfo();
Parse_End:
    return;
}

//发送数据桢
void Tx_FrameInfo(void)
{
    unsigned char ucCS=0;
    
    //UartTxBondRate=UART_BOND_RATE_1200;//Set Uart Tx Boudrate
    
    //P6OUT|=(IR_EN);

    //先发送4个前导字
    for(FramePointer=0; FramePointer<4; FramePointer++)
    {
        UartSendByte(PRE_FRAME_FLAG);
    }

    E2promRead(PTL_ADDRESS_OF_WATCH_NO, &FrameBuffer[FRM_ADDR], LEN_OF_WATCH_NO);
    
    //发送数据桢
    for(FramePointer=0; FramePointer<FRM_CS; FramePointer++)
    {
        if(FramePointer>FRM_DATALEN)
            FrameBuffer[FramePointer]+=FRAME_DATA_APPENDVALUE;
        UartSendByte(FrameBuffer[FramePointer]);
        ucCS+=FrameBuffer[FramePointer];
    }
    
    //发送校验值
    UartSendByte(ucCS);
    
    //发送帧结束标志
    UartSendByte(FRAME_END_FLAG);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -