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

📄 iccard.c

📁 单相 CPU卡表复费率电能表,内部有提供I2C驱动,CPU卡驱动,NEC单片机0513等
💻 C
📖 第 1 页 / 共 3 页
字号:
#pragma interrupt INTTM02     MD_INTTM02
#include "includes.h"

volatile  Dummy_Comm485_ParameterS Cpu_card_comm;

uchar cd_data[ICCARD_MAX_DLEN];
uchar IC_ATR_DATA[8];
uchar IC_CPU_RAND_DATA[8];
uchar IC_CPU_ENCRYPT_DATA[8];
uchar IC_ESAM_RAND_DATA[8];
uchar IC_ESAM_ENCRYPT_DATA[8];
uchar IC_ESAM_KEY_BUFFER[24];
uchar IC_WRITE_BUFFER[80];
uchar recv_flag = 0;
uchar card_in_slot = 0;
uchar test_value = 0;
uchar IC_Card_flag = 0;

const uchar IC_SOUND_CLR[] = {SOUND_OF_CLR_CARD, SOUND_OF_INSERT, SOUND_OF_SYS_DEAL, SOUND_OF_WAIT};
const uchar IC_SOUND_BUY[] = {SOUND_OF_BUY_CARD, SOUND_OF_SYS_DEAL, SOUND_OF_WAIT};
const uchar IC_SOUND_BUY_OK[] = {SOUND_OF_BUY_OK};
const uchar IC_SOUND_BUY_ERR[] = {SOUND_OF_BUY_ERR};
const uchar IC_SOUND_CLR_OK[] = {SOUND_OF_CLR_FINISH};
const uchar IC_SOUND_NOT_IDENTIFY[] = {SOUND_OF_NOT_IDENTIFY_CARD};
	
void TM02Init(void)
{
    CPUCARD_COMM_STOP();
    PER0.0 = 1;
    TS0L.2 = 0;
    TMR02 = 0x0000;
    TPS0L = 0x0044;
    TDR02 = CLK_COUNT_9600; 
}

__interrupt void MD_INTTM02( void )
{
    TMIF02 = 0;
    TS0L.2 = 0;	
    TDR02 = CLK_COUNT_9600;
    TS0L.2 = 1;
    Cpu_card_comm.BIT_Count++;
    if( Cpu_card_comm.State_T_Or_R == TXDING )
    {
        CPU_card_send();
    }
    else
    {
        CPU_card_receive();
    }
}

void CPU_card_start_tx(uchar frame_start_Pointer, uchar len)
{
    _disable_interrupt();
    Cpu_card_comm.Uart_Data = 0;
    Cpu_card_comm.Len_Of_Need_To_Send = len;
    Cpu_card_comm.FramePointer = frame_start_Pointer;
    Cpu_card_comm.BIT_Count = 0;
    Cpu_card_comm.State_T_Or_R = TXDING;
    Cpu_card_comm.verify = 0;
    MemsetZero( (uchar *)&Cpu_card_comm.Serial_Buffer[0], frame_start_Pointer );
    if( !TS0L.2 ) TS0L.2 = 1;
    TDR02 = CLK_COUNT_9600;
    TMIF02 = 0;
    CPUCARD_COMM_START();
    _enable_interrupt();
}

