又菜又爱玩的尾巴 2024-12-26 16:30 采纳率: 66.7%
浏览 7

单片机C语言程序(相关搜索:c语言)

目的:根据光敏电阻电阻值得到光照度的大小
该程序的功能:按下P2.4按键 数码管开始显示光照度 按下P2.6选择P2.5管脚的功能,每按下P2.5引脚对伽马 R E 的增加0.1
但是录入到Proteus中 当改变电阻值时,数码管的数值并不能实时更新,这是为什么?

#include <reg51.h>
#include <intrins.h>

// 按键和控制信号定义
sbit adc_rd = P3^7;        // RD 信号
sbit adc_wr = P3^6;        // WR 信号
sbit key_start = P2^4;     // "开始"按键
sbit add = P2^5;           // 增加按键
sbit key_choose = P2^6;    // "选择"按键

// 数码管控制定义
sbit s1 = P2^0;  // 数码管位选
sbit s2 = P2^1;
sbit s3 = P2^2;
sbit s4 = P2^3;

// 全局变量
unsigned char Disbuf[] = {0, 0, 0};    // 显示缓冲区
unsigned char code tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; // 数码管编码表
float gamma = 0.5, r = 1.0, e = 1.0;   // 参数默认值
unsigned char chooseParam = 0;         // 当前选择的增益参数
unsigned char newParam = 0;            // 新参量
unsigned char adcValue = 0;            // 存储 ADC 转换值
bit measuring = 0;                     // 实时测量标志

// 延时函数
void delay(unsigned int time) {
    unsigned int i, j;
    for (i = 0; i < time; i++) {
        for (j = 0; j < 120; j++);
    }
}

// 数码管显示
void display() {
    P1 = tab[Disbuf[2]]; s4 = 0; delay(5); s4 = 1; // 个位
    P1 = tab[Disbuf[1]]; s3 = 0; delay(5); s3 = 1; // 十位
    P1 = Disbuf[0] ? tab[Disbuf[0]] : 0xff; s2 = 0; delay(5); s2 = 1; // 百位
}

// ADC初始化
void adcInit() {
    adc_wr = 0; _nop_(); adc_wr = 1;
}

// 读取ADC值
unsigned char adcRead() {
    unsigned char d;
    P0 = 0xff; _nop_();
    adc_rd = 0; _nop_(); d = P0; _nop_(); adc_rd = 1;
    return (d);
}

// 更新显示缓冲区
void updateDisplay(unsigned char dat) {
    unsigned int intensity = (int)(dat * gamma * r * e);  // 光照度转换
    Disbuf[0] = intensity / 100;
    Disbuf[1] = (intensity % 100) / 10;
    Disbuf[2] = intensity % 10;
}

// 参数调整逻辑
void adjustParameters() {
    if (key_choose == 0) {  // 切换当前调整的参数
        chooseParam = chooseParam + 1;  // 循环切换 gamma → r → e → gamma
        newParam = chooseParam % 3;    // 计算新参量
        delay(200);  // 防抖
    }
    if (add == 0) {  // 增加当前选择的参数值
        if (newParam == 0) {
            gamma += 0.1;
            if (gamma > 1.0) {  // 如果 gamma 大于等于 1,将其重置为 0.5
                gamma = 0.5;
            }
        }
        if (newParam == 1) r += 0.1;
        if (newParam == 2) e += 0.1;
        delay(200);  // 防抖
    }
}

// 设置测量模式
void setMeasurementMode() {
    if (key_start == 0) {
        measuring = 1; 
        delay(200);  // 开始实时测量
    }
}

// 主函数
void main() {
    adcInit();  // 初始化ADC
    while (1) {
        adjustParameters();  // 调整增益参数
        setMeasurementMode();  // 设置测量模式

        if (measuring) {
            adcValue = adcRead();      // 实时读取 ADC 值
            updateDisplay(adcValue);   // 更新显示缓冲区
        }
        display();  // 更新数码管显示
        delay(20);  // 动态显示延时
    }
}
![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/0049e9576b6e45a3aaa1edf9a7364b12.png "#left")


img

  • 写回答

