STM32学习问题记录(6)--ADC(DMA方式)

    在上一次的博客中重新学习了DMA(附上链接:点击打开链接),这次我们便学以致用了,ADC的概念想必大家都是十分清楚了,模拟转数字,可以用在测信号,测电压,在我们的生活中有着十分巨大的作用,这次我们就来看看ADC又有哪些操作吧!

       ADC流程,首先ADC采集一个信号(信号范围大都为0-3.3V,ps:3.3V可通过更改Vref寄存器修改),每隔相同时间菜一次数值发送到一个可变16位数中,下面是我们的数组定义:

__IO uint16_t ADC_ConvertedValue;    //定义该16位数用来传输数据,原因是我们使用的12位AD,由于寄存器的定义方便,因此使用16位数

下面是ADC的初始化和配置代码:

void ADC1_Init(void)
{
	ADC1_GPIO_Config();     //下面有详细的代码配置
	ADC1_Mode_Config();
}

static void ADC1_GPIO_Config(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;    //定义写入寄存器的结构体
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能时钟,注意使能的是DMA1
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); //本实验使用的是GPIOC1,使能ADC1,GPIO时钟
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  //配置为PC.1    
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //设置为模拟输入 
 GPIO_Init(GPIOC, &GPIO_InitStructure);    // 初始化写入寄存器中
}

static void ADC1_Mode_Config(void)
{
 DMA_InitTypeDef DMA_InitStructure;   //定义写入DMA寄存器的结构体
 ADC_InitTypeDef ADC_InitStructure;   //定义写入ADC寄存器的结构体
 DMA_DeInit(DMA1_Channel1);  //复位初始化,配置为复位模式,下面我们再重新配置(不知道有用没)
 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;    //设置源地址
 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //设置内存地址
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  // 设置传输方向
 DMA_InitStructure.DMA_BufferSize = 1;    //因为我们最后一直改变一个变量,所以只有一位
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;      //内存地址固定
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设传输数据大小为半字
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   //内存传输数据大小为半字
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;          //循环模式
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;    //高优先级
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;     //禁止内存间传输数据
 DMA_Init(DMA1_Channel1, &DMA_InitStructure);    //将结构体写入寄存器中
 
 DMA_Cmd(DMA1_Channel1, ENABLE);    //使能DMA寄存器的1通道
 
 /* ADC1 configuration */ 
 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;   //因为只有一个通道,所以为独立ADC模式
 ADC_InitStructure.ADC_ScanConvMode = DISABLE ;       //一个通道,所以不使能扫描模式
 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;   //开启连续转换,就是不停转换
 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发,外部触发只有几个固定引脚,详情看手册
 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //我们定义16位数,采集12位,所以要定义对齐方向,在这我们采取右对齐
 ADC_InitStructure.ADC_NbrOfChannel = 1;          //要转换的通道数目
 ADC_Init(ADC1, &ADC_InitStructure);          ////将结构体写入寄存器中
 
 RCC_ADCCLKConfig(RCC_PCLK2_Div8);   //72M时钟8分频为9M PS:ADC最大时钟速率为14M,后面解释

 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);  //初始化,采样时间为55.5us,采样序号是1,PS:采样时间最                                                                         // 为1.5us,转换时间为固定12.5us,所以相当于采集完一次数为14us
 ADC_DMACmd(ADC1, ENABLE);   //  使能DMA1 
 ADC_Cmd(ADC1, ENABLE);   //使能ADC1 
 ADC_ResetCalibration(ADC1);   //复位校准寄存器
 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准寄存器完成 
 ADC_StartCalibration(ADC1);   //ADC校准
 while(ADC_GetCalibrationStatus(ADC1));  //等待校准完成 
 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1的软件触发
}
 
 

以上就是我们用到的ADC的配置代码,若要读出ADC的数值,只需要调用我们的输出寄存器值就可完成,下面有个小例子,结合之前的串口通信代码,可将采集到的AD数值发送到电脑串口调试助手上

 
 
while (1)
{
ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; // 转化 PS:将0-3.3分成4096份,ADC读出的是多少份,所以以这                                                                                //样计算	
printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); 
printf("\r\n The current AD value = %f V \r\n",ADC_ConvertedValueLocal);     //打印,USART代码  链接:点击打开链接
Delay(0xffffee);   //延时
}



以上,有问题或有建议的同学可在下面评论或者私信我,我都会看的哈哈!


猜你喜欢

转载自blog.csdn.net/vca821/article/details/80539564