使用STM32实现简单的智能一卡通

一、项目概述 智能一卡通是基于STM32开发的一种集合了多种功能的智能卡片,可以用于学校、企事业单位以及公共交通等场景。本项目使用STM32微控制器来实现一个简单的智能一卡通系统,具体功能包括:卡片信息存储、充值、消费、余额查询以及简单的数据加密和解密等。

二、硬件准备

  1. STM32微控制器(如STM32F103C8T6)
  2. RC522射频卡读写模块
  3. OLED显示屏
  4. 数字键盘
  5. 若干LED灯

三、软件准备

  1. Keil MDK集成开发环境
  2. STM32CubeMX配置工具
  3. MFRC522 RFID库
  4. u8glib OLED库

四、实现步骤

  1. 硬件连接 将RC522模块的SDA、SCK、MISO、MOSI、IRQ、RST和GND接到STM32开发板的对应引脚上,将RC522模块的3.3V接到STM32的3.3V引脚上。将OLED的SDA、SCK和GND接到STM32的对应引脚上,将OLED的VCC引脚接到3.3V引脚上。将数字键盘的行引脚接到STM32的GPIO引脚上,将列引脚接到GPIO的输入引脚上。将LED的引脚接到STM32的GPIO引脚上。

  2. STM32CubeMX配置 使用STM32CubeMX配置工具生成项目代码。首先选择正确的设备型号(如STM32F103C8T6),然后配置相应的引脚。将RC522模块的SDA引脚、SCK引脚、MISO引脚和MOSI引脚设置为SPI模式,并配置相应的时钟。将OLED的SDA引脚和SCK引脚设置为I2C模式,并配置相应的时钟。将数字键盘的行引脚设置为输出模式,列引脚设置为输入模式。将LED的引脚设置为输出模式。

  3. 代码编写 在Keil MDK中创建一个新工程,将生成的STM32CubeMX代码复制到工程中。

(1)编写MFRC522 RFID库的代码,包括初始化RC522模块、读取卡片信息、写入卡片信息等函数。

(2)编写u8glib OLED库的代码,包括显示文本、图形等函数。

(3)编写数字键盘的驱动代码,包括按键扫描、获取键值等函数。

(4)编写主函数main(),实现智能一卡通的功能。

  1. 主要功能实现 (1)卡片信息存储 当用户第一次使用卡片时,将用户的个人信息(如姓名、学号、余额等)存储到卡片中。

(2)充值 用户可以通过输入金额实现卡片余额的充值。

(3)消费 用户可以通过输入金额实现卡片余额的消费。

(4)余额查询 用户可以通过按键操作实现卡片余额的查询。

(5)数据加密和解密 为了保证卡片信息的安全,可以对存储的卡片信息进行简单的数据加密和解密。

五、代码案例

#include "stm32f1xx_hal.h"
#include "mfrc522.h"
#include "u8g2.h"
#include "keypad.h"

#define OLED_I2C_ADDRESS 0x78

extern SPI_HandleTypeDef hspi1;

extern UART_HandleTypeDef huart1;

uint8_t cardUID[4];
char cardData[64];

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART1_UART_Init(void);

void OLED_Init();
void OLED_DrawString(char* str, int x, int y);
void OLED_Clear();
void OLED_DrawDecimal(int dec, int x, int y);
void OLED_DrawCardData(char* cardData);
void OLED_DrawBalance(int balance);
void OLED_DrawMenu(int currentMenuItem);

void RFID_Init();
void RFID_ReadCardUID();
void RFID_ReadCardData();
void RFID_WriteCardData();

void Keypad_Init();
char Keypad_GetKey();

enum MenuItem {
    BALANCE, RECHARGE, CONSUME
};

int balance = 0;
enum MenuItem currentMenuItem = BALANCE;

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SPI1_Init();
    MX_USART1_UART_Init();
    OLED_Init();
    Keypad_Init();
    RFID_Init();
    
    OLED_Clear();
    OLED_DrawMenu(currentMenuItem);
    
    while (1) {
        char key = Keypad_GetKey();
        
        if (key == '1') {
            currentMenuItem = BALANCE;
            OLED_Clear();
            OLED_DrawMenu(currentMenuItem);
        } else if (key == '2') {
            currentMenuItem = RECHARGE;
            OLED_Clear();
            OLED_DrawMenu(currentMenuItem);
        } else if (key == '3') {
            currentMenuItem = CONSUME;
            OLED_Clear();
            OLED_DrawMenu(currentMenuItem);
        }
        
        if (currentMenuItem == BALANCE) {
            RFID_ReadCardData();
            OLED_DrawCardData(cardData);
            OLED_DrawBalance(balance);
        } else if (currentMenuItem == RECHARGE) {
            RFID_ReadCardData();
            OLED_DrawCardData(cardData);
            
            OLED_DrawString("Amount to recharge:", 0, 32);
            int rechargeAmount = 0;
            char key = '0';
            do {
                key = Keypad_GetKey();
                if (key >= '0' && key <= '9') {
                    rechargeAmount = rechargeAmount * 10 + key - '0';
                    OLED_DrawDecimal(rechargeAmount, 128, 32);
                }
            } while (key != '#');
            
            balance += rechargeAmount;
            RFID_WriteCardData();
            
            OLED_Clear();
            OLED_DrawMenu(currentMenuItem);
            OLED_DrawCardData(cardData);
            OLED_DrawBalance(balance);
        } else if (currentMenuItem == CONSUME) {
            RFID_ReadCardData();
            OLED_DrawCardData(cardData);
            
            OLED_DrawString("Amount to consume:", 0, 32);
            int consumeAmount = 0;
            char key = '0';
            do {
                key = Keypad_GetKey();
                if (key >= '0' && key <= '9') {
                    consumeAmount = consumeAmount * 10 + key - '0';
                    OLED_DrawDecimal(consumeAmount, 128, 32);
                }
            } while (key != '#');
            
            if (balance >= consumeAmount) {
                balance -= consumeAmount;
                RFID_WriteCardData();
            } else {
                OLED_Clear();
                OLED_DrawString("Insufficient balance", 0, 16);
                HAL_Delay(2000);
            }
            
            OLED_Clear();
            OLED_DrawMenu(currentMenuItem);
            OLED_DrawCardData(cardData);
            OLED_DrawBalance(balance);
        }
    }
}

void OLED_Init() {
    u8g2_t u8g2;
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_sw_i2c_delay);
    u8x8_SetI2CAddress(u8g2_GetU8x8(&u8g2), OLED_I2C_ADDRESS);
    u8g2_InitDisplay(&u8g2);
    u8g2_SetPowerSave(&u8g2, 0);
}

void OLED_DrawString(char* str, int x, int y) {
    u8g2_t u8g2;
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_sw_i2c_delay);
    u8x8_SetI2CAddress(u8g2_GetU8x8(&u8g2), OLED_I2C_ADDRESS);
    u8g2_FirstPage(&u8g2);
    do {
        u8g2_DrawStr(&u8g2, x, y, str);
    } while (u8g2_NextPage(&u8g2));
}

void OLED_Clear() {
    u8g2_t u8g2;
    u8g2_Setup_ssd1306_i2c_128x

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CrMylive.

穷呀,求求补助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值