久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3|回復: 0
收起左側

求助單片機仿真程序,找不到修復的地方

[復制鏈接]
ID:1144486 發(fā)表于 2025-4-22 14:22 | 顯示全部樓層 |閱讀模式
求求各位指導一下我維修的方向,程序仿真lcd1602不顯示任何字符,按鈕只有最后一列有反饋
所有程序:
dht11.h的程序:
// dht11.h
#ifndef __DHT11_H__
#define __DHT11_H__

#include "main.h"


void DHT11_Start(void);
unsigned char DHT11_Read(void);
float Read_TRH(UCHAR channel);

#endif




dht11.c的程序:
// dht11.c
#include "adc0832.h"
#include "delay.h"
#include "dht11.h"
#include "HW_key.h"
#include "main.h"
#include "lcd1602.h"
#include <intrins.h>
#include <reg52.h>
sbit DHT11_DATA = P1^7;  // 定義數(shù)據(jù)引腳

// 函數(shù)聲明
void DHT11_Start(void) {
    DHT11_DATA = 0;
    Delay_ms(18);
    DHT11_DATA = 1;
    Delay_us(30);
}
unsigned char DHT11_Read(void) {
    unsigned char i = 0;
        unsigned char received_data = 0;
    for(i = 0; i < 8; i++) {  // 變量i必須在循環(huán)外聲明
        received_data <<= 1;
        while(!DHT11_DATA);
        Delay_us(30);
        if(DHT11_DATA)
            received_data |= 0x01;
        while(DHT11_DATA);
    }
    return received_data;
}
float Read_TRH(UCHAR channel) {

    unsigned char dht_data[5]; // 重命名數(shù)組
    unsigned char i; // 提前聲明循環(huán)變量
    float temperature = 0.0;
    float humidity = 0.0;

    DHT11_Start();

    for(i = 0; i < 5; i++) {
        dht_data[i] = DHT11_Read(); // 使用新名稱
    }

    if(dht_data[4] == (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3])) {
        if(channel == 1) {
            temperature = dht_data[2];
            temperature += dht_data[3] / 10.0;
            if (dht_data[2] & 0x80) {
                temperature = -((dht_data[2] & 0x7F) + dht_data[3] / 10.0);
            }
            return temperature;
        }
        else if(channel == 0) {
            humidity = (dht_data[0] * 256.0 + dht_data[1]) / 10.0;
            return humidity;
        }
    }
    return 0.0;
}




adc0832.h的程序:
// adc0832.h
#ifndef __ADC0832_H__
#define __ADC0832_H__

#include "main.h"

sbit ADC0832_CS = P1^2;  // 避免與其它模塊共用P1口
sbit ADC0832_CLK = P1^1;
sbit ADC0832_DI = P1^0;
sbit ADC0832_DO = P1^0;

// 函數(shù)聲明
unsigned char ADC0832_Read(unsigned char channel);

#endif // __ADC0832_H__




adc0832.c的程序:
// adc0832.c
#include "adc0832.h"
#include "delay.h"
#include "dht11.h"
#include "HW_key.h"
#include "main.h"
#include "lcd1602.h"
#include <intrins.h>


unsigned char ADC0832_Read(unsigned char channel) {
    unsigned char i;
        unsigned char adc_data = 0;  // 變量名改為 adc_data
    ADC0832_CS = 0;
    ADC0832_CLK = 0;
    ADC0832_DI = 1;


    ADC0832_CLK = 1; _nop_(); ADC0832_CLK = 0;
    ADC0832_DI = (channel >> 0) & 0x01;
    ADC0832_CLK = 1; _nop_(); ADC0832_CLK = 0;
    ADC0832_DI = (channel >> 1) & 0x01;
    ADC0832_CLK = 1; _nop_(); ADC0832_CLK = 0;


    for(i = 0; i < 8; i++) {
        ADC0832_CLK = 1;
        adc_data <<= 1;          // 同步修改變量名
        if(ADC0832_DO) {
            adc_data |= 0x01;    // 同步修改變量名
        }
        ADC0832_CLK = 0;
    }
    ADC0832_CS = 1;
    return adc_data;             // 同步修改變量名
}





delay.c的程序:
// delay.c
#include "adc0832.h"
#include "delay.h"
#include "dht11.h"
#include "HW_key.h"
#include "main.h"
#include "lcd1602.h"
#include <intrins.h>
void Delay_ms(u16 ms) {
    u16 i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 120; j++);
}