void CPU_card_receive(void)
{
    uchar temp_bit;

    IC_IO_DIR(IC_IO_DIR_INPUT);
    	
    if( Cpu_card_comm.selectDevice == SEL_CARD )
    {
        temp_bit = CPU_CARD_IO;
    }
    else
    {
        temp_bit = ESAM_IO_PIN;
    }		
	
    switch( Cpu_card_comm.BIT_Count )
    {
        case 9:
            if( Cpu_card_comm.verify != temp_bit )
            {
                Cpu_card_comm.verify |= VERIFY_ERROR;
            }
            else
            {
                Cpu_card_comm.verify = 0;
            }	
            break;
			
        case 10:
            recv_flag = 0;	
            TS0L.2 = 0;            			
            CPUCARD_COMM_STOP();			
            if( 0 == ( Cpu_card_comm.verify & VERIFY_ERROR ) )
            {
                if( Cpu_card_comm.FramePointer < sizeof( Cpu_card_comm.Serial_Buffer ) )
                {
                    Cpu_card_comm.Serial_Buffer[Cpu_card_comm.FramePointer++] = Cpu_card_comm.Uart_Data;
                }
            }            
            break;
			
	default:
            Cpu_card_comm.Uart_Data >>= 1;
            if( temp_bit )
            {
                Cpu_card_comm.Uart_Data |= 0x80;
            }
            Cpu_card_comm.verify ^= temp_bit;
            break;
    }
}

void CPU_card_send(void)
{	
    IC_IO_DIR(IC_IO_DIR_OUTPUT);
	
    if( Cpu_card_comm.Uart_Data & 0x01 )
    {
        IC_IO(1);
        Cpu_card_comm.verify=~Cpu_card_comm.verify;
    }
    else
    {
        IC_IO(0);
    }
	
    switch( Cpu_card_comm.BIT_Count )
    {
        case 1:
            Cpu_card_comm.Uart_Data = Cpu_card_comm.Serial_Buffer[Cpu_card_comm.FramePointer];
            Cpu_card_comm.Serial_Buffer[Cpu_card_comm.FramePointer] = 0;
            break;
			
        case 9:
            Cpu_card_comm.Uart_Data = Cpu_card_comm.verify;
            break;
			
        case 10:
            Cpu_card_comm.Uart_Data = 0x01;
            break;
			
        case 11:
            if( 0 == --Cpu_card_comm.Len_Of_Need_To_Send )
            {	
                CPUCARD_COMM_STOP();
                Cpu_card_comm.verify = 0;
                Cpu_card_comm.BIT_Count = 0;
                Cpu_card_comm.Uart_Data = 0;
            }
            break;
			
        case 12:
        case 13:
        case 14:						
            break;
			
        case 15:
            Cpu_card_comm.FramePointer++;
            Cpu_card_comm.verify = 0;
            Cpu_card_comm.BIT_Count = 0;
            Cpu_card_comm.Uart_Data = 0;
            break;
		
        default:
            Cpu_card_comm.Uart_Data>>=1;
            break;
    }
}

void CPU_card_start_rx(void)
{
    _disable_interrupt();	
    IC_IO_DIR(IC_IO_DIR_INPUT);
    Cpu_card_comm.State_T_Or_R = RXDING;
    Cpu_card_comm.FramePointer = 0;
    Cpu_card_comm.BIT_Count = 0;
    Cpu_card_comm.verify = 0;		
    _enable_interrupt();
}

void CPU_card_comm_init(void)
{
    Cpu_card_comm.FramePointer %= sizeof( Cpu_card_comm.Serial_Buffer );
    MemsetZero( &Cpu_card_comm.Serial_Buffer[0], Cpu_card_comm.FramePointer );
    CPU_card_start_rx();
}

void CPUCardReset()
{
    if( Cpu_card_comm.selectDevice == SEL_CARD )
    {
        CPU_RST(0);
        Delay(400);
        CPU_RST(1);
    }
    else
    {
        ESAM_RST(0);
        Delay(400);
        ESAM_RST(1);
    }	
} 

