51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机技术文章 > 51单片机 > 详细内容
STC系列单片机内部AD的应用
发布时间:2009/9/23  阅读次数:2749  字体大小: 【】 【】【
STC89LE52AD、54AD58AD516AD这几款89系列的STC单片机内部自带有88位的AD转换器,分布在P1口的8位上,当时钟在40MHz以下时,每17个机器周期可完成一次AD转换。
                 AD相关的几个寄存器如表1所示。
1 STC89系列单片机AD相关寄存器
名称
地址
功能描述
D7
D6
D5
D4
D3
D2
D1
D0
复位值
P1_ADC_EN
97H
允许P1.X成为AD
AD_P17
AD_P16
AD_P15
AD_P14
AD_P13
AD_P12
AD_P11
AD_P10
0000 0000
ADC_CONTR
C5H
AD转换控制寄存器
--
--
--
ADC_FLAG
ADC_START
CHS2
CHS1
CHS0
xxx0 0000
ADC_DATA
C6H
AD转换结果寄存器
--
--
--
--
--
--
--
--
0000 0000
                 P1_ADC_ENP1.X口的AD使能寄存器。
                                     相应位设置为“1”时,对应的P1. X口作为AD转换使用,内部上拉电阻自动断开。
                 ADC_CONTRAD 转换控制寄存器。
                                     ADC_STARTAD转换启动控制位,设置为“1”时,AD开始转换。
                                  ADC_FLAGAD转换结束标志位,当AD转换完成后,ADC_FLAG=1
                                     CHS2CHS1CHS0:为模拟输入通道选择,如表2所示。
2   STC89系列单片机AD模拟通道选择设置
CHS2
CHS1
CHS0
模拟输入通道选择
0
0
0
选择P1.0作为AD输入来用
0
0
1
选择P1.1作为AD输入来用
0
1
0
选择P1.2作为AD输入来用
0
1
1
选择P1.3作为AD输入来用
1
0
0
选择P1.4作为AD输入来用
1
0
1
选择P1.5作为AD输入来用
1
1
0
选择P1.6作为AD输入来用
1
1
1
选择P1.7作为AD输入来用
       ADC_DATAAD 转换结果寄存器。模拟/数字转换结果计算公式如下:
结果=256×Vin / Vcc
                 Vin为模拟输入通道输入电压,Vcc为单片机实际工作电压,用单片机工作电压作为模拟参考电压。
                 下面一个例程演示STC89LE516AD/X2系列单片机的A/D转换功能。 时钟11.0592MHz 转换结果以16进制形式输出到串行口,可以用串行口调试程序观察输出结果。(本代码摘自宏晶科技芯片手册,经作者调试可正常运行)
                 新建文件part3.4.5.c,程序代码如下:
                                  #include <reg52.H>