void Delay_us(u16 us) {
    while(us--) {
        _nop_(); _nop_(); _nop_(); _nop_(); // 約1us(根據(jù)晶振頻率調整)
    }
}       





delay.h的程序:
// delay.h
#ifndef __DELAY_H__
#define __DELAY_H__

#include "main.h"

void Delay_ms(u16 ms);
void Delay_us(u16 us);

#endif // __DELAY_H__






lcd1602.c的程序:
#include "adc0832.h"
#include "delay.h"
#include "dht11.h"
#include "HW_key.h"
#include "main.h"
#include "lcd1602.h"

#include <intrins.h>  // 包含_nop_()函數(shù)

// 全局變量定義(嚴格符合C89規(guī)范)
LCD_Command lcdQueue[LCD_QUEUE_SIZE];
unsigned char lcdQueueCount = 0;
unsigned char lcdQueueHead = 0;
unsigned char lcdQueueTail = 0;
  // 定義尾指針
bit lcdBusy = 0;
// 命令寫入函數(shù)
void WriteCOMDATA(unsigned char lcd_data, unsigned char cmd) {
    if(lcdQueueCount >= LCD_QUEUE_SIZE) return;

    lcdQueue[lcdQueueTail].lcd_data = lcd_data;
    lcdQueue[lcdQueueTail].isCommand = cmd;
    lcdQueueTail = (lcdQueueTail + 1) % LCD_QUEUE_SIZE;
    lcdQueueCount++;
}

// LCD初始化
void LCD_Init(void) {
    Delay_ms(20);
    WriteCOMDATA(0x38, 1);  // 8位模式,雙行顯示
    Delay_ms(5);
        while (lcdQueueCount > 0);
    WriteCOMDATA(0x0C, 1);  // 顯示開,光標關
    while (lcdQueueCount > 0);
        WriteCOMDATA(0x06, 1);  // 光標右移
    WriteCOMDATA(0x01, 1);  // 清屏
    Delay_ms(5);
}

// 字符寫入函數(shù)
void WriteChar(unsigned char Row, unsigned char Col, unsigned char Num, unsigned char *pBuffer) {
    unsigned char address, i;
    // 計算地址
    address = (Row == 1) ? (0x80 + Col) : (0xC0 + Col);
    WriteCOMDATA(address, 1);

    // 寫入數(shù)據(jù)
    for(i = 0; i < Num; i++) {
        WriteCOMDATA(*pBuffer++, 0);
    }
}

// 命令處理函數(shù)(定時器中斷中調用)
void LCD_Process(void) interrupt 1 {
    if(lcdQueueCount > 0 && !lcdBusy) {
        LCD_Command cmd;

        // 提取命令
        cmd = lcdQueue[lcdQueueHead];
        lcdQueueHead = (lcdQueueHead + 1) % LCD_QUEUE_SIZE;
        lcdQueueCount--;

        // 硬件操作
        lcdBusy = 1;
        RS = cmd.isCommand ? 0 : 1;
        RW = 0;
        LCD_PINDATA = cmd.lcd_data;
        E = 1;
        _nop_(); _nop_(); _nop_(); _nop_();  // 至少保持300ns
        E = 0;
        Delay_us(100);  // 確保命令執(zhí)行完成

        lcdBusy = 0;
               
    }
}








lcd1602.h的程序:
#ifndef __LCD1602_H__
#define __LCD1602_H__

#include "main.h"
// 隊列長度定義
#define LCD_QUEUE_SIZE 16  
// 命令結構體
typedef struct {
    unsigned char lcd_data;
    unsigned char isCommand;
} LCD_Command;
typedef unsigned char u8;  // 添加u8類型定義

extern LCD_Command lcdQueue[LCD_QUEUE_SIZE];
extern unsigned char lcdQueueCount;
extern unsigned char lcdQueueHead;
extern unsigned char lcdQueueTail;  // 新增聲明
extern bit lcdBusy;

// 函數(shù)聲明
void WriteCOMDATA(UCHAR lcd_data, UCHAR cmd);
void LCD_Init(void);
void WriteChar(UCHAR Row, UCHAR Col, UCHAR Num, UCHAR *pBuffer);
void LCD_Process(void) interrupt 1;;

#endif