void CPU_card_read_response(uchar read_len)
{
    ushort ii = 0,old_IE0,old_IE1,old_IE2;
    uchar temp_bit;
			
    old_IE0 = MK0;
    old_IE1 = MK1;
    old_IE2 = MK2;
    MK0 = 0xFFFF;
    MK1 = 0xFFFF;
    MK2 = 0xFFFF;
    CPU_card_start_rx();	 
	
    while( Cpu_card_comm.FramePointer < read_len )
    {
        if( Cpu_card_comm.selectDevice == SEL_CARD )
            temp_bit = CPU_CARD_IO;
        else
            temp_bit = ESAM_IO_PIN;
	
        if( ( !temp_bit ) && ( recv_flag == 0 ) )
        {     
            CPUCARD_COMM_STOP();
            recv_flag = 1;
            Cpu_card_comm.BIT_Count = 0;
            Cpu_card_comm.verify = 0;
            Cpu_card_comm.State_T_Or_R = RXDING;	
            TDR02 = CLK_COUNT_9600; 
            TMIF02 = 0;
            TS0L.2 = 1;
            CPUCARD_COMM_START();
            ii = 0;
        }
		
        ii++;
        if( Cpu_card_comm.FramePointer > 1 )
        {
            if( ii > 6000 ) break;
        }
        else
        {
            if( ii > 60000 ) break;
        }		
    }

    CPUCARD_COMM_STOP();
    MK0 = old_IE0;
    MK1 = old_IE1;
    MK2 = old_IE2;
}

void CPU_card_send_command(uchar s_pos, uchar send_len)
{
    ushort ii = 0, old_IE0, old_IE1, old_IE2;

    old_IE0 = MK0;
    old_IE1 = MK1;
    old_IE2 = MK2;
    MK0 = 0xFFFF;
    MK1 = 0xFFFF;
    MK2 = 0xFFFF;
    CPU_card_start_tx( s_pos, send_len );
    while( !TMMK02 )
    {
        ClrWdt();
        Delay(2);
        if( ii++ > 60000 ) break;
    }

    if( !TMMK02 )
    {
        CPUCARD_COMM_STOP();
    }
	
    MK0 = old_IE0;
    MK1 = old_IE1;
    MK2 = old_IE2;	
}

/*
 * 清零卡:
 *     由生产厂家制作和使用,
 *     1.用于IC卡电度表进行"复位"操作,使IC卡电度表复位成生产状态.
 *     2.强制进行继电器的开关操作.
 * 内容:68H+11H+00H+CSUM+16H (CSUM=校验和)
 */
uchar ic_setting(void)
{
    ulong new_buy;
    uchar *recv_buf = cd_data;
    uchar fn_data,temp[4];
			
    memcpy( recv_buf, &Cpu_card_comm.Serial_Buffer[1], 0x19 );
    memcpy( temp, recv_buf+3, 4 );
    ExchangeData(temp);
    
    // 购电底数	
    new_buy = *((ulong *)(temp));
    new_buy = Hex2BcdLong( new_buy );
    
    // 购电次数清零
    MemsetZeroWriteE2prom( DB_GDCS, 4 );
    
    // 剩余电量	
    PrePayData.BalanceSum = new_buy;
    FramWrite( DB_SYDL, (uchar *)&new_buy, POWER_DATA_LEN );	
    
    // 累计购电量	
    PrePayData.CumulateBuySum = new_buy;
    FramWrite( DB_LJGDL, (uchar *)&new_buy, POWER_DATA_LEN );
    
    // 累计用电量	
    PrePayData.CumulatePaySum = 0;
    FramWrite( DB_LJDL, (uchar *)&PrePayData.CumulatePaySum, POWER_DATA_LEN );
    
    // 过零电量	
    PrePayData.OverZeroSum = 0;
    FramWrite( DB_GLDL, (uchar *)&PrePayData.OverZeroSum, POWER_DATA_LEN );
    
    // 最后购电量	
    FramWrite( DB_ZHGDL, (uchar *)&new_buy, POWER_DATA_LEN );

    // 重置状态字
    fn_data = (~USED_METER);
    save_data( &fn_data, DB_ST, 1 );

    if( RELAYPARA.EnableFlag & BIT0 )
    {
        RELAY0_ON();
        RELAY1_ON();
        RELAYPARA.Status &=~ BIT0;
    }
    
#if 0
    if( RELAYPARA.EnableFlag & BIT1 )
    {
        RELAY1_ON();
        RELAYPARA.Status &=~ BIT1;
    }        
#endif

    FramWrite( ADDR_OF_RELAY_PARA+OFFSET_RELAY_STATUS, &RELAYPARA.Status, 1 );

    return OK;	
}

