AD0808调试笔记

1.adc0808在采样期间 A2 A1 A0 是否保持不变

在ADC0808的采样期间,地址线A2、A1、A0是必须保持不变的。这是一个关键点,理解它需要先弄清ADC0808的工作原理。

ADC0808在采样和转换期间,只负责将已经选中的某一路模拟信号转换为数字值,不具备自动切换通道的功能。所以在转换期间改变地址线状态,很可能导致结果出错。

核心原因:地址锁存机制

ADC0808的设计,决定了地址线只在特定时刻被读取,之后不再响应其变化:

  • 地址锁存信号 (ALE) :有一个专门的ALE(地址锁存允许)引脚,地址线(ADD A, B, C)的状态就是在**ALE引脚上升沿**这一瞬间,被锁存(记住)的。

  • 锁存后不再响应:一旦地址被锁存,内部的多路复用开关就固定连接到了对应的模拟输入通道。此后,无论地址线怎么变化,都不会影响正在进行的转换过程。这种设计也叫"写时选通"

2.一次完整的工作流程

你可以参考这个标准流程来编写代码,确保采样正确:

  1. 设置地址 :代码先把想采样的通道地址(A2, A1, A0)送到地址线上。

  2. 锁存地址(ALE高电平) :紧接着给ALE引脚一个正脉冲(高电平)。在脉冲的上升沿,地址被锁存到芯片内部,选定输入通道。

  3. 启动转换(启动正脉冲) :紧接着给START引脚一个至少100ns宽的正脉冲。其下降沿启动A/D转换。

  4. 等待转换完成 :转换期间,EOC(转换结束)引脚为低电平

  5. 读取结果 :等待EOC变高后,给OE(输出允许)引脚一个高电平,此时就能从D0-D7引脚读到转换好的数字量了。

  6. 切换下一通道:重复以上步骤,进行下一路采样。

示例代码:

cpp 复制代码
/*----------------------------------------------------------
 程序名称:ADC0808 电压采集与数码管显示(C语言版)
 硬件平台:8088 单板机 + ADC0808 + 8255
 功能描述:采集 IN0 通道电压,转换为数字量后计算电压值,
           通过 4 位数码管动态显示(单位:0.01V)
----------------------------------------------------------*/

#include <dos.h>
#include <conio.h>

/* 端口地址定义(根据实际硬件连接修改) */
#define ADC_BASE    0x80    /* ADC0808 片选端口(WR启动,RD读取) */
#define ADC_EOC     0x82    /* EOC 状态查询端口(bit0=1 表示转换完成) */
#define DISP_SEG    0x88    /* 数码管段码输出端口(8255 PA口) */
#define DISP_BIT    0x8A    /* 数码管位选输出端口(8255 PB口) */
#define CTRL_8255   0x8C    /* 8255 控制端口 */

/* 共阴数码管段码表(0-9) */
unsigned char code SegCode[10] = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66,
    0x6D, 0x7D, 0x07, 0x7F, 0x6F
};

unsigned char AdcValue;     /* ADC 原始值 0~255 */
unsigned int  Voltage;       /* 电压值(单位:0.01V),例如 500 = 5.00V */

/* 函数声明 */
void Init8255(void);
unsigned char ReadADC(unsigned char channel);
void DisplayVoltage(unsigned int voltage);
void Delay(unsigned int count);
void DelayShort(void);

/*----------------------------------------------------------
 主函数
----------------------------------------------------------*/
void main(void)
{
    Init8255();                     /* 初始化 8255 */
    
    while (!kbhit())                /* 按任意键退出循环 */
    {
        AdcValue = ReadADC(0);      /* 读取通道 IN0 */
        
        /* 电压换算公式:
           Voltage(0.01V) = (AdcValue * 500) / 256
           500 = 5.00V × 100 (转换为 0.01V 单位)
        */
        Voltage = (unsigned int)((unsigned long)AdcValue * 500 / 256);
        
        DisplayVoltage(Voltage);    /* 数码管显示电压值 */
        
        Delay(0xFFFF);              /* 采样间隔控制 */
    }
}

/*----------------------------------------------------------
 8255 初始化:方式0,PA/PB 输出,PC 输入
----------------------------------------------------------*/
void Init8255(void)
{
    outp(CTRL_8255, 0x82);    /* 10000010B */
}