HW_key.c的程序:
// HW_key.c
#include "adc0832.h"
#include "delay.h"
#include "dht11.h"
#include "HW_key.h"
#include "main.h"
#include "lcd1602.h"
#include <intrins.h>
UCHAR Key_row = 0x0F; // 初始化為無按鍵狀態(tài)

UCHAR KEY_ROW_SCAN(void) {
    // 讀取行引腳狀態(tài)
    Key_row = 0x0F; // 默認無按鍵
    if (ROW1 == 0) Key_row &= ~0x08; // 第1行
    if (ROW2 == 0) Key_row &= ~0x04; // 第2行
    if (ROW3 == 0) Key_row &= ~0x02; // 第3行
    if (ROW4 == 0) Key_row &= ~0x01; // 第4行

    if (Key_row != 0x0F) { // 有按鍵按下
        Delay_ms(10); // 消抖
        if (Key_row != 0x0F) {
            return Key_row;
        }
    }
    return 0x0F; // 無按鍵按下
}

UCHAR KEY_SCAN(void) {
    char key = 0;
    char row = KEY_ROW_SCAN();
    if(row != 0x0F) {
        // 掃描列前復位
        COL1 = 1; COL2 = 1; COL3 = 1; COL4 = 1;

        // 掃描列
        COL1 = 1; COL2 = 0; COL3 = 1; COL4 = 1;
        if(!ROW1) key = '1';
        else if(!ROW2) key = '2';
        else if(!ROW3) key = '3';
        else if(!ROW4) key = 'A';

        COL1 = 0; COL2 = 1; COL3 = 1; COL4 = 1;
        if(!ROW1) key = '4';
        else if(!ROW2) key = '5';
        else if(!ROW3) key = '6';
        else if(!ROW4) key = 'B';

        COL1 = 1; COL2 = 1; COL3 = 0; COL4 = 1;
        if(!ROW1) key = '7';
        else if(!ROW2) key = '8';
        else if(!ROW3) key = '9';
        else if(!ROW4) key = 'C';

        COL1 = 1; COL2 = 1; COL3 = 1; COL4 = 0;
        if(!ROW1) key = '*';
        else if(!ROW2) key = '0';
        else if(!ROW3) key = '#';
        else if(!ROW4) key = 'D';
    }
    return key;
}

void HW_KEY_FUNCTION(void) {
    char key = KEY_SCAN();
    if(key != 0x0F) {
        // 根據(jù)按鍵執(zhí)行相應操作
        switch(key) {
            // 第一行按鍵:調整溫度上限和下限閾值
            case '1':
                T1H = (T1H < 99) ? T1H + 1 : 99;
                break;
            case '2':
                T1H = (T1H > T1L + 1) ? T1H - 1 : T1L + 1;
                break;
            case '3':
                T1L = (T1L < T1H - 1) ? T1L + 1 : T1H - 1;
                break;
            case 'A':
                T1L = (T1L > 0) ? T1L - 1 : 0;
                break;

            // 第二行按鍵:調整濕度上限和下限閾值
            case '4':
                R1H = (R1H < 99) ? R1H + 1 : 99;
                break;
            case '5':
                R1H = (R1H > R1L + 1) ? R1H - 1 : R1L + 1;
                break;
            case '6':
                R1L = (R1L < R1H - 1) ? R1L + 1 : R1H - 1;
                break;
            case 'B':
                             R1L = (R1L > 0) ? R1L - 1 : 0;
                break;

            // 第三行按鍵:調整PM2.5上限和下限閾值
            case '7':
                HPM = (HPM < 9999) ? HPM + 1 : 9999;
                break;
            case '8':
                HPM = (HPM > 0) ? HPM - 1 : 0;
                break;
            case '9':
                HPM = (HPM < 9999) ? HPM + 1 : 9999;
                break;
            case 'C':
                HPM = (HPM > 0) ? HPM - 1 : 0;
                break;

            // 第四行按鍵:進入設置模式,確認操作,返回上一級操作,以及返回當前讀取的溫度、濕度和PM2.5頁面
            case '*':
                shezhi_flag = (shezhi_flag + 1) % 7; // 進入設置模式
                break;
            case '0':
                shezhi_flag = 0; // 確認操作
                break;
            case '#':
                shezhi_flag = 0; // 返回上一級操作
                break;
            case 'D':
                shezhi_flag = 0; // 返回當前讀取的頁面
                break;
            default:
                break;
        }
    }
}






