實(shí)驗(yàn)2:基于RFID的電子錢包應(yīng)用實(shí)驗(yàn)

實(shí)驗(yàn)?zāi)康?/h1>
  • 了解RFID相關(guān)知識榔组。
  • 掌握RFID模塊讀寫IC卡數(shù)據(jù)的作原理與方法搞坝。

實(shí)驗(yàn)環(huán)境

  • 軟件:IAR SWSTM8 1.30钞护。
  • 硬件:RFID射頻模塊,電子標(biāo)簽养渴,ST-Link雷绢。

實(shí)驗(yàn)內(nèi)容

  1. 編程使用RFID模塊,完成自動識別讀理卑、寫取IC卡信息功能翘紊,實(shí)現(xiàn)RFID電子錢包軟件功能。
  2. 實(shí)現(xiàn)電子標(biāo)簽卡的扣款功能藐唠,將電子標(biāo)簽的錢數(shù)十六進(jìn)制的后兩位扣款清零帆疟。
  3. 將實(shí)驗(yàn)小組的任一位成員的學(xué)號后兩位作為錢數(shù)充值到電子標(biāo)簽的錢數(shù)后兩位當(dāng)中鹉究。

實(shí)驗(yàn)步驟

實(shí)驗(yàn)代碼

1) 初始化

  • 將tx_buf的前四組分別置為EE、CC踪宠、FE自赔、01,并將最后一組置為FF柳琢,其余為0绍妨。判斷MFRC531_Init() 是否等于MI_OK,若相等柬脸,則初始化MFRC531他去。
 //初始化
    for(i = 0;i < 14;i++)
        tx_buf[i] = 0;
    tx_buf[0] = 0xEE;
    tx_buf[1] = 0xCC;
    tx_buf[2] = 0xFE;
    tx_buf[3] = 0x01;
    tx_buf[13] = 0xFF;

    if(MFRC531_Init() == MI_OK) //MFRC531初始化
    {
        BEEP_On();
        delay_ms(200);
        BEEP_Off();
        LED_On();
    }

2) 尋卡

  • 尋卡過程中status = PcdRequest(0x52, g_pTagType),若未尋到肖粮,則Flag=0孤页,若尋到,則Flag=1涩馆,并獲取卡號和余額行施。