/*----------------------------------------------------------
 读取指定 ADC 通道的转换结果(查询方式)
 参数:channel = 0~7(选择 IN0~IN7)
 返回:8 位 ADC 值(0~255)
----------------------------------------------------------*/
unsigned char ReadADC(unsigned char channel)
{
    unsigned char result;
    
    /* 1. 启动 ADC0808 转换 */
    /* 注意:通道选择需通过 A、B、C 地址线实现,
       这里简化处理,假设通道由硬件连线固定为 IN0 */
    outp(ADC_BASE, 0x00);           /* 写任意数据产生 START 脉冲 */
    
    /* 2. 等待 EOC 变高(转换完成) */
    while ((inp(ADC_EOC) & 0x01) == 0)
        ;                           /* 循环查询 */
    
    /* 3. 读取转换结果 */
    result = inp(ADC_BASE);
    
    return result;
}

/*----------------------------------------------------------
 数码管动态显示电压值(4 位显示,范围 0.00V ~ 5.00V)
 输入:voltage(单位 0.01V,例如 500 表示 5.00V)
----------------------------------------------------------*/
void DisplayVoltage(unsigned int voltage)
{
    unsigned char digit[4];         /* 存储 4 位显示数字 */
    unsigned char i;
    unsigned int temp;
    
    /* 拆分 voltage 为 4 位数字
       例如 voltage = 500
       digit[0] = 5   (整数部分)
       digit[1] = 0   (小数第一位)
       digit[2] = 0   (小数第二位)
       digit[3] = 0   (未使用,显示 0 或不显示)
    */
    digit[0] = voltage / 100;       /* 百位(整数部分 0~5) */
    temp = voltage % 100;
    digit[1] = temp / 10;           /* 十位(小数第一位) */
    digit[2] = temp % 10;           /* 个位(小数第二位) */
    digit[3] = 0;                   /* 第四位可显示单位 'U' 或熄灭 */
    
    /* 动态扫描显示(每位显示约 2ms) */
    for (i = 0; i < 4; i++)
    {
        /* 输出段码 */
        outp(DISP_SEG, SegCode[digit[i]]);
        
        /* 输出位选(假设共阴数码管,高电平选通) */
        outp(DISP_BIT, (unsigned char)(1 << i));
        
        DelayShort();               /* 短暂延时保持显示 */
        
        /* 消隐(可选,防止重影) */
        outp(DISP_SEG, 0x00);
    }
}

/*----------------------------------------------------------
 长延时函数(用于控制采样频率)
----------------------------------------------------------*/
void Delay(unsigned int count)
{
    unsigned int i;
    for (i = 0; i < count; i++)
        ;                           /* 空循环延时 */
}

/*----------------------------------------------------------
 短延时函数(用于数码管扫描)
----------------------------------------------------------*/
void DelayShort(void)
{
    unsigned int i;
    for (i = 0; i < 100; i++)
        ;
}

3.特殊情况:无内置采样保持的局限

ADC0808芯片内部没有集成采样保持电路 ,如果输入信号变化很快,会导致转换结果不准确。应用中通常需要外接采样保持电路 ,或确保输入信号在整个转换期间(约100μs)都保持稳定

4.信号输入端不能悬空,否则乱码

相关推荐
iCxhust1 小时前
C#进程管理程序
开发语言·汇编·stm32·单片机·c#·微机原理
hhcgchpspk2 小时前
汇编语言传递数据和地址的误区
汇编·笔记·nasm·masm
智者知已应修善业2 小时前
【51单片机2个外部中断显示中断历时,初始化8左移3位共阳数码管】2024-6-6
c++·经验分享·笔记·算法·51单片机
zhaoshuzhaoshu3 小时前
嵌入式开发之IIC接口详解-STM32
嵌入式硬件·软件工程
SUNNYSPY0014 小时前
AO3402-ASEMI开关电源专用AO3402
单片机
iCxhust4 小时前
MTK8088单板机制作(一)时钟电路
汇编·单片机·嵌入式硬件·微机原理·8088单板机
2601_958352904 小时前
双麦 DSP 音频拾音模块 A-68:多场景远场语音交互的声学解决方案
嵌入式硬件·音视频·降噪·回音消除·音频处理模块
tq10864 小时前
OperationSequence DSL 2.1 语法规范
笔记
崇山峻岭之间4 小时前
单片机直流有刷电机速度环PID控制实验
单片机·嵌入式硬件
xiangw@GZ5 小时前
智能锁浮空系统指纹头金属环ESD防护技术分析
单片机·嵌入式硬件