HW_key.h的程序:
// HW_key.h
#ifndef __HW_KEY_H__
#define __HW_KEY_H__

#include "main.h"

extern UCHAR Key_row; // 全局變量聲明

UCHAR KEY_ROW_SCAN(void);
UCHAR KEY_SCAN(void);
void HW_KEY_FUNCTION(void);

#endif // __HW_KEY_H__





main.c的程序:
// main.c
#include "main.h"
#include "LCD1602.h"
#include "dht11.h"
#include "HW_key.h"
#include "adc0832.h"
#include "delay.h"
#include "keymap.h"
#include <stdio.h>
#include <string.h>

// 全局變量定義
int T1L = 12;    // 溫度下限閾值初始值
int T1H = 35;    // 溫度上限閾值初始值
int R1L = 15;    // 濕度下限閾值初始值
int R1H = 60;    // 濕度上限閾值初始值
int HPM = 75;    // PM2.5 上限閾值初始值
UCHAR shezhi_flag = 0; // 設置模式標志
UCHAR Mode_flag = 0;   // 工作模式標志
float pm1 = 0.0;      // 溫度值
float pm2 = 0.0;      // 濕度值
float PM = 0.0;       // PM2.5 值
extern int T1L, T1H, R1L, R1H, HPM;
extern UCHAR shezhi_flag, Mode_flag;
// main.c 中實現(xiàn) read_data:
float read_data(UCHAR channel) {
    return (float)ADC0832_Read(channel);  // 調用 ADC0832_Read
}

// 主函數(shù)
void main(void) {
    // 初始化各個模塊
        Timer0_Init();
    LCD_Init();


    // 主循環(huán)
    while(1) {
        // 1. 讀取傳感器數(shù)據(jù)
        pm1 = Read_TRH(1); // 讀取溫度,假設通道1為溫度
        pm2 = Read_TRH(0); // 讀取濕度,假設通道0為濕度
        PM = read_data(2);     // 讀取PM2.5,假設通道2為PM2.5

        // 2. 處理按鍵輸入
        HW_KEY_FUNCTION();

        // 3. 檢查閾值并控制報警
        check_thresholds();

        // 4. 更新LCD顯示
        update_display();

        // 5. 延時以穩(wěn)定讀取頻率
                set_parameters();
        Delay_ms(200); // 根據(jù)需要調整延時
    }
}

// 檢查閾值并控制報警
void check_thresholds(void) {
    bit temp_alarm = (pm1 > T1H || pm1 < T1L);
    bit humi_alarm = (pm2 > R1H || pm2 < R1L);
    bit pm_alarm = (PM > HPM);

    BUZZER = (temp_alarm || humi_alarm || pm_alarm) ? 0 : 1;

    LED1 = (pm1 > T1H) ? 0 : 1;  // 溫度上限報警
    LED2 = (pm1 < T1L) ? 0 : 1;  // 溫度下限報警
    LED3 = (pm2 > R1H) ? 0 : 1;  // 濕度上限報警
    LED4 = (pm2 < R1L) ? 0 : 1;  // 濕度下限報警
    LED5 = (PM > HPM) ? 0 : 1;   // PM2.5報警
}

// 更新LCD顯示
void update_display(void) {
    char buffer[16];
    // 顯示溫度
    sprintf(buffer, "T:%dC", (int)pm1);
    WriteChar(1, 1, strlen(buffer), buffer);

    // 顯示濕度
    sprintf(buffer, "H:%d%%", (int)pm2);
    WriteChar(1, 9, strlen(buffer), buffer);

    // 顯示PM2.5
    sprintf(buffer, "PM2.5:%d", (int)PM);
    WriteChar(2, 1, strlen(buffer), buffer);
}

