標題: 求助怎么解決isp串口工具輸出亂碼 [打印本頁]

作者: tianxi第一    時間: 2025-6-20 17:45
標題: 求助怎么解決isp串口工具輸出亂碼
姓名: 張?  李四  王五
張三不能正常顯示三,其他還沒有嘗試
以下是我的代碼
#include <reg52.h>
#include "lcd1602.h"
#include "mfrc522.h"
#include "uart.h"
#include <stdio.h>

// 定義蜂鳴器控制端口
sbit BUZZER = P3^6;

// 系統(tǒng)時鐘頻率(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", "王五"},

};

// 定義卡片數(shù)量
#define CARD_COUNT 3

// 定義系統(tǒng)狀態(tài)
#define SYSTEM_IDLE       0  // 空閑狀態(tài)
#define SYSTEM_SUCCESS    1  // 簽到成功狀態(tài)
#define SYSTEM_FAILURE    2  // 簽到失敗狀態(tài)
volatile unsigned char systemState = SYSTEM_IDLE;
volatile unsigned int displayTimer = 0;  // 顯示計時器

// 定義卡片數(shù)據(jù)緩沖區(qū)
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]; // 當前學生姓名

// 蜂鳴器狀態(tài)定義
#define BEEP_IDLE   0  // 空閑狀態(tài)
#define BEEP_ON     1  // 蜂鳴器開啟
#define BEEP_OFF    2  // 蜂鳴器關閉
volatile unsigned char beepState = BEEP_IDLE;  // 蜂鳴器狀態(tài)
volatile unsigned char beepCount = 0;         // 剩余鳴叫次數(shù)
volatile unsigned int beepTimer = 0;          // 計時計數(shù)器

// 蜂鳴器發(fā)聲函數(shù) - 成功時短鳴
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;  // 確保蜂鳴器最終關閉
}

/**
* 蜂鳴器失敗提示音 - 短鳴三聲(終極優(yōu)化版)
* 通過精確計時確保三聲鳴叫一致且立即停止
*/
void beep_failure(void) {
    if(beepState == BEEP_IDLE) {  // 僅在空閑狀態(tài)下啟動
        beepState = BEEP_ON;       // 切換到開啟狀態(tài)
        beepCount = 3;             // 設置鳴響3次
        beepTimer = 500;           // 首次鳴響500ms
    }
}

// 蜂鳴器任務
void beepTask(void) {
    static unsigned int beepCounter = 0;  // 新增計數(shù)器,跟蹤精確計時
   
    // 如果處于空閑狀態(tài),直接返回,不執(zhí)行任何操作
    if(beepState == BEEP_IDLE) {
        return;
    }
   
    switch(beepState) {
        case BEEP_ON:
            BUZZER = ~BUZZER;  // 翻轉電平發(fā)聲
            
            // 精確計時控制
            if(++beepCounter >= 200) {  // 500次計數(shù)約500ms
                beepCounter = 0;
                BUZZER = 0;                // 關閉蜂鳴器
               
                // 檢查是否為最后一聲
                if(beepCount == 1) {
                    beepState = BEEP_IDLE; // 最后一聲后直接進入空閑狀態(tài)
                    BUZZER = 0;            // 雙重確保蜂鳴器關閉
                } else {
                    beepState = BEEP_OFF;  // 否則進入間隔狀態(tài)
                    beepTimer = 300;       // 間隔300ms
                }
            }
            break;
            
        case BEEP_OFF:
            if(++beepCounter >= 300) {  // 300次計數(shù)約300ms
                beepCounter = 0;
                beepCount--;                 // 剩余次數(shù)減1
                beepState = BEEP_ON;         // 繼續(xù)鳴響
                beepTimer = 500;             // 鳴響500ms
            }
            break;
            
        default:
            beepCounter = 0;  // 重置計數(shù)器
            beepState = BEEP_IDLE;
            BUZZER = 0;       // 確保蜂鳴器關閉
            break;
    }
}

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

// 顯示狀態(tài)處理函數(shù)
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++) {
        // 逐個字節(jié)比較卡號
        for(j = 0; j < 4; j++) {
            if(card_id[j] != students[i].card_id[j]) {
                break;
            }
        }
        
        // 如果4個字節(jié)都匹配,找到學生信息
        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';
   
    // 發(fā)出成功提示音
    beep_success();
   
    // 設置顯示狀態(tài)
    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)) {
        // 通過串口發(fā)送學生信息
        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 {
        // 未找到學生信息,發(fā)送卡號
        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';
   
    // 發(fā)出失敗提示音
    beep_failure();
   
    // 設置顯示狀態(tài)
    LCDInit();
    DisplayListChar(0, 0, "Invalid Card!");
    DisplayListChar(0, 1, display_card_id_str);
   
    systemState = SYSTEM_FAILURE;
    displayTimer = 5000;  // 5000個滴答 = 約5秒
   
    // 通過串口發(fā)送未授權卡片信息
    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++) {
        // 逐個字節(jié)比較卡號
        for(j = 0; j < 4; j++) {
            if(card_id[j] != students[i].card_id[j]) {
                break;
            }
        }
        
        // 如果4個字節(jié)都匹配,返回合法
        if(j == 4) {
            return 1;
        }
    }
   
    // 未找到匹配的卡片,返回不合法
    return 0;
}