1条回答 默认 最新

  • 道友老李 JWE233286一种基于机器视觉的水表指针读数识别及修正的方法 专利发明者 2024-12-26 16:47
    关注
    让【道友老李】来帮你解答,本回答参考通义千问大模型编写,并整理提供,如果还有疑问可以点击头像关注私信或评论。
    如果答案让您满意,请采纳、关注,非常感谢!
    ### 问题分析与解决方案

    根据你的描述,程序的功能是通过光敏电阻的电阻值来计算光照度,并在数码管上显示。按下P2.4按键后开始显示光照度,按下P2.6按键可以选择P2.5按键的功能,每按下P2.5按键一次,伽马(gamma)、R或E参数增加0.1。

    然而,当你在Proteus中改变光敏电阻的电阻值时,数码管的数值并不能实时更新。这可能是由于以下几个原因:

    1. ADC读取频率:ADC读取频率可能不够高,导致无法实时检测到电阻值的变化。
    2. 延时函数:延时函数可能导致主循环执行速度较慢,影响实时性。
    3. 按键防抖:按键防抖的延时时间较长,影响了主循环的执行速度。

    解决方案

    1. 提高ADC读取频率:减少延时时间,提高ADC读取频率。
    2. 优化延时函数:使用更高效的延时函数。
    3. 优化按键防抖:减少按键防抖的延时时间。

    代码优化

    以下是优化后的代码示例:

    #include <reg51.h>
    #include <intrins.h>
    
    // 按键和控制信号定义
    sbit adc_rd = P3^7;        // RD 信号
    sbit adc_wr = P3^6;        // WR 信号
    sbit key_start = P2^4;     // "开始"按键
    sbit add = P2^5;           // 增加按键
    sbit key_choose = P2^6;    // "选择"按键
    
    // 数码管控制定义
    sbit s1 = P2^0;  // 数码管位选
    sbit s2 = P2^1;
    sbit s3 = P2^2;
    sbit s4 = P2^3;
    
    // 全局变量
    unsigned char Disbuf[] = {0, 0, 0};    // 显示缓冲区
    unsigned char code tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; // 数码管编码表
    float gamma = 0.5, r = 1.0, e = 1.0;   // 参数默认值
    unsigned char chooseParam = 0;         // 当前选择的增益参数
    unsigned char newParam = 0;            // 新参量
    unsigned char adcValue = 0;            // 存储 ADC 转换值
    bit measuring = 0;                     // 实时测量标志
    
    // 延时函数
    void delay(unsigned int time) {
        unsigned int i, j;
        for (i = 0; i < time; i++) {
            for (j = 0; j < 120; j++);
        }
    }
    
    // 数码管显示
    void display() {
        P1 = tab[Disbuf[2]]; s4 = 0; delay(5); s4 = 1; // 个位
        P1 = tab[Disbuf[1]]; s3 = 0; delay(5); s3 = 1; // 十位
        P1 = Disbuf[0] ? tab[Disbuf[0]] : 0xff; s2 = 0; delay(5); s2 = 1; // 百位
    }
    
    // ADC初始化
    void adcInit() {
        adc_wr = 0; _nop_(); adc_wr = 1;
    }
    
    // 读取ADC值
    unsigned char adcRead() {
        unsigned char d;
        P0 = 0xff; _nop_();
        adc_rd = 0; _nop_(); d = P0; _nop_(); adc_rd = 1;
        return (d);
    }
    
    // 更新显示缓冲区
    void updateDisplay(unsigned char dat) {
        unsigned int intensity = (int)(dat * gamma * r * e);  // 光照度转换
        Disbuf[0] = intensity / 100;
        Disbuf[1] = (intensity % 100) / 10;
        Disbuf[2] = intensity % 10;
    }
    
    // 参数调整逻辑
    void adjustParameters() {
        if (key_choose == 0) {  // 切换当前调整的参数
            chooseParam = (chooseParam + 1) % 3;  // 循环切换 gamma → r → e
            newParam = chooseParam;
            delay(200);  // 防抖
        }
        if (add == 0) {  // 增加当前选择的参数值
            if (newParam == 0) {
                gamma += 0.1;
                if (gamma > 1.0) {
                    gamma = 0.5;
                }
            }
            if (newParam == 1) r += 0.1;
            if (newParam == 2) e += 0.1;
            delay(200);  // 防抖
        }
    }
    
    // 设置测量模式
    void setMeasurementMode() {
        if (key_start == 0) {
            measuring = 1;
            delay(200);  // 开始实时测量
        }
    }
    
    // 主函数
    void main() {
        adcInit();  // 初始化ADC
        while (1) {
            adjustParameters();  // 调整增益参数
            setMeasurementMode();  // 设置测量模式
            if (measuring) {
                adcValue = adcRead();      // 实时读取 ADC 值
                updateDisplay(adcValue);   // 更新显示缓冲区
            }
            display();  // 更新数码管显示
            delay(10);  // 动态显示延时
        }
    }
    

    优化点说明

    1. 减少延时时间:将delay(20)改为delay(10),提高主循环的执行频率。
    2. 优化按键防抖:保持按键防抖的延时时间为200ms,确保按键响应的稳定性。
    3. 循环切换参数:使用(chooseParam + 1) % 3来实现参数的循环切换。

    通过这些优化,可以提高程序的实时性和响应速度,确保数码管能够实时显示光照度的变化。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月26日