void Timer0_Init(void) {
    TMOD |= 0x01;    // 模式1(16位定時器)
    TH0 = 0x3C;      // 12MHz,50ms中斷
    TL0 = 0xB0;
    ET0 = 1;         // 啟用中斷
    EA = 1;          // 全局中斷使能
    TR0 = 1;               // 啟動定時器0
}
// 設置參數(shù)處理函數(shù)
void set_parameters(void) {
    // 根據(jù) shezhi_flag 設置不同的參數(shù)
    // shezhi_flag = 0: 設置溫度上限
    // shezhi_flag = 1: 設置溫度下限
    // shezhi_flag = 2: 設置濕度上限
    // shezhi_flag = 3: 設置濕度下限
    // shezhi_flag = 4: 設置PM2.5上限
    // shezhi_flag = 5: 設置PM2.5下限
    // shezhi_flag = 6: 退出設置模式
    switch(shezhi_flag) {
        case 0:
            // 設置溫度上限
            T1H = (T1H < 99) ? T1H + 1 : 99;
            break;
        case 1:
            // 設置溫度下限
            T1L = (T1L < T1H - 1) ? T1L + 1 : T1H - 1;
            break;
        case 2:
            // 設置濕度上限
            R1H = (R1H < 99) ? R1H + 1 : 99;
            break;
        case 3:
            // 設置濕度下限
            R1L = (R1L < R1H - 1) ? R1L + 1 : R1H - 1;
            break;
        case 4:
            // 設置PM2.5上限
            HPM = (HPM < 9999) ? HPM + 1 : 9999;
            break;
        case 5:
            // 設置PM2.5下限
            // 這里假設沒有單獨的PM2.5下限設置,可以根據(jù)需要調整
            // 例如:
            // PM2.5_L = (PM2.5_L < HPM - 1) ? PM2.5_L + 1 : HPM - 1;
            break;
        case 6:
            // 退出設置模式
            shezhi_flag = 0;
            break;
        default:
            shezhi_flag = 0;
            break;
    }
}

// 鍵盤掃描函數(shù)









main.h的程序:
// main.h
#ifndef __MAIN_H__
#define __MAIN_H__

#include <reg52.h>
#include <string.h>

// 統(tǒng)一硬件接口定義
sbit RS = P1^4;   // LCD 控制引腳
sbit RW = P1^5;
sbit E  = P1^6;

sbit COL1 = P3^4; // 鍵盤列
sbit COL2 = P3^5;
sbit COL3 = P3^6;
sbit COL4 = P3^7;
sbit ROW1 = P3^0; // 鍵盤行
sbit ROW2 = P3^1;
sbit ROW3 = P3^2;
sbit ROW4 = P3^3;

sbit LED1 = P2^0; // 溫度上限報警
sbit LED2 = P2^1; // 溫度下限報警
sbit LED3 = P2^2; // 濕度上限報警
sbit LED4 = P2^3; // 濕度下限報警
sbit LED5 = P2^4; // PM2.5 上限報警
sbit BUZZER = P1^3; // 蜂鳴器
#define LCD_PINDATA P0


typedef unsigned char UCHAR;
typedef unsigned int  u16;
typedef unsigned long u32;

// 全局變量聲明(extern)
extern int T1H, T1L, R1H, R1L, HPM;
extern UCHAR shezhi_flag, Mode_flag;

void Timer0_Init(void);           // 定時器初始化
float read_data(UCHAR channel);   // 讀取PM2.5數(shù)據(jù)
void check_thresholds(void);      // 閾值檢查
void update_display(void);        // 顯示更新
void set_parameters(void);        // 設置參數(shù)處理
UCHAR KEY_SCAN(void);             // 按鍵掃描
void HW_KEY_FUNCTION(void);       // 按鍵功能處理

#endif

51hei圖片_20250422142052.png
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩高清三区 | 色av一区 | 国产精品一区二区久久 | 性色的免费视频 | 精品国产乱码久久久久久牛牛 | 午夜亚洲| 少妇午夜一级艳片欧美精品 | 中文字幕在线二区 | 四虎伊人| 欧美二三区 | 色婷婷精品| 人人种亚洲 | 欧美9999 | 天天操欧美 | 国产男女视频 | 亚洲精品一区二区三区中文字幕 | 淫片专区| 国产视频久久久 | 国产精品久久久久免费 | 久久精品亚洲 | 亚洲一区中文字幕 | 日韩一区二区在线视频 | 亚洲高清av | 日日日干干干 | 午夜精品久久久久久久久久久久久 | 一级毛片高清 | 亚洲一区二区视频在线观看 | 国产大片黄色 | 网站国产 | 免费黄色a级毛片 | 99久久精品免费看国产四区 | 国产精品久久久久不卡 | 日韩中文字幕视频 | 久久久美女| 中文字幕在线三区 | 成人国产精品入口免费视频 | 欧美日韩精品一区二区三区视频 | 91大神在线资源观看无广告 | 99re6在线视频精品免费 | 国产亚洲精品久久久久久牛牛 | 91精品国产综合久久婷婷香蕉 |