uchar ic_checking(void)
{
    uchar *recv_buf, rec_num;

    recv_buf = &Cpu_card_comm.Serial_Buffer[1];
	
    if( OK != IC_read_file( SEL_CARD, 2, 0, 1 ) )
    {
        return(EPM_E__5);
    }

    rec_num = recv_buf[0];		
    if( rec_num >= 15 )
    {
        return(EPM_E__19);
    }
	
    //选择反写文件	
    if( OK != IC_select_file( SEL_TYPE_EF, 2 ) )
    {
        return EPM_E__14;
    }

    if( OK != IC_checking_writeback(rec_num) )
    {
        return EPM_E__15;
    }

    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR] = rec_num + 1;
    if( OK != IC_write_file( SEL_CARD, 2, 0, 1 ) )
    {
        return EPM_E__20;
    }

    Delay20ms(20);

    return(OK);
}

uchar ic_updating_pwd(void)
{
    uchar key_num = 0, ii ;
	
    if( OK != IC_read_file( SEL_CARD, FILE_ID_MODIFY_PASSWORD, 2, 1 ) )
    {
        return(EPM_E__5);
    }

    key_num = ( Cpu_card_comm.Serial_Buffer[1]/IC_KEY_LEN );
    if( ( key_num > MAX_PWD_NUM ) || ( key_num == 0 ) )
    {
        return EPM_E__27;
    }

    for( ii = 0 ; ii < key_num; ii++ )
    {
        if( OK != IC_read_file(SEL_CARD, FILE_ID_MODIFY_PASSWORD, 4 + ii * IC_KEY_LEN, IC_KEY_LEN ) )
        {
            return(EPM_E__5);
        }

        memcpy( IC_ESAM_KEY_BUFFER, Cpu_card_comm.Serial_Buffer + 1, IC_KEY_LEN );
        if( OK != ESAM_update_key() )
        {
            return(EPM_E__28);
        }
    }
	
    return OK;	
}

uchar ic_refill_writeback(uchar *meterAddr, ulong * buy_times, uchar card_sn)
{
    unsigned char fn_data[50];
    
    load_data( IC_WRITE_BUFFER, DB_SYDL, 20 );    
    ExchangeData( IC_WRITE_BUFFER );	
    ExchangeData( IC_WRITE_BUFFER+8 );	
    ExchangeData( IC_WRITE_BUFFER+12 );	
    ExchangeData( IC_WRITE_BUFFER+16 );

    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR] = 0x68;
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 1] = 0x80;
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 2] = 0x22;	
    memcpy( &Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 3], IC_WRITE_BUFFER, 20 );

    //save buy times
    memcpy( &Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 7], (unsigned char *)buy_times, 4 );

    // 非法插卡次数清零
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 23] = 0;
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 24] = 0;    

    // 电能表状态字
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 25] = 0;

    // 电表表号
    memcpy(&Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 26], meterAddr, USER_METER_LEN);

    // 卡序号
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 36] = card_sn;

    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 0x25] = GetSum(&Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 1], 0x24);
    Cpu_card_comm.Serial_Buffer[IC_WRITE_START_ADDR + 0x26] = 0x16;

    if( OK != IC_write_file( SEL_ESAM, 2, 0, 0x27 ) )
    {
        return ERROR;
    }

    if( OK != IC_get_rand_data( SEL_CARD, 4 ) )
    {
        return ERROR;
    }

    if( OK != ESAM_read_MAC( 2, 0, 0x27 ) )
    {

⌨️ 快捷键说明

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