找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 126|回复: 5
打印 上一主题 下一主题
收起左侧

求助怎么解决isp串口工具输出乱码

[复制链接]
跳转到指定楼层
楼主
ID:1154560 发表于 2025-6-20 17:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
姓名: 张?  李四  王五
张三不能正常显示三,其他还没有尝试
以下是我的代码
#include <reg52.h>
#include "lcd1602.h"
#include "mfrc522.h"
#include "uart.h"
#include <stdio.h>

// 定义蜂鸣器控制端口
sbit BUZZER = P3^6;

// 系统时钟频率(Hz),用于计算延时
#define FOSC 11059200

// 学生信息结构体定义
typedef struct {
    unsigned char card_id[4];    // 卡片ID
    unsigned char student_id[10]; // 学生学号
    unsigned char name[20];      // 学生姓名
} StudentInfo;

// 预定义学生信息 (3名学生)
StudentInfo students[3] = {
    {{0xE4, 0xCA, 0x18, 0x05}, "2501", "张三"},
    {{0x16, 0x41, 0xC0, 0x01}, "2502", "李四"},
    {{0x70, 0x02, 0x53, 0xF4}, "2503", "王五"},

};

// 定义卡片数量
#define CARD_COUNT 3

// 定义系统状态
#define SYSTEM_IDLE       0  // 空闲状态
#define SYSTEM_SUCCESS    1  // 签到成功状态
#define SYSTEM_FAILURE    2  // 签到失败状态
volatile unsigned char systemState = SYSTEM_IDLE;
volatile unsigned int displayTimer = 0;  // 显示计时器

// 定义卡片数据缓冲区
unsigned char card_data[16];
unsigned char current_card_id[4];
unsigned char display_card_id_str[13];  // 显示用卡号字符串

// 存储当前学生信息
unsigned char current_student_id[10];   // 当前学生学号
unsigned char current_student_name[20]; // 当前学生姓名

// 蜂鸣器状态定义
#define BEEP_IDLE   0  // 空闲状态
#define BEEP_ON     1  // 蜂鸣器开启
#define BEEP_OFF    2  // 蜂鸣器关闭
volatile unsigned char beepState = BEEP_IDLE;  // 蜂鸣器状态
volatile unsigned char beepCount = 0;         // 剩余鸣叫次数
volatile unsigned int beepTimer = 0;          // 计时计数器

// 蜂鸣器发声函数 - 成功时短鸣
void beep_success(void) {
    unsigned int i, j;
    for(i = 0; i < 1000; i++) {
        BUZZER = ~BUZZER;
        for(j = 0; j < 30; j++);  // 约0.5ms延时,1000次约500ms
    }
    BUZZER = 0;  // 确保蜂鸣器最终关闭
}

/**
* 蜂鸣器失败提示音 - 短鸣三声(终极优化版)
* 通过精确计时确保三声鸣叫一致且立即停止
*/
void beep_failure(void) {
    if(beepState == BEEP_IDLE) {  // 仅在空闲状态下启动
        beepState = BEEP_ON;       // 切换到开启状态
        beepCount = 3;             // 设置鸣响3次
        beepTimer = 500;           // 首次鸣响500ms
    }
}

// 蜂鸣器任务
void beepTask(void) {
    static unsigned int beepCounter = 0;  // 新增计数器,跟踪精确计时
   
    // 如果处于空闲状态,直接返回,不执行任何操作
    if(beepState == BEEP_IDLE) {
        return;
    }
   
    switch(beepState) {
        case BEEP_ON:
            BUZZER = ~BUZZER;  // 翻转电平发声
            
            // 精确计时控制
            if(++beepCounter >= 200) {  // 500次计数约500ms
                beepCounter = 0;
                BUZZER = 0;                // 关闭蜂鸣器
               
                // 检查是否为最后一声
                if(beepCount == 1) {
                    beepState = BEEP_IDLE; // 最后一声后直接进入空闲状态
                    BUZZER = 0;            // 双重确保蜂鸣器关闭
                } else {
                    beepState = BEEP_OFF;  // 否则进入间隔状态
                    beepTimer = 300;       // 间隔300ms
                }
            }
            break;
            
        case BEEP_OFF:
            if(++beepCounter >= 300) {  // 300次计数约300ms
                beepCounter = 0;
                beepCount--;                 // 剩余次数减1
                beepState = BEEP_ON;         // 继续鸣响
                beepTimer = 500;             // 鸣响500ms
            }
            break;
            
        default:
            beepCounter = 0;  // 重置计数器
            beepState = BEEP_IDLE;
            BUZZER = 0;       // 确保蜂鸣器关闭
            break;
    }
}

// 显示欢迎信息
void display_welcome(void) {
    LCDInit();
    DisplayListChar(0, 0, "Student Attend");
    DisplayListChar(0, 1, "Place Card Here");
}