if(Flag == 0) // 未發(fā)現(xiàn)卡,尋卡
    {
        //UART2_SendString("no card is find\r", 17);
        status = MFRC531_OpenAnt();
        delay_ms(10);

        status = PcdRequest(0x52, g_pTagType);
        status = PcdAnticoll(g_cSNR);
        status = PcdSelect(g_cSNR,&buf_temp[0]);

        if(MI_OK != status)
        {
            Flag = 0;
        }
        else  // 獲取卡號和余額
        {
            Flag = 1;
        ```
  • 尋到卡后魂那,判斷此卡是否進(jìn)行過初始化蛾号,如果沒有,則初始化錢包內(nèi)的余額為0涯雅,若money[12]==0x01鲜结,則表示已經(jīng)初始化過,將tx_buf的第五至八位(從零開始計(jì)數(shù))置為g_cSNR的第零至三位活逆,為卡序列號精刷,將tx_buf的第9至12位置為money的第三至零位,為卡內(nèi)金額蔗候。
// 判斷是否進(jìn)行過初始化怒允,如果沒有,初始化錢包內(nèi)的余額為0
        if(money[12] == 0x01)//已經(jīng)初始化
        {
            tx_buf[4] = 0x03;
            tx_buf[5] = g_cSNR[0];
            tx_buf[6] = g_cSNR[1];
            tx_buf[7] = g_cSNR[2];
            tx_buf[8] = g_cSNR[3];
            tx_buf[9] = money[3];
            tx_buf[10] = money[2];
            tx_buf[11] = money[1];
            tx_buf[12] = money[0];
            
            UART2_SendString(tx_buf, 14);
        }

3) 充值和扣款

  • status = PcdValue(0xC1, 1, money_buf)锈遥,所傳參數(shù)第一個0xC1表示充值纫事,若要扣款,則為0xC0所灸,money_buf為當(dāng)前卡內(nèi)余額丽惶。
//充值
status = PcdValue(0xC1, 1, money_buf);
//扣款
status = PcdValue(0xC0, 1, money_buf);

硬件連接

  1. 把RFID模塊插到實(shí)驗(yàn)箱的主板上的串口
  2. 把ST-Link配合JTAG仿真器插到標(biāo)有ST-Link標(biāo)志的串口上
  3. 把仿真器一端的USB線插到PC機(jī)的USB端口,通過主板上的“加”“減”按鍵調(diào)整要實(shí)驗(yàn)的RFID模塊(會有黃色LED燈提示)爬立,硬件連接完畢钾唬。

編譯、燒錄并測試

  1. 我們用IAR SWSTM8 1.30軟件,打開..\RFID_電子錢包實(shí)驗(yàn)\Project\MFRC531_ATM8.eww知纷。
  2. 工程編譯:點(diǎn)擊“Project”->“Rebuild All”壤圃。
  3. 點(diǎn)擊“Rebuild All”進(jìn)行編譯陵霉。
  4. 將卡片放在燒錄板上琅轧,把程序燒到模塊里,點(diǎn)擊“ ”中間的Download and Debug進(jìn)行燒錄踊挠,完成后聽到蜂鳴器響一聲乍桂。
  5. 關(guān)閉上述已打開程序,打開串口測試軟件效床,將傳感器模塊連接到串口轉(zhuǎn)USB模塊上睹酌,將USB2UART模塊的USB線連接到PC機(jī)的USB端口,然后打開串口工具剩檀,配置好串口憋沿,波特率115200,8個數(shù)據(jù)位沪猴,一個停止位辐啄,無校驗(yàn)位,串口開始工作运嗜。

實(shí)驗(yàn)結(jié)果

充值

  • 發(fā)送數(shù)據(jù)EE CC FE 01 01 20 18 42 75 FF,其中EE CC FE 01是固定的壶辜,第二個01表示充值命令,20 18 42 75表示充值金額担租,F(xiàn)F表示結(jié)束砸民。接收到數(shù)據(jù)EE CC FE 01 01 DD 41 7F 51 20 18 42 75 FF,其中奋救,EE CC FE 01為固定數(shù)據(jù)岭参,第二個01表示充值操作,DD 41 7F 51為卡序列號尝艘,20 18 42 75為卡內(nèi)余額演侯,F(xiàn)F表示結(jié)束。


扣款

  • 發(fā)送數(shù)據(jù)EE CC FE 01 02 20 18 42 75 FF, 其中EE CC FE 01是固定的利耍,第二個02表示扣款命令蚌本,20 18 42 75表示扣款金額,F(xiàn)F表示結(jié)束隘梨。接收到數(shù)據(jù)EE CC FE 01 02 DD 41 7F 51 00 00 00 00 FF程癌,其中,EE CC FE 01為固定數(shù)據(jù)轴猎,02表示扣款操作嵌莉,DD 41 7F 51為卡序列號,00 00 00 00為卡內(nèi)余額捻脖,F(xiàn)F表示結(jié)束锐峭。


main.c的全部代碼

main.c

#include "main.h"

u8 rx_buf[10];//發(fā)送的命令
// EE CC FE 01 充值or扣款 金額 金額 金額 金額 FF
// EE CC FE 01   01/02    
u8 rx_counter;
u8 Uart_RecvFlag = 0;

u8 tx_buf[14];//串口返回的內(nèi)容

u8 g_cSNR[4];       //M1卡序列號
u8 g_pTagType[2];   // M1卡型號代碼
u8 money[16];       //余額
u8 p_KeyA[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
u8 p_Key[12];
u8 money_buf[4];//要充值的錢

u8 Flag = 0;    //是否發(fā)現(xiàn)卡標(biāo)志

//電子錢包-扇區(qū)0 塊號1

// 時鐘設(shè)置中鼠,內(nèi)部時鐘16M
void CLK_Config(void)                
{
    CLK_DeInit();
    CLK_HSICmd(ENABLE);
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
    CLK_ClockSecuritySystemEnable();
}


void TIM4_Config(void)
{
    TIM4_DeInit();
    TIM4_TimeBaseInit(TIM4_PRESCALER_128,125);  // 1ms 中斷
    TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
    TIM4_Cmd(ENABLE);
}


void BEEP_Config(void)
{
    BEEP_DeInit();
    BEEP_Init(BEEP_FREQUENCY_4KHZ);
    BEEP_LSICalibrationConfig(LSI_FREQUENCY_MAX);
}

void BEEP_On(void)
{
    BEEP_Cmd(ENABLE);
}


void BEEP_Off(void)
{
    BEEP_Cmd(DISABLE);
}

void EXTI_Config(void)
{
    GPIO_Init(GPIOC, GPIO_PIN_1, GPIO_MODE_IN_PU_IT); 
    EXTI_DeInit();
    EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY);
}


void EEPROM_Config(void)
{
    FLASH_DeInit();
    FLASH_Unlock(FLASH_MEMTYPE_DATA);
    FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);   
}

unsigned char buf[16];

void main(void)
{
    u8 i = 0;
    u8 buf_temp[16];
    signed char status;
    
    CLK_Config();
    
    Uart2_Init();
    
    LED_Init();

    EEPROM_Config();    
    //PD4第二功能腳不是beep功能,就強(qiáng)制寫成beep 
    if(FLASH_ReadOptionByte(0x4803) != 0x807F) 
    { 
        FLASH_ProgramOptionByte(0x4803,0x80);//將PD4的第二功能腳寫成beep 
        WWDG->CR = 0x80;//復(fù)位stm8 
    } 
    
    
    BEEP_Config();


    delay_ms(500);
    
    //初始化
    for(i = 0;i < 14;i++)
        tx_buf[i] = 0;
    tx_buf[0] = 0xEE;
    tx_buf[1] = 0xCC;
    tx_buf[2] = 0xFE;
    tx_buf[3] = 0x01;
    tx_buf[13] = 0xFF;

    if(MFRC531_Init() == MI_OK) //MFRC531初始化
    {
        BEEP_On();
        delay_ms(200);
        BEEP_Off();
        LED_On();
    }
    else
    {
        BEEP_On();
        delay_ms(200);
        BEEP_Off();
        delay_ms(200);
        BEEP_On();
        delay_ms(200);
        BEEP_Off();
        LED_Off();
        while(1);
    }
    
    MFRC531_CfgISOType('A'); 
    
    rx_counter = 0;
    Uart_RecvFlag = 0;
    Flag = 0;
 
    enableInterrupts();
       
    while (1)
    { 
        if(Flag == 0) // 未發(fā)現(xiàn)卡沿癞,尋卡
        {
          //UART2_SendString("no card is find\r", 17);
            status = MFRC531_OpenAnt();
            delay_ms(10);
        
            status = PcdRequest(0x52, g_pTagType);
        
            status = PcdAnticoll(g_cSNR);
        
            status = PcdSelect(g_cSNR,&buf_temp[0]);

            if(MI_OK != status)
            {
                Flag = 0;
            }
            else  // 獲取卡號和余額
            {
                Flag = 1;
                
                ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                status = PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰                            
                status = PcdRead(1, money);
                
                // 判斷是否進(jìn)行過初始化援雇,如果沒有,初始化錢包內(nèi)的余額為0
                if(money[12] == 0x01)//已經(jīng)初始化
                {
                    tx_buf[4] = 0x03;
                    tx_buf[5] = g_cSNR[0];
                    tx_buf[6] = g_cSNR[1];
                    tx_buf[7] = g_cSNR[2];
                    tx_buf[8] = g_cSNR[3];
                    tx_buf[9] = money[3];
                    tx_buf[10] = money[2];
                    tx_buf[11] = money[1];
                    tx_buf[12] = money[0];
                    
                    UART2_SendString(tx_buf, 14);
                    //UART2_SendString(tx_buf, 14);
                    //UART2_SendString(tx_buf, 14);
                }
                else//未初始化
                {
                    ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                    PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                    status = PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰 
                    //money初始化
                    buf_temp[0] = 0;
                    buf_temp[1] = 0;
                    buf_temp[2] = 0;
                    buf_temp[3] = 0;
                    buf_temp[4] = 0xff;
                    buf_temp[5] = 0xff;
                    buf_temp[6] = 0xff;
                    buf_temp[7] = 0xff;
                    buf_temp[8] = 0;
                    buf_temp[9] = 0;
                    buf_temp[10] = 0;
                    buf_temp[11] = 0;
                    buf_temp[12] = 0x01;
                    buf_temp[13] = 0xfe;
                    buf_temp[14] = 0x01;
                    buf_temp[15] = 0xfe;
                    status = PcdWrite(1,buf_temp);
                    
                    
                    tx_buf[4] = 0x03;
                    tx_buf[5] = g_cSNR[0];
                    tx_buf[6] = g_cSNR[1];
                    tx_buf[7] = g_cSNR[2];
                    tx_buf[8] = g_cSNR[3];
                    tx_buf[9] = 0;
                    tx_buf[10] = 0;
                    tx_buf[11] = 0;
                    tx_buf[12] = 0;
                    
                    UART2_SendString(tx_buf, 14);
                    //UART2_SendString(tx_buf, 14);
                    //UART2_SendString(tx_buf, 14);                  
                }
                
                //Flag = 0;// by smartt
                delay_ms(1000);
            }  
        }

        if(Uart_RecvFlag&Flag)  // 已發(fā)現(xiàn)卡椎扬,讀寫
        {
            //rx_buf的第6-9位是要充值的余額
            money_buf[0] = rx_buf[8];
            money_buf[1] = rx_buf[7];
            money_buf[2] = rx_buf[6];
            money_buf[3] = rx_buf[5];
            
            switch(rx_buf[4])
            {
            case 0x01:  // 充值
                tx_buf[4] = 0x01;
                ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰 
                status = PcdValue(0xC1, 1, money_buf);
                ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰
                status = PcdRead(1, money);
                if(MI_OK == status)
                {
                    tx_buf[9] = money[3];
                    tx_buf[10] = money[2];
                    tx_buf[11] = money[1];
                    tx_buf[12] = money[0];
                        
                    UART2_SendString(tx_buf, 14);
                }
                else
                {
                    Flag = 0; 
                }
                break;
            case 0x02:  // 扣款
                tx_buf[4] = 0x02;
                ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰 
                status = PcdValue(0xC0, 1, money_buf);
                ChangeCodeKey(p_KeyA,p_Key);    //轉(zhuǎn)換密鑰格式
                PcdAuthKey(p_Key);              //傳送密鑰到RC531 FIFO
                PcdAuthState(0x60, 1, g_cSNR);  //驗(yàn)證密鑰
                status = PcdRead(1, money);
                if(MI_OK == status)
                {
                    tx_buf[9] = money[3];
                    tx_buf[10] = money[2];
                    tx_buf[11] = money[1];
                    tx_buf[12] = money[0];
                        
                    UART2_SendString(tx_buf, 14);
                }
                else
                {
                    Flag = 0; 
                }
                break;   
            default:
                break;   
            }
   
            
            LED_Toggle();
        Uart_RecvFlag = 0;
        }
    }
}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

版權(quán)聲明:本文為CSDN博主「路燈謠」的原創(chuàng)文章惫搏,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明蚕涤。
原文鏈接:https://blog.csdn.net/lululumiao/article/details/117181671

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末筐赔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子揖铜,更是在濱河造成了極大的恐慌茴丰,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件天吓,死亡現(xiàn)場離奇詭異贿肩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)失仁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門尸曼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萄焦,你說我怎么就攤上這事控轿。” “怎么了拂封?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵茬射,是天一觀的道長。 經(jīng)常有香客問我冒签,道長在抛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任萧恕,我火速辦了婚禮刚梭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘票唆。我一直安慰自己朴读,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布走趋。 她就那樣靜靜地躺著衅金,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氮唯,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天鉴吹,我揣著相機(jī)與錄音,去河邊找鬼惩琉。 笑死豆励,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的琳水。 我是一名探鬼主播肆糕,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼般堆,長吁一口氣:“原來是場噩夢啊……” “哼在孝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淮摔,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤私沮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后和橙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仔燕,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年魔招,在試婚紗的時候發(fā)現(xiàn)自己被綠了晰搀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡办斑,死狀恐怖外恕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乡翅,我是刑警寧澤鳞疲,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蠕蚜,受9級特大地震影響尚洽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靶累,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一腺毫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挣柬,春花似錦潮酒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春叁熔,著一層夾襖步出監(jiān)牢的瞬間委乌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工荣回, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留遭贸,地道東北人。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓心软,卻偏偏與公主長得像壕吹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子删铃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容