单片机练习 - AD转换

继续像昨天一样, 今天也用TX-B开发板参照模数转换ADC0804的应用中的实验要求和源代码, 自己也改进了一些代码.

ADC0804与单片机的连接电路图:
单片机练习 - AD转换_第1张图片

6位数码管与单片机的连接电路图
单片机练习 - AD转换_第2张图片

数码管动态扫描显示的原理:就六位数码管显示123456举例说明如下:先让第一个数码管显示1,其余的全部不亮,1大约亮几毫秒,然后熄灭,紧接着立即让第二个数码管显示2,其余的全部不亮,2同样亮几毫秒,依次这样亮到第六个数码管,然后再回来显示1,如此这样以很快的速度不断循环下去,由于人眼的视觉暂留时间大约为20毫秒左右,所以是感觉不出有不亮的数码管存在的,看见的是六个数码管同时在显示,数值是123456,如果我们把这个过程一点点放慢,看见的是从第一个数码管显1,然后移到第二个再显2,。。。也就是说在任一时刻只有一位数码管是亮的。

ADC0804: ADC0804是8位全MOS中速A/D 转换器、它是逐次逼近式A/D 转换器,片内有三态数据输出锁存器,可以和单片机直接接口。单通道输入,转换时间大约为100us。ADC0804 转换时序是:当CS=0 许可进行A/D 转换。WR由低到高时,A/D开始转换,一次转换一共需要66-73 个时钟周期。CS与WR同时有效时启动A/D转换,转换结束产生INTR 信号(低电平有效),可供查询或者中断信号。在CS和RD 的控制下可以读取数据结果。本实验没有使用INTR信号。

源代码:

ContractedBlock.gif ExpandedBlockStart.gif ADC0804
  1None.gif#include <reg51.H>
  2None.gif//读取通过ADC0804将模拟量转换成数字量, 并显示相应的数值
  3None.gif#include <intrins.H>  //要使用到_nop_();函数, 延时一个空操作时间
  4None.gif
  5None.gif#define uchar unsigned char
  6None.gif
  7None.gifunsigned char j, k;
  8None.gif//延时函数, 例i=10,则大概延时10ms.
  9None.gifvoid delay(unsigned char i)
 10ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 11InBlock.gif    for(j = i; j > 0; j--)
 12ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 13InBlock.gif        for(k = 125; k > 0; k--);
 14ExpandedSubBlockEnd.gif    }

 15ExpandedBlockEnd.gif}

 16None.gif
 17ExpandedBlockStart.gifContractedBlock.gifunsigned char code table[]=dot.gif{0x3f,0x06,0x5b,0x4f,0x66,
 18ExpandedBlockEnd.gif    0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}
