找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 446|回复: 4
收起左侧

关于adc0809的转换问题

[复制链接]
ID:1148254 发表于 2025-4-16 20:54 | 显示全部楼层 |阅读模式
现在有个很大的问题,打板焊接后我没有模拟量输入adc0809也会有数字量输出,大概在90左右,换算下在in0有个1.75v左右的电压,不确定是什么原因,然后插上GP2Y1014AU后adc输出的数字量直接变成0,偶尔会在跳变一下。现在不知道怎么办了,想换个adc芯片。下面是程序,附件是原理图和pcb文件。顺便问下我的报警电路这样设计可以换成无源蜂鸣器吗?第一次发这个,如果有违规的地方请和我说。
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

// LCD1602引脚
sbit lcdrs = P3^4;  // RS接P3.4
sbit lcdrw = P3^3;  // RW接P3.3
sbit lcden = P3^2;  // EN接P3.2
#define LCD_Data P1  // 数据口接P1

// ADC0809引脚
sbit clock = P2^0;  // 时钟输入
sbit state = P2^2;  // 启动转换
sbit eoc   = P2^3;  // 转换结束
sbit oe    = P2^7;  // 输出使能
#define adcdata P0   // 数据口接P0

// GP2Y1014AU引脚(粉尘传感器)
sbit led = P3^7;     // LED控制

// 延时函数(11.0592MHz晶振)
void delay_us(uchar us) {
    while(--us);
}

void delay_ms(uint ms) {
    uint i, j;
    for(i = ms; i > 0; i--)
        for(j = 100; j > 0; j--); // 适配11.0592MHz,约1ms
}

// LCD写命令
void write_com(uchar com) {
    lcdrs = 0; lcdrw = 0;
    LCD_Data = com;
    lcden = 1; delay_us(10); lcden = 0;
    delay_ms(2);
}

// LCD写数据
void write_dat(uchar dat) {
    lcdrs = 1; lcdrw = 0;
    LCD_Data = dat;
    lcden = 1; delay_us(10); lcden = 0;
    delay_ms(1);
}

// LCD初始化
void init_lcd() {
    delay_ms(50); // 上电延时
    write_com(0x38); // 8位数据,2行
    delay_ms(5);
    write_com(0x0C); // 显示开,无光标
    delay_ms(5);
    write_com(0x06); // 光标右移
    delay_ms(5);
    write_com(0x01); // 清屏
    delay_ms(5);
}

// LCD显示字符串
void LCD_ShowString(uchar x, uchar y, uchar *str) {
    uchar addr = (y == 0) ? (0x80 + x) : (0xC0 + x);
    write_com(addr);
    while(*str) write_dat(*str++);
}
uchar LCD_ShowNum(uchar x, uchar y, uint num) {
    uchar addr = (y == 0) ? (0x80 + x) : (0xC0 + x);
    uchar digits[5]; // 最多 5 位(uint 最大 65535)
    uchar i, len = 0;

    // 将数字转换为字符数组,从低位到高位
    do {
        digits[len++] = (num % 10) + '0';
        num /= 10;
    } while (num > 0 && len < 5);

    // 设置显示位置
    write_com(addr);
    // 从高位到低位显示(反向输出),跳过前导 0
    for (i = len; i > 0; i--) {
        write_dat(digits[i - 1]);
    }
    return len;
}

// 初始化定时器0(500kHz时钟)
void init_timer0() {
    TMOD |= 0x02;   // 定时器0,模式2
    TH0 = 0x22;     // 500kHz @11.0592MHz
    TL0 = 0x22;
    ET0 = 1;        // 允许定时器0中断
    EA = 1;         // 开启总中断
    TR0 = 1;        // 启动定时器0
}

// 定时器0中断服务函数(生成时钟)
void timer0_isr() interrupt 1 {
    clock = ~clock;
}
uchar reverse_bits(uchar value) {
    uchar result = 0;
    uchar i;
    for (i = 0; i < 8; i++) {
        result <<= 1;          // 左移一位
        result |= (value & 1);  // 取最低位
        value >>= 1;            // 右移一位
    }
    return result;
}
// ADC读取函数
uchar ADC_Read() {
    uchar adc_value;

    // 1. 启动转换(START下降沿)
    state = 1;
    _nop_(); _nop_();
    state = 0;

    // 2. 等待转换开始(EOC变低)
    //while(eoc == 1);
    // 3. 等待转换完成(EOC变高)
    while(eoc == 0);

    // 4. 读取数据
    oe = 1;
    //adcdata = 0xFF;     // P0设置为输入
    _nop_(); _nop_();
    adc_value =reverse_bits( adcdata);
回复

使用道具 举报

ID:1148254 发表于 2025-4-16 20:56 | 显示全部楼层
                return adc_value;
}
//PM2.5
uint PM_Value()
{
        uint adc_value=0;        //adc值变量
        uint PM_value =0;        //PM2.5值变量
        led=0;
        delay_us(280);
        adc_value=ADC_Read();//获取一次adc值,并累加
        if(adc_value==0)
                return 0;
        delay_us(19);
        led=1;
        PM_value=((adc_value/255.0)*5*0.17-0.1)*1000;//计算PM2.5值
        delay_us(9680);
        return PM_value;
}
// 主函数
void main() {
                uchar i;
    init_timer0();  // 启动ADC时钟
    init_lcd();     // 初始化LCD
    state = 0;      // START初始低
    oe = 0;         // OE初始关闭
   
    LCD_ShowString(0, 0, "ADC Value:");
    LCD_ShowString(0, 1, "PM2.5:   ");
   
    while(1) {
        uchar val = ADC_Read();
                                uchar pm  = PM_Value();
        LCD_ShowNum(10, 0, val);  // 显示ADC值
        i=LCD_ShowNum(6, 1, pm);   // 显示PM2.5模拟值
                                LCD_ShowString(6+i, 1, "ug/m3   ");
        delay_ms(200);            // 控制采样率
    }
}
这个是剩下的程序
回复

使用道具 举报

ID:469589 发表于 2025-4-17 09:01 | 显示全部楼层
adc0809输入不能开路,否则可能有数字。
所以有任何电路接入则这个“干扰”会减小。
回复

使用道具 举报

ID:940483 发表于 2025-4-17 15:29 | 显示全部楼层
注释掉reverse_bits:
让ADC_Read直接返回adcdata,观察下数值
  1. uchar ADC_Read() {
  2.     state = 1; _nop_(); state = 0;
  3.     while(eoc == 0);
  4.     oe = 1;
  5.     _nop_();
  6.     uchar adc_value = adcdata; // 移除
  7.     oe = 0;
  8.     return adc_value;
  9. }
复制代码
如果输入都没有的话,ADC输出0,就是reverse_bits导致的啦,那就是很大可能连线问题了
还有你电路图传在哪里?
回复

使用道具 举报

ID:1148254 发表于 2025-4-18 15:16 | 显示全部楼层
Tonghao666 发表于 2025-4-17 15:29
注释掉reverse_bits:
让ADC_Read直接返回adcdata,观察下数值
如果输入都没有的话,ADC输出0,就是rever ...

附件里面
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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