// 显示状态处理函数
void displayTask(void) {
    switch(systemState) {
        case SYSTEM_SUCCESS:
            if(displayTimer > 0) {
                displayTimer--;
            } else {
                systemState = SYSTEM_IDLE;
                display_welcome();
            }
            break;
            
        case SYSTEM_FAILURE:
            if(displayTimer > 0) {
                displayTimer--;
            } else {
                systemState = SYSTEM_IDLE;
                display_welcome();
            }
            break;
            
        default: break;
    }
}

// 查找学生信息
bit find_student_info(unsigned char *card_id) {
    unsigned char i, j;
   
    // 遍历所有学生信息
    for(i = 0; i < CARD_COUNT; i++) {
        // 逐个字节比较卡号
        for(j = 0; j < 4; j++) {
            if(card_id[j] != students[i].card_id[j]) {
                break;
            }
        }
        
        // 如果4个字节都匹配,找到学生信息
        if(j == 4) {
            // 复制学生ID和姓名
            for(j = 0; j < 10 && students[i].student_id[j] != '\0'; j++) {
                current_student_id[j] = students[i].student_id[j];
            }
            current_student_id[j] = '\0';
            
            for(j = 0; j < 20 && students[i].name[j] != '\0'; j++) {
                current_student_name[j] = students[i].name[j];
            }
            current_student_name[j] = '\0';
            
            return 1;
        }
    }
   
    // 未找到匹配的学生信息
    return 0;
}

// 显示签到成功信息
void display_success(unsigned char *card_id) {
    unsigned char i, j;
   
    // 转换卡号为字符串(保持LCD显示不变)
    j = 0;
    for(i = 0; i < 4; i++) {
        display_card_id_str[j++] = (card_id[i] >> 4) + ((card_id[i] >> 4) < 10 ? '0' : 'A' - 10);
        display_card_id_str[j++] = (card_id[i] & 0x0F) + ((card_id[i] & 0x0F) < 10 ? '0' : 'A' - 10);
        display_card_id_str[j++] = ' ';
    }
    display_card_id_str[j] = '\0';
   
    // 发出成功提示音
    beep_success();
   
    // 设置显示状态
    LCDInit();
    DisplayListChar(0, 0, "Attend Success!");
    DisplayListChar(0, 1, display_card_id_str);
   
    systemState = SYSTEM_SUCCESS;
    displayTimer = 5000;  // 5000个滴答 = 约5秒
   
    // 查找学生信息
    if(find_student_info(card_id)) {
        // 通过串口发送学生信息
        Uart_Send_String("签到成功 - ");
        Uart_Send_String("学号: ");
        Uart_Send_String(current_student_id);
        Uart_Send_String(" 姓名: ");
        Uart_Send_String(current_student_name);
        Uart_Send_String("\r\n");
    } else {
        // 未找到学生信息,发送卡号
        Uart_Send_String("签到成功 - 卡号: ");
        for(i = 0; i < 4; i++) {
            Sent_UART((card_id[i] >> 4) + ((card_id[i] >> 4) < 10 ? '0' : 'A' - 10));
            Sent_UART((card_id[i] & 0x0F) + ((card_id[i] & 0x0F) < 10 ? '0' : 'A' - 10));
            Sent_UART(' ');
        }
        Sent_UART('\r');
        Sent_UART('\n');
    }
}

// 显示签到失败信息
void display_failure(unsigned char *card_id) {
    unsigned char i, j;
   
    // 转换卡号为字符串
    j = 0;
    for(i = 0; i < 4; i++) {
        display_card_id_str[j++] = (card_id[i] >> 4) + ((card_id[i] >> 4) < 10 ? '0' : 'A' - 10);
        display_card_id_str[j++] = (card_id[i] & 0x0F) + ((card_id[i] & 0x0F) < 10 ? '0' : 'A' - 10);
        display_card_id_str[j++] = ' ';
    }
    display_card_id_str[j] = '\0';
   
    // 发出失败提示音
    beep_failure();
   
    // 设置显示状态
    LCDInit();
    DisplayListChar(0, 0, "Invalid Card!");
    DisplayListChar(0, 1, display_card_id_str);
   
    systemState = SYSTEM_FAILURE;
    displayTimer = 5000;  // 5000个滴答 = 约5秒
   
    // 通过串口发送未授权卡片信息
    Uart_Send_String("未授权卡片 - 卡号: ");
    for(i = 0; i < 4; i++) {
        Sent_UART((card_id[i] >> 4) + ((card_id[i] >> 4) < 10 ? '0' : 'A' - 10));
        Sent_UART((card_id[i] & 0x0F) + ((card_id[i] & 0x0F) < 10 ? '0' : 'A' - 10));
        Sent_UART(' ');
    }
    Sent_UART('\r');
    Sent_UART('\n');
}

// 核对卡片ID是否合法
bit check_card_id(unsigned char *card_id) {
    unsigned char i, j;
   
    // 遍历所有学生信息
    for(i = 0; i < CARD_COUNT; i++) {
        // 逐个字节比较卡号
        for(j = 0; j < 4; j++) {
            if(card_id[j] != students[i].card_id[j]) {
                break;
            }
        }
        
        // 如果4个字节都匹配,返回合法
        if(j == 4) {
            return 1;
        }
    }
   
    // 未找到匹配的卡片,返回不合法
    return 0;
}