#include <intrins.H>
// 定义与 ADC 有关的特殊功能寄存器
sfr P1_ADC_EN = 0x97; //A/D转换功能允许寄存器
sfr ADC_CONTR = 0xC5; //A/D转换控制寄存器
sfr ADC_DATA = 0xC6;   //A/D转换结果寄存器
typedef unsigned char INT8U;
typedef unsigned int INT16U;
void delay(INT8U delay_time) // 延时函数
{
                 INT8U n;
                 INT16U m;
                 for (n=0;n<delay_time;n++)
                                   {
                                                       for(m=0;m<10000;m++);
                                   }
}
void initiate_RS232(void)   //串口初始化
{
                 ES = 0;              // 禁止串口中断
                 SCON = 0x50;     // 0101,0000 8 位数据位, 无奇偶校验
                 T2CON = 0x34;   // 00110100 T2 作为波特率发生器
                 RCAP2H = 0xFF; // 时钟11.0592MHz, 9600 波特率
                 RCAP2L = 0xDB;
                 ES = 1;               // 允许串口中断
}
void Send_Byte(INT8U one_byte) // 发送一个字节
{
                 TI = 0;              // 清零串口发送中断标志
                 SBUF = one_byte;
                 while (TI == 0);
                 TI = 0;              // 清零串口发送中断标志
}
INT8U get_AD_result(INT8U channel)
{
                 INT8U AD_finished = 0; // 存储 A/D 转换标志
                 ADC_DATA = 0;
                 ADC_CONTR = channel; // 选择 A/D 当前通道
                 delay(1);                                          //使输入电压达到稳定
                 ADC_CONTR |= 0x08; //0000,1000 ADC_START = 1, 启动A/D 转换
                 AD_finished = 0;
                 while ( AD_finished == 0 ) // 等待A/D 转换结束
                 {
                                   AD_finished = (ADC_CONTR & 0x10); //0001,0000, ADC_FLAG ==1测试A/D                                   换结束否
                 }
                 ADC_CONTR &= 0xF7; //1111,0111 ADC_START = 0, 关闭A/D 转换,
                 return (ADC_DATA); // 返回 A/D 转换结果
}
void main()
{
                 initiate_RS232();
                 P1 = P1 | 0x63; // 0110,0011,要设置为 A/D 转换的P1.x ,先设为高
                 P1_ADC_EN = 0x63; //0110,0011, P1 P1.0,P1.1,P1.5,P1.6 设置为 A/D 转换输入脚
                 // 断开P1.0,P1.1,P1.5,P1.6 内部上拉电阻
                 while(1)
                 {
                                   Send_Byte(get_AD_result(0)); //P1.0 A/D 当前通道, 测量并发送结果
                                   delay(0x200);
                                   Send_Byte(get_AD_result(1)); //P1.1 A/D 当前通道, 测量并发送结果
                                   delay(0x200);
                                   Send_Byte(get_AD_result(5)); //P1.5 A/D 当前通道, 测量并发送结果
                                   delay(0x200);
                                   Send_Byte(get_AD_result(6)); //P1.6 A/D 当前通道, 测量并发送结果
                                   delay(0x200);
                                   Send_Byte(0); // 连续发送 4 00H, 便于观察输出显示
                                   Send_Byte(0);
                                   Send_Byte(0);
                                   Send_Byte(0);
                                   delay(0x200); // 延时
                                   delay(0x200);
                                   delay(0x200);
                                   delay(0x200);
                                   delay(0x200);
                                   delay(0x200);
                 }
}
       知识点:typedef与#define的区别
                           typedef:类型定义,其功能是用户为已有数据类型取“别名”。
                           如:typedef   int   INT; 意思是将int重新定义为INT,以后使用INT a;就相当于int            a;
             用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单,而且使意义更为明确,因而增强了可读性。例如:typedef int a[10];表示a是整型数组类型,数组长度为10,然后就可用a定义变量,如:a s1,s2;完全等效于:int s1[10],s2[10];
define:宏定义。
             如:#define PI 3.14 意思是以后程序中出现PI的地方将用3.14代替,这个替换是在编译预处理阶段完成的,注意#define最后没有分号,否则编译时将分号一同带入PI中。
我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[4]
  • 评论人:[匿名] 时间: [2012/7/24 1:56:11] IP:[88.127.240.12*]
  • PRoryv , [url=http://fztmsuzrfhqw.com/]fztmsuzrfhqw[/url], [link=http://aaxdomtttfvq.com/]aaxdomtttfvq[/link], http://pggqagxyjovp.com/
  • 评论人:[匿名] 时间: [2012/7/23 19:07:11] IP:[213.202.77.13*]
  • Ds71lj <a href="http://ushbdgrrmpsw.com/">ushbdgrrmpsw</a>
  • 评论人:[匿名] 时间: [2012/7/22 23:04:43] IP:[94.23.1.2*]
  • This piece was cogent, well-wirtetn, and pithy.
  • 评论人:[匿名] 时间: [2012/7/16 21:01:26] IP:[182.151.209.13*]
  • 恩,不错

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号