// 主函數(shù)
void main(void) {
    unsigned char card_detected = 0;
   
    // 初始化系統(tǒng)
    PcdReset();         // 初始化RC522
    Uart_Init();        // 初始化串口
    LCDInit();          // 初始化LCD
    BUZZER = 0;         // 初始化蜂鳴器端口
    // 串口提示系統(tǒng)啟動
    Uart_Send_String("RFID Attendance System Started\r\n");
   
    display_welcome();  // 顯示歡迎信息
   
    while(1) {
        // 處理蜂鳴器狀態(tài)
        beepTask();
        
        // 處理顯示狀態(tài)
        displayTask();
        
        // 檢測卡片(僅在空閑狀態(tài)下檢測)
        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);
                    }
                    
                    // 讓卡片進入休眠狀態(tài)
                    PcdHalt();
                }
            }
        }
        
        // 延時降低CPU使用率(精確延時)
        delay_ms(1);  // 1ms延時,提高響應速度
    }
}
                    
作者: rundstedt    時間: 2025-6-20 19:07
亂碼無非就是幾個問題,波特率,位數(shù),有無校驗,字符編碼。
作者: tianxi第一    時間: 2025-6-20 22:53
rundstedt 發(fā)表于 2025-6-20 19:07
亂碼無非就是幾個問題,波特率,位數(shù),有無校驗,字符編碼。

只有一個三字亂碼其他都沒有呀,如果是這些問題會不會其他也亂碼

作者: lose2836    時間: 2025-6-20 23:16
文本的編碼方式需要確定一下
作者: tianxi第一    時間: 2025-6-21 14:28
lose2836 發(fā)表于 2025-6-20 23:16
文本的編碼方式需要確定一下

GBK編碼
作者: angmall    時間: 2025-6-22 09:21
關于 Keil 軟件中 0xFD 問題的說明
眾所周知,Keil 軟件的 8051 和 80251 編譯器的所有版本都有一個叫做 0xFD 的問題,主要表現(xiàn)在字
符串中不能含有帶 0xFD 編碼的漢字,否則 Keil 軟件在編譯時會跳過 0xFD 而出現(xiàn)亂碼。
關于這個問題,Keil 官方的回應是:0xfd、0xfe、0xff 這 3 個字符編碼被 Keil 編譯器內部使用,所
以代碼中若包含有 0xfd 的字符串時,0xfd 會被編譯器自動跳過。
Keil 官方提供的解決方法:在帶有 0xfd 編碼的漢字后增加一個 0xfd 即可。例如:
printf("數(shù)學"); //Keil 編譯后打印會顯示亂碼
printf("數(shù)\xfd 學"); //顯示正常
這里的“\xfd”是標準 C 代碼中的轉義字符,“\x”表示其后的 1~2 個字符為 16 進制數(shù)!癨xfd”表
示將 16 進制數(shù) 0xfd 插入到字符串中。
由于“數(shù)”的漢字編碼是 0xCAFD,Keil 在編譯時會將 FD 跳過,而只將 CA 編譯到目標文件中,后
面通過轉義字符手動再補一個 0xfd 到目標文件中,就形成完整的 0xCAFD,從而可正常顯示。
關于 0xFD 的補丁網(wǎng)上有很多,基本只對舊版本的 Keil 軟件有效。打補丁的方法均是在可執(zhí)行文件
中查找關鍵代碼[80 FB FD],并修改為[80 FB FF],這種修改方法查找的關鍵代碼過于簡單,很容易修改
到其它無關的地方,導致編譯出來的目標文件運行時出現(xiàn)莫名其妙的問題。所以,代碼中的字符串有包
含如下的漢字時,建議使用 Keil 官方提供的解決方法進行解決
GB2312 中,包含 0xfd 編碼的漢字如下:
褒餅昌除待諜洱俘庚過糊積箭燼君魁
例籠慢謬凝琵訖驅三升數(shù)她聽妄錫淆
旋妖引育札正鑄 佚冽邶埤犖蔟摭啐
幘獫愷泯潺嫗紈琮槧輦挲臊忑睚銓稞
瘕頎螨籪酏觚鳊鼾
另外,Keil 項目路徑名的字符中也不能含有帶 0xFD 編碼的漢字,否則 Keil 軟件會無法正確編譯此
項目。





歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1