前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

51单片机C语言编程(十一)-模数、数模转换

qiguaw 2024-09-16 01:29:46 资源文章 17 ℃ 0 评论

一、AD转换

1、电位器AD值

XPT2046.h

#ifndef	 __XPT2046_H_
#define __XPT2046_H_
//---包含头文件---//
#include<reg52.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
//---定义使用的IO口---//
sbit DOUT = P3^7;	 //输出
sbit CLK = P3^6;	 //时钟
sbit DIN = P3^4;	 //输入
sbit CS = P3^5;	 //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif

XPT2046.c

#include"XPT2046.h"
/****************************************************************************
*函数名:SPI_Write
*输 入:dat:写入数据
*输 出:无
*功 能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
	uchar i;
	CLK = 0;
	for(i=0; i<8; i++)
	{
		DIN = dat >> 7; 	//放置最高位
		dat <<= 1;
		CLK = 0;			//上升沿放置数据
		CLK = 1;
	}
}
/****************************************************************************
*函数名:SPI_Read
*输 入:无
*输 出:dat:读取 到的数据
*功 能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
	uint i, dat=0;
	CLK = 0;
	for(i=0; i<12; i++)		//接收12位数据
	{
		dat <<= 1;
		CLK = 1;
		CLK = 0;
		dat |= DOUT;
	}
	return dat;	
}
/****************************************************************************
*函数名:Read_AD_Data
*输 入:cmd:读取的X或者Y
*输 出:endValue:最终信号处理后返回的值
*功 能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
	uchar i;
	uint AD_Value;
	CLK = 0;
	CS = 0;
	SPI_Write(cmd);
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	 //发送一个时钟周期,清除BUSY
	_nop_();
	_nop_();
	CLK = 0;
	_nop_();
	_nop_();
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}

main.c

/**************************************************************************************
*		 电位器AD实验												 *
实现现象:下载程序后数码管后4位显示电位器检测的AD值,范围是0-4095,一般达不到最大,这个受
			你供电电压的影响.
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				 
***************************************************************************************/
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"	
typedef unsigned int u16;	 //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*******************************************************************************
* 函 数 名 : delay
* 函数功能		 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函数名 :datapros()
* 函数功能		 :数据处理函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void datapros()
{
	u16 temp;
	static u8 i;
	if(i==50)
	{
		i=0;
		temp = Read_AD_Data(0x94);		// AIN0 电位器
	}
	i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];//个位
	disp[3]=smgduan[temp%1000%100%10];		
}
/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能		 :数码管显示函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void DigDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第0位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第1位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第2位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第3位	
		}
		P0=disp[3-i];//发送数据
		delay(100); //间隔一段时间扫描	
		P0=0x00;//消隐
	}		
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能		 : 主函数
* 输 入 : 无
* 输 出 	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		datapros();	 //数据处理函数
		DigDisplay();//数码管显示函数		
	}		
}

2、光敏电阻AD值

XPT2046.h

#ifndef	 __XPT2046_H_
#define __XPT2046_H_
//---包含头文件---//
#include<reg52.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
//---定义使用的IO口---//
sbit DOUT = P3^7;	 //输出
sbit CLK = P3^6;	 //时钟
sbit DIN = P3^4;	 //输入
sbit CS = P3^5;	 //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif

XPT2046.c

#include"XPT2046.h"
/****************************************************************************
*函数名:TSPI_Start
*输 入:无
*输 出:无
*功 能:初始化触摸SPI
****************************************************************************/
void SPI_Start(void)
{
	CLK = 0;
	CS = 1;
	DIN = 1;
	CLK = 1;
	CS = 0;		
}
/****************************************************************************
*函数名:SPI_Write
*输 入:dat:写入数据
*输 出:无
*功 能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
	uchar i;
	CLK = 0;
	for(i=0; i<8; i++)
	{
		DIN = dat >> 7; 	//放置最高位
		dat <<= 1;
		CLK = 0;			//上升沿放置数据
		CLK = 1;
	}
}
/****************************************************************************
*函数名:SPI_Read
*输 入:无
*输 出:dat:读取 到的数据
*功 能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
	uint i, dat=0;
	CLK = 0;
	for(i=0; i<12; i++)		//接收12位数据
	{
		dat <<= 1;
		CLK = 1;
		CLK = 0;
		dat |= DOUT;
	}
	return dat;	
}
/****************************************************************************
*函数名:Read_AD_Data
*输 入:cmd:读取的X或者Y
*输 出:endValue:最终信号处理后返回的值
*功 能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
	uchar i;
	uint AD_Value;
	CLK = 0;
	CS = 0;
	SPI_Write(cmd);
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	 //发送一个时钟周期,清除BUSY
	_nop_();
	_nop_();
	CLK = 0;
	_nop_();
	_nop_();
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}

main.c

/**************************************************************************************
*		 光敏电阻AD实验												 *
实现现象:下载程序后数码管后4位显示光敏电阻检测的AD值。
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				 
***************************************************************************************/
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"	
typedef unsigned int u16;	 //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*******************************************************************************
* 函 数 名 : delay
* 函数功能		 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函数名 :datapros()
* 函数功能		 :数据处理函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void datapros()
{
	u16 temp;
	static u8 i;
	if(i==50)
	{
		i=0;
		temp = Read_AD_Data(0xA4);		// AIN2 光敏电阻
	}
	i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];//个位
	disp[3]=smgduan[temp%1000%100%10];		
}
/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能		 :数码管显示函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void DigDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第0位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第1位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第2位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第3位	
		}
		P0=disp[3-i];//发送数据
		delay(100); //间隔一段时间扫描	
		P0=0x00;//消隐
	}		
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能		 : 主函数
* 输 入 : 无
* 输 出 	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		datapros();	 //数据处理函数
		DigDisplay();//数码管显示函数		
	}		
}