// 主函数
void main(void) {
    unsigned char card_detected = 0;
   
    // 初始化系统
    PcdReset();         // 初始化RC522
    Uart_Init();        // 初始化串口
    LCDInit();          // 初始化LCD
    BUZZER = 0;         // 初始化蜂鸣器端口
    // 串口提示系统启动
    Uart_Send_String("RFID Attendance System Started\r\n");
   
    display_welcome();  // 显示欢迎信息
   
    while(1) {
        // 处理蜂鸣器状态
        beepTask();
        
        // 处理显示状态
        displayTask();
        
        // 检测卡片(仅在空闲状态下检测)
        if(systemState == SYSTEM_IDLE &&
           PcdRequest(PICC_REQIDL, &card_data[0]) == MI_OK) {
            // 防冲突,获取卡片序列号
            if(PcdAnticoll(current_card_id) == MI_OK) {
                // 选卡
                if(PcdSelect(current_card_id) == MI_OK) {
                    card_detected = 1;
                    
                    // 核对卡片ID
                    if(check_card_id(current_card_id)) {
                        // 合法卡片,显示签到成功
                        display_success(current_card_id);
                    } else {
                        // 非法卡片,显示失败
                        display_failure(current_card_id);
                    }
                    
                    // 让卡片进入休眠状态
                    PcdHalt();
                }
            }
        }
        
        // 延时降低CPU使用率(精确延时)
        delay_ms(1);  // 1ms延时,提高响应速度
    }
}
                    
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:879809 发表于 2025-6-20 19:07 | 只看该作者
乱码无非就是几个问题,波特率,位数,有无校验,字符编码。
回复

使用道具 举报

板凳
ID:1154560 发表于 2025-6-20 22:53 | 只看该作者
rundstedt 发表于 2025-6-20 19:07
乱码无非就是几个问题,波特率,位数,有无校验,字符编码。

只有一个三字乱码其他都没有呀,如果是这些问题会不会其他也乱码
回复

使用道具 举报

地板
ID:685462 发表于 2025-6-20 23:16 | 只看该作者
文本的编码方式需要确定一下
回复

使用道具 举报

5#
ID:1154560 发表于 2025-6-21 14:28 来自触屏版 | 只看该作者
lose2836 发表于 2025-6-20 23:16
文本的编码方式需要确定一下

GBK编码
回复

使用道具 举报

6#
ID:155507 发表于 2025-6-22 09:21 | 只看该作者
关于 Keil 软件中 0xFD 问题的说明
众所周知,Keil 软件的 8051 和 80251 编译器的所有版本都有一个叫做 0xFD 的问题,主要表现在字
符串中不能含有带 0xFD 编码的汉字,否则 Keil 软件在编译时会跳过 0xFD 而出现乱码。
关于这个问题,Keil 官方的回应是:0xfd、0xfe、0xff 这 3 个字符编码被 Keil 编译器内部使用,所
以代码中若包含有 0xfd 的字符串时,0xfd 会被编译器自动跳过。
Keil 官方提供的解决方法:在带有 0xfd 编码的汉字后增加一个 0xfd 即可。例如:
printf("数学"); //Keil 编译后打印会显示乱码
printf("数\xfd 学"); //显示正常
这里的“\xfd”是标准 C 代码中的转义字符,“\x”表示其后的 1~2 个字符为 16 进制数。“\xfd”表
示将 16 进制数 0xfd 插入到字符串中。
由于“数”的汉字编码是 0xCAFD,Keil 在编译时会将 FD 跳过,而只将 CA 编译到目标文件中,后
面通过转义字符手动再补一个 0xfd 到目标文件中,就形成完整的 0xCAFD,从而可正常显示。
关于 0xFD 的补丁网上有很多,基本只对旧版本的 Keil 软件有效。打补丁的方法均是在可执行文件
中查找关键代码[80 FB FD],并修改为[80 FB FF],这种修改方法查找的关键代码过于简单,很容易修改
到其它无关的地方,导致编译出来的目标文件运行时出现莫名其妙的问题。所以,代码中的字符串有包
含如下的汉字时,建议使用 Keil 官方提供的解决方法进行解决
GB2312 中,包含 0xfd 编码的汉字如下:
褒饼昌除待谍洱俘庚过糊积箭烬君魁
例笼慢谬凝琵讫驱三升数她听妄锡淆
旋妖引育札正铸 佚冽邶埤荦蔟摭啐
帻猃恺泯潺妪纨琮椠辇挲臊忑睚铨稞
瘕颀螨簖酏觚鳊鼾
另外,Keil 项目路径名的字符中也不能含有带 0xFD 编码的汉字,否则 Keil 软件会无法正确编译此
项目。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表