;//0-F数码管的编码(共阴极)
 19None.gif
 20None.gif//控制数码管段选的锁存器锁存端   下降沿过后锁存,即先令dula = 1,再令dula=0,完成锁存
 21None.gifsbit dula=P2^6;  
 22None.gif//控制数码管位选的锁存器锁存端   过程如dula
 23None.gifsbit wela=P2^7;
 24None.gifsbit adrd = P3^7;  //一个上升沿脉冲, 打开读取ADC
 25None.gifsbit adwr = P3^6;  //一个上升沿脉冲, 启动ADC
 26ExpandedBlockStart.gifContractedBlock.gifuchar ds[] = dot.gif{000}//存放转换结果
 27None.gifsbit adcs = P0^7;  //ADC的片选, 低电平有效
 28None.gif
 29None.gif//datas[0]百位数字,datas[1]十位, datas[2]个位
 30None.gifvoid display(uchar datas[]) 
 31ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 32InBlock.gif    uchar count;
 33InBlock.gif    for(count = 0; count < 3; count++)
 34ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 35InBlock.gif        //片选
 36InBlock.gif        wela = 0
 37InBlock.gif        P0 = ((0xfe << count) | (0xfe >> (8 - count))) & 0x7f//选择第(count + 1) 个数码管
 38InBlock.gif        wela = 1//打开锁存, 给它一个下降沿量
 39InBlock.gif        wela = 0;
 40InBlock.gif        //段选
 41InBlock.gif        dula = 0;
 42InBlock.gif        P0 = table[datas[count]];  //显示数字
 43InBlock.gif        dula = 1;  //打开锁存, 给它一个下降沿量
 44InBlock.gif        dula = 0;
 45InBlock.gif        delay(5); //延时5ms, 即亮5ms
 46InBlock.gif
 47InBlock.gif        //清除段先, 让数码管灭, 去除对下一位的影响, 去掉高位对低位重影
 48InBlock.gif        //若想知道影响效果如何, 可自行去掉此段代码
 49InBlock.gif        //因为数码管是共阴极的, 所有灭的代码为: 00H
 50InBlock.gif        dula = 0;
 51InBlock.gif        P0 = 0x00;  //显示数字
 52InBlock.gif        dula = 1//打开锁存, 给它一个下降沿量
 53InBlock.gif        dula = 0;
 54ExpandedSubBlockEnd.gif    }

 55ExpandedBlockEnd.gif}

 56None.gif
 57None.gif//启动ADC
 58None.gifvoid ADStart()
 59ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 60InBlock.gif    adcs = 0;  //选中ADC
 61InBlock.gif    _nop_();
 62InBlock.gif    adwr = 0;
 63InBlock.gif    _nop_();
 64InBlock.gif    adwr = 1;  //一个上升沿脉冲
 65InBlock.gif    _nop_();
 66InBlock.gif    adcs = 1;
 67ExpandedBlockEnd.gif}

 68None.gif
 69None.gif//读ADC
 70None.gifuchar ADRead()
 71ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 72InBlock.gif    uchar tmp;
 73InBlock.gif    adcs = 0//选中ADC
 74InBlock.gif    _nop_();
 75InBlock.gif    adrd = 0//准备读取
 76InBlock.gif    _nop_();
 77InBlock.gif    _nop_();  
 78InBlock.gif    tmp = P1;  //读取ADC数据
 79InBlock.gif    adrd = 1;
 80InBlock.gif    _nop_();
 81InBlock.gif    adcs = 1;
 82InBlock.gif    return tmp;
 83ExpandedBlockEnd.gif}

 84None.gif
 85None.gifvoid main()
 86ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 87InBlock.gif    uchar advalue, icount;
 88InBlock.gif    
 89InBlock.gif    while(1)
 90ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 91InBlock.gif        //启动AD转换
 92InBlock.gif        ADStart();
 93InBlock.gif        //读AD
 94InBlock.gif        advalue = ADRead();
 95InBlock.gif        
 96InBlock.gif        ds[0= advalue / 100;             //百位
 97InBlock.gif        ds[1= (advalue % 100/ 10;      //十位
 98InBlock.gif        ds[2= advalue % 10;            //个位
 99InBlock.gif         //循环显示五十次, 再去采样电压, 留足够的时间让ADC0804完成模数转换
100InBlock.gif        for(icount = 0; icount < 50; icount++)
101ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
102InBlock.gif            display(ds);
103ExpandedSubBlockEnd.gif        }

104ExpandedSubBlockEnd.gif    }

105ExpandedBlockEnd.gif}


特别对于数码管显示函数display()

 1 None.gif // datas[0]百位数字,datas[1]十位, datas[2]个位
 2 None.gif void  display(uchar datas[]) 
 3 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 4InBlock.gif    uchar count;
 5InBlock.gif    for(count = 0; count < 3; count++)
 6ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 7InBlock.gif        //片选
 8InBlock.gif        wela = 0
 9InBlock.gif        P0 = ((0xfe << count) | (0xfe >> (8 - count))) & 0x7f//选择第(count + 1) 个数码管
10InBlock.gif        wela = 1//打开锁存, 给它一个下降沿量
11InBlock.gif        wela = 0;
12InBlock.gif        //段选
13InBlock.gif        dula = 0;
14InBlock.gif        P0 = table[datas[count]];  //显示数字
15InBlock.gif        dula = 1;  //打开锁存, 给它一个下降沿量
16InBlock.gif        dula = 0;
17InBlock.gif        delay(5); //延时5ms, 即亮5ms
18InBlock.gif
19InBlock.gif        //清除段先, 让数码管灭, 去除对下一位的影响, 去掉高位对低位重影
20InBlock.gif        //若想知道影响效果如何, 可自行去掉此段代码
21InBlock.gif        //因为数码管是共阴极的, 所有灭的代码为: 00H
22InBlock.gif        dula = 0;
23InBlock.gif        P0 = 0x00;  //显示数字
24InBlock.gif        dula = 1//打开锁存, 给它一个下降沿量
25InBlock.gif        dula = 0;
26ExpandedSubBlockEnd.gif    }

27ExpandedBlockEnd.gif}

若去掉将数码灭掉的那4行代码, 显示效果将如下:
单片机练习 - AD转换_第3张图片

而最理想的效果应如下:
单片机练习 - AD转换_第4张图片

这是因为74HC573的锁存, 上一位的结果被锁存了, 在片选后, 也被显示在选中的位上.
只要在片选前将锁存的结果清除, 即可消除这个影响.

你可能感兴趣的:(嵌入式)