注明:本实验均采用HC6800-ES V2.0开发板。

3、热敏电阻AD值

XPT2046.h

#ifndef	 __XPT2046_H_
#define __XPT2046_H_
//---包含头文件---//
#include<reg52.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
//---定义使用的IO口---//
sbit DOUT = P3^7;	 //输出
sbit CLK = P3^6;	 //时钟
sbit DIN = P3^4;	 //输入
sbit CS = P3^5;	 //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif

XPT2046.c

#include"XPT2046.h"
/****************************************************************************
*函数名:TSPI_Start
*输 入:无
*输 出:无
*功 能:初始化触摸SPI
****************************************************************************/
void SPI_Start(void)
{
	CLK = 0;
	CS = 1;
	DIN = 1;
	CLK = 1;
	CS = 0;		
}
/****************************************************************************
*函数名:SPI_Write
*输 入:dat:写入数据
*输 出:无
*功 能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
	uchar i;
	CLK = 0;
	for(i=0; i<8; i++)
	{
		DIN = dat >> 7; 	//放置最高位
		dat <<= 1;
		CLK = 0;			//上升沿放置数据
		CLK = 1;
	}
}
/****************************************************************************
*函数名:SPI_Read
*输 入:无
*输 出:dat:读取 到的数据
*功 能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
	uint i, dat=0;
	CLK = 0;
	for(i=0; i<12; i++)		//接收12位数据
	{
		dat <<= 1;
		CLK = 1;
		CLK = 0;
		dat |= DOUT;
	}
	return dat;	
}
/****************************************************************************
*函数名:Read_AD_Data
*输 入:cmd:读取的X或者Y
*输 出:endValue:最终信号处理后返回的值
*功 能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
	uchar i;
	uint AD_Value;
	CLK = 0;
	CS = 0;
	SPI_Write(cmd);
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	 //发送一个时钟周期,清除BUSY
	_nop_();
	_nop_();
	CLK = 0;
	_nop_();
	_nop_();
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}

main.c

/**************************************************************************************
*		 热敏电阻AD实验												 *
实现现象:下载程序后数码管后4位显示热敏电阻检测的AD值.
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				 
***************************************************************************************/
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"	
typedef unsigned int u16;	 //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*******************************************************************************
* 函 数 名 : delay
* 函数功能		 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函数名 :datapros()
* 函数功能		 :数据处理函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void datapros()
{
	u16 temp;
	static u8 i;
	if(i==50)
	{
		i=0;
		temp = Read_AD_Data(0xD4);		// AIN1 热敏电阻
	}
	i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];//个位
	disp[3]=smgduan[temp%1000%100%10];		
}
/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能		 :数码管显示函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void DigDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第0位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第1位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第2位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第3位	
		}
		P0=disp[3-i];//发送数据
		delay(100); //间隔一段时间扫描	
		P0=0x00;//消隐
	}		
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能		 : 主函数
* 输 入 : 无
* 输 出 	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		datapros();	 //数据处理函数
		DigDisplay();//数码管显示函数		
	}		
}

4、外部输入AD值

XPT2046.h

#ifndef	 __XPT2046_H_
#define __XPT2046_H_
//---包含头文件---//
#include<reg52.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
//---定义使用的IO口---//
sbit DOUT = P3^7;	 //输出
sbit CLK = P3^6;	 //时钟
sbit DIN = P3^4;	 //输入
sbit CS = P3^5;	 //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif

XPT2046.c

