`

51单片机学习笔记:利用ADC0804模数转换器采集电压

阅读更多

电位器调节待检测电压值,在数码管上显示出来,

代码大多从书上搬过来的,书上例5.3.1要求前3个数码管显示AD转换后的8位数字量(即0~255)

我这里让前4个数码管显示具体电压值,比如1.352

 

#include <reg52.h>
#include "MY51.H"

void initSMG()		//数码管初始化信息
{
	//上电时,都为高电平
	P0=0xff;
	wela=open;
	P0=0xff;
	wela=lock;

	P0=0;
	dula=open;
	P0=0;
	dula=lock;
}

void ADC0804_csToLow()  //cs置低电平
{
	wela=open;	//打开锁存器
	P0=0x7f;		//锁存器最高位送0,也就是CSAD置0
	wela=lock;
}

void ADC0804_startConvert() //P3.6口是wr,由高到底,再拉高后,ad开始转换
{
	adwr=high;	//虽然原本就是高的,但我们要养成好习惯,该是什么就是什么
	_nop_();
	adwr=low; 	//wr置低后,过小会后AD内部开始执行转换,转换完成后INTR自动置低触发中断
	_nop_();
	adwr=high;
	//由于我们用的不是150pF电容,而是104pF,所以转换比较慢,在调用本函数后最好延时10毫秒以上
}

uint8 ADC0804_readResult()  //读转换结果
{
	uint8 result=0;
	//延时一会儿,转换就完成了,由于我们将INTR和CS都拉低了,直接操作RD后就可以读了
	P1=0xff;	//防止由于转换未完成原因引起的误读
	adrd=high;
	_nop_();
	adrd=low; //rd置低电平后数据总线P1口得到数据,并由led显示现象
	_nop_();
	result=P1;
	adrd=high;
	//读完以后,如果ad芯片不用了,就把cs拉高,注销片选
	return result;
} 

void show(uint8 value)   //基准电压是2.5V 为了计算方便扩大到2500
{
	uint16 temp=value*(2500/255.0); //扩大到4位整数,小数点另外附加显示
	uint8 oneWela,twoWela,threeWela,fourWela; //oneWela是最左边的数码管
	oneWela=temp/1000;
	twoWela=temp%1000/100;
	threeWela=temp%100/10;
	fourWela=temp%10;
	displaySMG(oneWela,twoWela,threeWela,fourWela,dark,dark,dotTable[1]); //最左边的数码管显示小数点
}

void main()
{
 
	uchar i=0;
	uchar adTemp=0;
 	initSMG();			//数码管数据初始化
	ADC0804_csToLow();	 //cs置低
	while(1)
	{
		ADC0804_startConvert();	//开始将电压数据转换成数字信号	
		for(i=5;i>0;i--)   //主要是延时一段时间,让ad完成转换
		{
			delayms(1);
			show(adTemp);   //延时的时候,数码管继续动态显示 
		}
		adTemp=ADC0804_readResult(); //读取数据
		show(adTemp);
	}
}

 

 

#ifndef _MY51_H_
#define _MY51_H_
#include <math.h>
#include <intrins.h>

typedef int   				int16  ;
typedef int   				INT16  ;
typedef unsigned int    uint16 ;
typedef unsigned int    UINT16 ;
typedef unsigned short  uint ;
typedef unsigned short  UINT ;
typedef unsigned short  word ;
typedef unsigned short  WORD ;
typedef unsigned long   uint32 ;
typedef unsigned long   UINT32 ;
typedef unsigned long   DWORD ;
typedef unsigned long   dword ;
typedef signed long	   int32	 ;
typedef signed long	   INT32  ;
typedef float		    	    float32	 ;
typedef double		    	double64  ;
typedef signed char		int8 ;
typedef signed char 		INT8 ;
typedef unsigned char	byte ;
typedef unsigned char    BYTE 	 ;		//WINDOWS的windef.h里面是这么定义的
typedef unsigned char	uchar ;
typedef unsigned char	UCHAR ;
typedef unsigned char	UINT8 ;
typedef unsigned char	uint8 ;
typedef unsigned char	BOOL	 ;		//windows中定义BOOL为int
typedef unsigned char	bool	 ;		    //bool是c++的内置类型

#define TRUE     1
#define true     1
#define FALSE    0
#define false    0

#define open     1    //open和close用于 标志打开和关闭状态
#define OPEN     1
#define close    0
#define CLOSE    0
#define lock     0
#define start    1
#define START    1
#define stop     0
#define STOP     0
#define keyDown  0
#define keyUp    1
#define gnd       0  //接地
#define GND       0  //接地
#define high	1  //高电平
#define low		0   //低电平
#define yes		1
#define YES     1
#define no		0
#define NO      0

sbit dula =P2^6;  //段选锁存器控制  控制笔段
sbit wela =P2^7;  //位选锁存器控制  控制位置

#define led P1    //灯总线控制
sbit led0=P1^0;   //8个led灯,阴极送低电平点亮
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;

sbit keyS2=P3^4; 	//4个独立按键
sbit keyS3=P3^5;
sbit keyS4=P3^6;
sbit keyS5=P3^7;

sbit csda=P3^2;  //DAC0832模数转换cs口
sbit adwr=P3^6; //ADC0804这个同DAC0832
sbit dawr=P3^6;
sbit adrd=P3^7;  //ADC0804
sbit beep=P2^3;  //蜂鸣器
void displaySMG(uint8 one,uint8 two,uint8 three,uint8 four,uint8 five,uint8 six,uint8 dot); 
void delayms(uint16 ms);
void T0_Work();

void delayms(uint16 ms)  //软延时函数
{
	uint16 i,j;
	for(i=ms;i>0;i--)
	{
        for(j=113;j>0;j--)
        {}
	}
}
///////////////////////////////////////////////////////////////////////////
#define dark	0x11  //在段中,0x11是第17号元素,为0是低电平,数码管不亮
#define dotDark 0xff //小数点全暗时
uint8 code table[]= { 			//0~F外加小数点和空输出的数码管编码
	0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
	0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
	0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
	0x39 , 0x5e , 0x79 , 0x71 , // C D E F
	0x80 , 0x00 ,0x40           // . 空  负号    空时是第0x11号也就是第17号元素
 };

uint8 dotTable[]={		   //小数点位置
    0xff ,                 //全暗
	0xfe , 0xfd , 0xfb ,   //1 2 3
	0xf7 , 0xef , 0xdf     //4 5 6                    
};
/////////////////////////////////////////////////////////////////////////////
uint8   TH0Cout=0 ;	    //初值	
uint8   TL0Cout=0 ;	   
uint16  T0IntCout=0;     //中断计数
uint16  T0IntCountAll=0; //(N-1)/65536+1;  //总中断次数
bool    bT0Delay=false;  //使用延时函数标志,初始未用
bool    bT0Over=false; 	 //中断处理函数执行结果之一

void startT0(uint32 ms)  //开启定时器
{	
	float32   	t=ms/1000.0;		   		 //定时时间
	double64    fox =11.0592*(pow(10,6));   //晶振频率
	uint32    	N=(t*fox)/12 ; 				 //定时器总计数值

	TH0Cout =(65536-N%65536)/256;      	 //装入计时值零头计数初值
	TL0Cout =(65536-N%65536)%256;
	T0IntCountAll=(N-1)/65536+1;			 //总中断次数
	TMOD=TMOD | 0x01; 						 //设置定时器0的工作方式为1
	
	EA =open;   //打开总中断
	ET0=open;   //打开定时器中断

	TH0=TH0Cout;  //定时器装入初值
	TL0=TL0Cout;
	TR0=start;	 //启动定时器
}

void delayT0(uint32 ms)		//硬延时函数,自己乱写的不好用,求指点
{
	startT0(ms);				//启动定时器
	bT0Delay=true;    		//告诉T0定时器,起用延时模式
	while(bT0Over==false);	//时间没到的话继续检测
	bT0Over=false;				//时间到了,让标志复位
}

void T0_times() interrupt 1 //T0定时器中断函数
{
	T0IntCout++;
	if(T0IntCout==T0IntCountAll)  //达到总中断次数值
	{	
		T0IntCout=0; 		 //中断次数清零,重新计时
		bT0Over=true;     //时间真的到了
		if(bT0Delay)		//本次中断是用来延时的吗
		{
			TR0=stop; 		 //如果是由延时函数开启T0的话,关闭T0
			return;
		}

		TH0=TH0Cout;   		//循环定时的话要重装初值,每次定时1秒,重装一次
		TL0=TL0Cout;
		T0_Work();     		//工作函数
	}
}

////////////////////////////////////////////////////////////////////////////////
void displaySMG(uint8 oneWela,uint8 twoWela,uint8 threeWela,uint8 fourWela,uint8 fiveWela,uint8 sixWela,uint8 dot)
{	
    //控制6位数码管显示函数,不显示的位用参数dark,保留ADC0804的片选信号
    uint8 csadState=0x80&P0;  				//提取最高位,即ADC0804的片选信号
    uint8 tempP0=((csadState==0)?0x7f:0xff); //数码管位选初始信号,阴极全置高电平
    P0=tempP0;		//0x7f表示数码管不亮,同时ADC0804片选有效
    wela=1;			//注:wela和dula上电默认为1
    P0=tempP0;
    wela=0;

    P0=0;			    //由于数码管是共阴极的,阳极送低电平,灯不亮,防止灯误亮
    dula=1;
    P0=0;
    dula=0;	 		    //段选数据清空并锁定
//////////////////////////oneWela
    {  //消除叠影,数码管阴极置高电平,并锁存
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;       	//低电平送到数码管阳极,避免数码管误亮
    dula=1;
    P0=table[oneWela]|((0x01&dot)?0x00:0x80);   //送段数据,叠加小数点的显示
    dula=0;
    

    P0=tempP0;          //送位数据前关闭所有显示,并保持csad信号
    wela=1;
    P0=tempP0 & 0xfe;   //0111 1110最高位是AD片选,低6位是数码管位选,低电平有效
    wela=0;
    delayms(2);

/////////////////////////twoWela
    {  //消除叠影
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;
    dula=1;
    P0=table[twoWela]|((0x02&dot)?0x00:0x80);
    dula=0;
    
    P0=tempP0;
    wela=1;
    P0=tempP0 & 0xfd;    //0111 1101
    wela=0;
    delayms(2);

/////////////////////////threeWela
    {  //消除叠影
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;
    dula=1;
    P0=table[threeWela]|((0x04&dot)?0x00:0x80);
    dula=0;

    P0=tempP0;
    wela=1;
    P0=tempP0 & 0xfb;    //0111 1011
    wela=0;
    delayms(2);

/////////////////////////fourWela
    {  //消除叠影
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;
    dula=1;
    P0=table[fourWela]|((0x08&dot)?0x00:0x80);
    dula=0;

    P0=tempP0;
    wela=1;
    P0=tempP0 & 0xf7;   //0111 0111
    wela=0;
    delayms(2);

/////////////////////////fiveWela
    {  //消除叠影
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;
    dula=1;
    P0=table[fiveWela]|((0x10&dot)?0x00:0x80);
    dula=0;

    P0=tempP0;
    wela=1;
    P0=tempP0 & 0xef; 		//0110 1111
    wela=0;
    delayms(2);

/////////////////////////sixWela
    {  //消除叠影
        P0=tempP0;
        wela=1;			
        P0=tempP0;
        wela=0;
    }
    P0=0;
    dula=1;
    P0=table[sixWela]|((0x20&dot)?0x00:0x80);
    dula=0;

    P0=tempP0;
    wela=1;
    P0=tempP0 & 0xdf;   //0101 1111
    wela=0;
    delayms(2);
}

#endif

 

0
3
分享到:
评论

相关推荐

    Proteus仿真实验之 51单片机模数(A/D)转换

    在Proteus中进行51单片机的A/D转换实验,首先需要配置单片机的A/D转换器。51单片机的A/D转换通常涉及以下几个步骤: 1. **初始化设置**:配置A/D转换器的工作模式,如选择采样时间、分辨率(一般为8位或12位)、...

    AVR学习笔记二十、基于模数转换的AD键盘实验.pdf

    基于模数转换的AD键盘实验,使用AVR系列微控制器的模数转换功能,配合ATmega16...在实验过程中,我们不仅学习了如何配置和使用模数转换器,还学习了如何处理串行通信和I/O端口的操作,加深了对AVR微控制器编程的理解。

    马伟力AVR笔记:六、模拟比较器和ADC实验.docx

    模拟比较器可以实现单片机系统电源电压的检测,更巧妙的应用是利用模拟比较器和一些简单的外围电路,设计简单的模数转换ADC。本实例实现利用模拟比较器比较某一点电压与内部模拟比较器参考电压的高低。 四、实验...

    51单片机自学笔记

    10. **应用扩展**:讲解如何将51单片机与其他外围设备如ADC(模数转换器)、DAC(数模转换器)、LCD显示屏等进行接口设计,提升系统的功能。 通过这些知识点的学习,初学者可以逐步掌握51单片机的基本操作和应用,...

    51单片机100V电压检测.zip

    5. `ADC0832.h`:ADC0832是一款8位逐次逼近型模数转换器,常用于51单片机系统中,这里可能是该芯片的头文件,定义了相关的函数和寄存器设置。 6. `两路电压检测.hex`:这是编译后的目标文件,可以直接烧录到51...

    C51单片机学习记录.zip

    此外,单片机还经常与外围设备如LCD显示屏、ADC(模数转换器)、DAC(数模转换器)、传感器等交互,这需要熟悉相应的接口协议和驱动程序编写。 "《C51单片机学习记录》"中的文件可能包含了以上各个方面的实例代码和...

    AVR学习笔记6、模拟比较器和ADC实验.rar_avr学习笔记

    AVR学习笔记6主要聚焦在模拟比较器和模数转换器(ADC)的应用上,这两者是AVR单片机中非常重要的硬件模块,对于理解和掌握AVR微控制器的使用至关重要。 模拟比较器(Analog Comparator)是AVR单片机中用于比较两个...

    msp430g2553学习笔记-----ADC10(公开).doc

    在深入探讨MSP430G2553微控制器中的ADC10模数转换器之前,我们首先需要了解ADC的基本概念。模数转换器(Analog-to-Digital Converter,ADC)是一种电子设备,它将连续变化的模拟信号转换为离散的数字表示,这个过程...

    飞思卡尔单片机设计的数字电压表

    首先,它通过一个模数转换器(ADC)将输入的模拟电压信号转化为数字信号,这是数字电压表的基础。ADC的选择应考虑其分辨率、转换速度和精度,以满足测量需求。 接下来,单片机会对ADC采集的数据进行处理,可能包括...

    《手把手教你学51单片机》例程配套文件教材配套程序文件

    7. **模数转换和数模转换**:在与模拟信号打交道时,了解ADC和DAC的原理及其在51单片机中的应用。 总的来说,这个压缩包为51单片机的学习提供了一套完整的实践资源,涵盖了从基础概念到实际应用的各个环节。通过...

    单片机学习资料

    学习者将学习到如何使用ADC(模数转换器)将模拟信号转换为数字值,以便单片机可以处理。 8. **【Energia开发环境】MSP430学习笔记.zip**:这可能是一个包含更多关于使用Energia进行MSP430开发的详细笔记或示例代码...

    十天学会单片机实例100

    理解模拟电路和如何与之交互,如ADC(模数转换器)和DAC(数模转换器)是单片机应用中的重要技能。 9. **编程环境与工具**:使用如AVR Studio等集成开发环境(IDE)进行编程,学习如何烧录程序到单片机,以及使用...

    《PIC单片机自学笔记》随书程序及原理图

    此外,这些实例可能还会涉及到模拟电路和数字电路的应用,如ADC(模数转换器)和DAC(数模转换器)的使用,以处理模拟信号。你还可以从中学到如何利用PIC单片机的内部资源,如定时器和计数器,来执行特定任务,如...

    MMA7361例程和资料整理

    为了与MMA7361通信,需要通过模拟输入引脚读取传感器的输出电压,然后通过ADC(模数转换器)将这些模拟信号转化为数字值。在实际应用中,通常需要编写相应的驱动程序,以实现数据的采集、处理和显示。 三、MMA7361...

    单片机源码-Mini51B的简易数字示波器系统(设计报告+电路原理图+仿真文件+程序).zip

    数字示波器的关键组件可能包括ADC(模数转换器)用于将模拟信号转换为数字信号,以及CPLD(复杂可编程逻辑器件)用于数据处理和接口控制。“数据采集卡电路图.pdf”和“CPLD接口设计.rar”可能包含这些硬件部分的...

    AVR学习笔记--AD应用指导

    ATmega16是一款8位微控制器,内置了高级RISC结构,具有多个输入/输出引脚、定时器、串行通信接口以及模数转换器(ADC)。模数转换是将物理世界中的模拟信号转化为数字信号的关键步骤,在许多嵌入式系统和物联网设备...

    LG-单片机开发板产品说明

    - 实验模块:可能包括ADC(模数转换器)、DAC(数模转换器)、PWM(脉宽调制)、UART(通用异步收发传输器)等,便于用户进行各种功能测试。 - 接口扩展:如USB、串口、SPI、I2C等通信接口,方便与其他设备交互。 ...

Global site tag (gtag.js) - Google Analytics