/单通道的ADC采集/void Adc_Config(void){ /定义两个初始化要用的结构体,下面给每个结构体成员赋值/ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;/ 使能GPIOA和ADC1通道时钟 注意:除了RCC_APB2PeriphClockCmd还有RCC_APB1PeriphClockCmd,那么该如何选择? APB2:高速时钟,最高72MHz,主要负责AD输入,I/O,串口1,高级定时器TIM APB1:低速时钟,最高36MHz,主要负责DA输出,串口2、3、4、5,普通定时器TIM,USB,IIC,CAN,SPI /RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12, ADC的采样时钟最快14MHz /配置输入电压所用的PA0引脚/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO_Mode_AIN:模拟输入(还有其他什么模式?请看下面的附录图1)GPIO_Init(GPIOA, &GPIO_InitStructure);ADC_DeInit(ADC1); //复位,将ADC1相关的寄存器设为默认值ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//工作模式:ADC1和ADC2独立工作模式 (还有其他什么模式?请看下面的附录图2)ADC_InitStructure.ADC_ScanConvMode = DISABLE;//数模转换工作:扫描(多通道)模式=ENABLE、单次(单通道)模式=DISABLEADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//数模转换工作:连续=ENABLE、单次=DISABLEADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC转换由软件触发启动 (还有其他什么模式?请看下面的附录图3)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐 除了右就是左:ADC_DataAlign_LeftADC_InitStructure.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目 范围是1-16ADC_Init(ADC1, &ADC_InitStructure);//根据ADC_InitStruct中指定的参数初始化外设ADC1的寄存器 /为啥要设置下面这一步? 细心的你可以发现上面初始化了一个引脚通道,初始化了一个ADC转换器,但ADC转换器并不知道你用的是哪个引脚吧? 这一步目的是:设置指定ADC的规则组通道(引脚),设置它们的转化顺序和采样时间 函数原型:void ADC_RegularChannelConfig(ADC_TypeDef ADCx, u8 ADC_Channel, u8 Rank, u8 ADC_SampleTime) 参数1 ADCx:x可以是1或者2来选择ADC外设ADC1或ADC2 参数2 ADC_Channel:被设置的ADC通道 范围ADC_Channel_0~ADC_Channel_17 参数3 Rank:规则组采样顺序取值范围1到16 ADC_SampleTime:指定ADC通道的采样时间值 (取值范围?请看下面的附录图4) / ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 ); ADC_Cmd(ADC1, ENABLE);//使能指定的ADC 注意:函数ADC_Cmd只能在其他ADC设置函数之后被调用 /下面4步按流程走,走完就行/ADC_ResetCalibration(ADC1);//重置指定的ADC的校准寄存器while(ADC_GetResetCalibrationStatus(ADC1)); //等待上一步操作完成ADC_StartCalibration(ADC1);//开始指定ADC的校准状态while(ADC_GetCalibrationStatus(ADC1));//等待上一步操作按成 }
Copy附录图1-GPIO_Mode值:附录图2-ADC_Mode值:附录图3-ADC_ExternalTrigConv值:附录图4-ADC_SampleTime值:对于一些刚接触stm32的人来说,看了上面的代码可能还会有很多疑问为什么要使能时钟?时钟到底设置多少才合适?对于ADC_GetConversionValue(ADC1)这个函数参数并没有指定那个通道,如果多个通道同时使用CAN1转换器转换时怎么获取每个通道的值?第一个问题,所有的外设都要使能时钟,时钟源分为外部时钟和内部时钟,外部时钟比如接8MHz晶振,内部时钟就在芯片内部集成,时钟源为所有的时序电路提供基本的脉冲信号时钟源好比是一颗跳动的心脏,它按照一定的频率在跳动,所有的器官(外设)要跟心脏(时钟源)桥接起来才能工作,但不同的外设需要的频率不同,所以在时钟源跟外设之中常常还会有一些分频器或者倍频器,以实现对频率的衰减或增强还想了解更多专业的解释可以去研究stm32的时钟树图第二个问题,回答这个问题那么就等于开始介绍多通道转换怎么实现了,看下图由图理解,一个ADC转换器只能选择转换一个通道,那么对比单通道我们只需做一下改变(以双通道为例):1.在void Adc_Config(void)函数里面添加:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure);
Copy配置多一个IO(PA1)口, 也就是通道12.在void Adc_Config(void)函数里面添加:ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
Copy首先简单介绍DMA,DMA(Direct Memory Access,直接内存存取) ,用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输无需CPU干预,节省CPU资源;ADC转换出来的值直接赋值给定义好的变量中配置好的DMA可以不停地将ADC转换值写到该变量中,在主函数直接判断该变量就知道此时的AD值,也就是说在主函数中不需要调用ADC_GetConversionValue()函数来获取转换值DMA跟其他外设一样需要进行配置通道,使能时钟等参数下面直接看代码分析:/基于DMA的ADC多通道采集/volatile uint16 ADCConvertedValue[10][3];//用来存放ADC转换结果,也是DMA的目标地址,3通道,每通道采集10次后面取平均数 void DMA_Init(void){ DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能时钟 DMA_DeInit(DMA1_Channel1); //将通道一寄存器设为默认值 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);//该参数用以定义DMA外设基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;//该参数用以定义DMA内存基地址(转换结果保存的地址) DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//该参数规定了外设是作为数据传输的目的地还是来源,此处是作为来源 DMA_InitStructure.DMA_BufferSize = 310;//定义指定DMA通道的DMA缓存的大小,单位为数据单位这里也就是ADCConvertedValue的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//设定外设地址寄存器递增与否,此处设为不变 Disable DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//用来设定内存地址寄存器递增与否,此处设为递增,Enable DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度为16位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据宽度为16位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道拥有高优先级 分别4个等级 低、中、高、非常高 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//使能DMA通道的内存到内存传输 DMA_Init(DMA1_Channel1, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道 DMA_Cmd(DMA1_Channel1, ENABLE);//启动DMA通道一}
Copy(图片来源网络,侵删)
0 评论