#include"XPT2046.h"
/****************************************************************************
*函数名:TSPI_Start
*输 入:无
*输 出:无
*功 能:初始化触摸SPI
****************************************************************************/
void SPI_Start(void)
{
	CLK = 0;
	CS = 1;
	DIN = 1;
	CLK = 1;
	CS = 0;		
}
/****************************************************************************
*函数名:SPI_Write
*输 入:dat:写入数据
*输 出:无
*功 能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
	uchar i;
	CLK = 0;
	for(i=0; i<8; i++)
	{
		DIN = dat >> 7; 	//放置最高位
		dat <<= 1;
		CLK = 0;			//上升沿放置数据
		CLK = 1;
	}
}
/****************************************************************************
*函数名:SPI_Read
*输 入:无
*输 出:dat:读取 到的数据
*功 能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
	uint i, dat=0;
	CLK = 0;
	for(i=0; i<12; i++)		//接收12位数据
	{
		dat <<= 1;
		CLK = 1;
		CLK = 0;
		dat |= DOUT;
	}
	return dat;	
}
/****************************************************************************
*函数名:Read_AD_Data
*输 入:cmd:读取的X或者Y
*输 出:endValue:最终信号处理后返回的值
*功 能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
	uchar i;
	uint AD_Value;
	CLK = 0;
	CS = 0;
	SPI_Write(cmd);
	for(i=6; i>0; i--); 	//延时等待转换结果
	CLK = 1;	 //发送一个时钟周期,清除BUSY
	_nop_();
	_nop_();
	CLK = 0;
	_nop_();
	_nop_();
	AD_Value=SPI_Read();
	CS = 1;
	return AD_Value;	
}

main.c

/**************************************************************************************
*		 外部输入AD实验												 *
实现现象:下载程序后数码管后4位显示外部输入IN3通道检测的AD值,模拟信号电压范围在0-5V
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				 
***************************************************************************************/
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"	
typedef unsigned int u16;	 //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 disp[4];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/*******************************************************************************
* 函 数 名 : delay
* 函数功能		 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
	while(i--);	
}
/*******************************************************************************
* 函数名 :datapros()
* 函数功能		 :数据处理函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void datapros()
{
	u16 temp;
	static u8 i;
	if(i==50)
	{
		i=0;
		temp = Read_AD_Data(0xE4);		// AIN3 外部输入
	}
	i++;
	disp[0]=smgduan[temp/1000];//千位
	disp[1]=smgduan[temp%1000/100];//百位
	disp[2]=smgduan[temp%1000%100/10];//个位
	disp[3]=smgduan[temp%1000%100%10];		
}
/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能		 :数码管显示函数
* 输入 : 无
* 输出 	 : 无
*******************************************************************************/
void DigDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)	 //位选,选择点亮的数码管,
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break;//显示第0位
			case(1):
				LSA=1;LSB=0;LSC=0; break;//显示第1位
			case(2):
				LSA=0;LSB=1;LSC=0; break;//显示第2位
			case(3):
				LSA=1;LSB=1;LSC=0; break;//显示第3位	
		}
		P0=disp[3-i];//发送数据
		delay(100); //间隔一段时间扫描	
		P0=0x00;//消隐
	}		
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能		 : 主函数
* 输 入 : 无
* 输 出 	 : 无
*******************************************************************************/
void main()
{	
	while(1)
	{
		datapros();	 //数据处理函数
		DigDisplay();//数码管显示函数		
	}		
}

二、DA转换

/**************************************************************************************
*		 DA-PWM输出实验												 *
实现现象:下载程序后DA模块上的指示灯呈呼吸灯效果,由暗变亮再由亮变暗
注意事项:要将AD/DA模块上的短接片将OUT和LED短接,板子丝印上有。
		 如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				 
***************************************************************************************/
#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16;	 //对数据类型进行声明定义
typedef unsigned char u8;
//--定义使用的IO口--//
sbit PWM=P2^1;
bit DIR;
//--定义一个全局变量--// 
u16 count,value,timer1;
/*******************************************************************************
* 函 数 名 : Timer1Init
* 函数功能		 : 定时器1初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1Init()
{
	TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
	TH1 = 0xFF; 
	TL1 = 0xff; //1us
		
	ET1=1;//打开定时器1中断允许
	EA=1;//打开总中断
	TR1=1;//打开定时器			
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能		 : 主函数
* 输 入 : 无
* 输 出 	 : 无
*******************************************************************************/
void main()
{	
	Timer1Init(); //定时器1初始化
	while(1)
	{
		if(count>100)							
		{ 
			count=0;
			if(DIR==1)					 //DIR控制增加或减小
			{
			 value++;
			}			
			if(DIR==0)
			{
			 value--;
			}
				
		}
		if(value==1000)
		{
		 DIR=0;
		}
		if(value==0)
		{
		 DIR=1;
		}	
				
		if(timer1>1000) //PWM周期为1000*1us
		{
			timer1=0;
		}
		if(timer1 <value)	
		{
			PWM=1;
		}
		else
		{
			PWM=0;
		}		
	}		
}
/*******************************************************************************
* 函 数 名 : Time1
* 函数功能		 : 定时器1的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Time1(void) interrupt 3 //3 为定时器1的中断号 1 定时器0的中断号 0 外部中断1 2 外部中断2 4 串口中断
{
	TH1 = 0xFF; 
	TL1 = 0xff; //1us
	timer1++; 
 count++;
	
}

本实验输出PWM波,编译生成hex文件后,下载到CPU中,DA模块的指示灯会呈现呼吸灯效果。

注明:本文所以程序均可在HC6800-ES V2.0开发板运行。开发板原理图以及有关芯片资料均可私戳小编获取!欢迎转发和收藏!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表