ADDA数模转换(PCF8591)

ADDA转换概念:
是指模/数转换器或者模拟/数字转换器 。
是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
PCF8591
	PCF8591是一种具有I2C总线接口的8位A/D,D/A转换芯片,在于
CPU的信息传输过程中仅靠时钟线SCL与数据线SDA就可以实现 。在
PCF8591的器件上输入输出的地址、控制和数据信号都是通过双向总线以
串行的方式进行传输 。PCF8591的功能包括多路模拟输入、内置跟踪保
持、8-bit模数转换和8-bit数模转换 。PCF8591的最大转换速率由I2C
总线的最大速率决定。
PCF8591电路图

在这里插入图片描述

PCF8591具有4个模拟输入(AIN0~AIN3)、1个模拟输出(AOUT)和1个串行I²C总线接口(SDA、SCL)。 
PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。
在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。 
OSC:外部时钟输入端,内部时钟 
EXT:内部、外部时钟选择线,使用内部时钟时 EXT 接地。 
VDD、VSS:电源端。 
AGND:模拟信号地。 
VREF:基准电源端

AD源码

int main(void)
{ 
	u16 adcx;
	float temp;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200); //初始化串口波特率为115200
	Adc_Init();         //初始化ADC

	while(1)
	{ 
	adcx=Get_Adc_Average(ADC_Channel_5,20);//获取通道5的转换值,20次取平均
	temp=(float)adcx*(3.3/4096);          //获取计算后的带小数的实际电压值,比如3.1111
	adcx=temp;                            //赋值整数部分给adcx变量,因为adcx为u16整形
	temp-=adcx;                           //把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111
	temp*=1000;                           //小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。
	delay_ms(250); 
	}
}
#include "adc.h"
#include "delay.h" 

//初始化ADC                  
void  Adc_Init(void)
{    
	GPIO_InitTypeDef  GPIO_InitStructure;
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	ADC_InitTypeDef  ADC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟

	//先初始化ADC1通道5 IO口
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PA5 通道5
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//不带上下拉
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化  
	
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);   //ADC1复位
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束  

	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟
	ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
	ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz 
	ADC_CommonInit(&ADC_CommonInitStructure);//初始化
	
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式 
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐 
	ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 
	ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
}
	
//获得ADC值
//ch: @ref ADC_channels 
//通道值 0~16取值范围为:ADC_Channel_0~ADC_Channel_16
//返回值:转换结果
u16 Get_Adc(u8 ch) 
{
	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles ); //ADC1,ADC通道,480个周期,提高采样时间可以提高精确度       
	ADC_SoftwareStartConv(ADC1);  //使能指定的ADC1的软件转换启动功能 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
	return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}

//获取通道ch的转换值,取times次,然后平均 
//ch:通道编号
//times:获取次数
//返回值:通道ch的times次转换结果平均值

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 

DA源码

int main(void)
{ 
	u16 adcx;
	float temp;
	u8 t=0;  
	u16 dacval=0;
	u8 key; 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);      //初始化延时函数
	uart_init(115200);  //初始化串口波特率为115200
	Adc_Init();     //adc初始化
	KEY_Init();     //按键初始化
	Dac1_Init();     //DAC通道1初始化
	DAC_SetChannel1Data(DAC_Align_12b_R,dacval);//初始值为0 
	
	while(1)
	{
		t++;
		key=KEY_Scan(0);     
		if(key==WKUP_PRES)
		{   
			if(dacval<4000)dacval+=200;
			DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
		}
		else if(key==2) 
		{
			if(dacval>200)dacval-=200;
			else dacval=0;
			DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
		}  
		if(t==10||key==KEY1_PRES||key==WKUP_PRES)  //WKUP/KEY1按下了,或者定时时间到了
		{   
 			adcx=DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值
			temp=(float)adcx*(3.3/4096);            //得到DAC电压值
			adcx=temp;
			temp-=adcx;
			temp*=1000;
			adcx=Get_Adc_Average(ADC_Channel_5,10);  //得到ADC转换值   
			temp=(float)adcx*(3.3/4096);           //得到ADC电压值
			adcx=temp;
			temp-=adcx;
			temp*=1000;    
			t=0;
		}     
	delay_ms(10);  
	} 
}
#include "dac.h"

//DAC通道1输出初始化
void Dac1_Init(void)
{  
	GPIO_InitTypeDef  GPIO_InitStructure;
	DAC_InitTypeDef DAC_InitType;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
	  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
	
	DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
	DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
	DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
	DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
	DAC_Init(DAC_Channel_1,&DAC_InitType);  //初始化DAC通道1
	DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC通道1
  
	DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值
}

//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
	double temp=vol;
	temp/=1000;
	temp=temp*4096/3.3;
	DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}
发布了5 篇原创文章 · 获赞 9 · 访问量 150

猜你喜欢

转载自blog.csdn.net/R_Z_Q/article/details/104454683