零死角玩转STM32—F4292.代码分析
ADC宏定义代码清单30-7多通道ADC相关宏定义12345678910111213141516171819202122232425//转换的通道个数#defineRHEOSTAT_NOFCHANEL#define#define#define#define#defineRHEOSTAT_ADC_DR_ADDRRHEOSTAT_ADC_GPIO_PORTRHEOSTAT_ADC_GPIO_CLKRHEOSTAT_ADCRHEOSTAT_ADC_CLK4((u32)ADC3+0x4c)GPIOFRCC_AHB1Periph_GPIOFADC3RCC_APB2Periph_ADC3GPIO_Pin_6ADC_Channel_4GPIO_Pin_7ADC_Channel_5GPIO_Pin_8ADC_Channel_6GPIO_Pin_9ADC_Channel_7RCC_AHB1Periph_DMA2DMA_Channel_2DMA2_Stream0#defineRHEOSTAT_ADC_GPIO_PIN1#defineRHEOSTAT_ADC_CHANNEL1#defineRHEOSTAT_ADC_GPIO_PIN2#defineRHEOSTAT_ADC_CHANNEL2#defineRHEOSTAT_ADC_GPIO_PIN3#defineRHEOSTAT_ADC_CHANNEL3#defineRHEOSTAT_ADC_GPIO_PIN4#defineRHEOSTAT_ADC_CHANNEL4//DMA2#define#define#define数据流0通道2RHEOSTAT_ADC_DMA_CLKRHEOSTAT_ADC_DMA_CHANNELRHEOSTAT_ADC_DMA_STREAM定义4个通道进行多通道ADC实验,并且定义DMA相关配置。ADCGPIO初始化函数代码清单30-8ADCGPIO初始化1staticvoidRheostat_ADC_GPIO_Config(void)2{3GPIO_InitTypeDefGPIO_InitStructure;45//使能GPIO时钟6RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK,ENABLE);78//配置IO9GPIO_InitStructure.GPIO_Pin=RHEOSTAT_ADC_GPIO_PIN1|10RHEOSTAT_ADC_GPIO_PIN2|11RHEOSTAT_ADC_GPIO_PIN3|12RHEOSTAT_ADC_GPIO_PIN4;13GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;14GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不上拉不下拉15GPIO_Init(RHEOSTAT_ADC_GPIO_PORT,&GPIO_InitStructure);16}使用到GPIO时候都必须开启对应的GPIO时钟,GPIO用于AD转换功能必须配置为模拟输入模式。配置ADC工作模式代码清单30-9ADC工作模式配置1staticvoidRheostat_ADC_Mode_Config(void)第456页共996
零死角玩转STM32—F4292{34567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465DMA_InitTypeDefDMA_InitStructure;ADC_InitTypeDefADC_InitStructure;ADC_CommonInitTypeDefADC_CommonInitStructure;//开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK,ENABLE);//开启DMA时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK,ENABLE);//------------------DMAInit结构体参数初始化------------------------//选择DMA通道,通道存在于数据流中DMA_InitStructure.DMA_Channel=RHEOSTAT_ADC_DMA_CHANNEL;//外设基址为:ADC数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr=RHEOSTAT_ADC_DR_ADDR;//存储器地址DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)ADC_ConvertedValue;//数据传输方向为外设到存储器DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;//缓冲区大小,指一次传输的数据项DMA_InitStructure.DMA_BufferSize=RHEOSTAT_NOFCHANEL;//外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//存储器地址递增DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//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传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority=DMA_Priority_High;//禁止DMAFIFO,使用直连模式DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//FIFO阈值大小,FIFO模式禁止时,这个不用配置DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;//存储器突发单次传输DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;//外设突发单次传输DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;//初始化DMA数据流,流相当于一个大的管道,管道里面有很多通道DMA_Init(RHEOSTAT_ADC_DMA_STREAM,&DMA_InitStructure);//使能DMA数据流DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM,ENABLE);//-------------------ADCCommon结构体参数初始化--------------------//独立ADC模式ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;//时钟为fpclkx分频ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//禁止DMA直接访问模式ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;第457页共996
零死角玩转STM32—F42966676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107}//采样时间间隔ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_10Cycles;ADC_CommonInit(&ADC_CommonInitStructure);//-------------------ADCInit结构体参数初始化---------------------//ADC分辨率ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//开启扫描模式ADC_InitStructure.ADC_ScanConvMode=ENABLE;//连续转换ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//使用软件触发,外部触发不用配置,注释掉即可//ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//数据右对齐ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//转换通道x个ADC_InitStructure.ADC_NbrOfConversion=RHEOSTAT_NOFCHANEL;ADC_Init(RHEOSTAT_ADC,&ADC_InitStructure);//------------------------------------------------------------------//配置ADC通道转换顺序和采样时间周期ADC_RegularChannelConfig(RHEOSTAT_ADC,RHEOSTAT_ADC_CHANNEL1,1,ADC_SampleTime_56Cycles);ADC_RegularChannelConfig(RHEOSTAT_ADC,RHEOSTAT_ADC_CHANNEL2,2,ADC_SampleTime_56Cycles);ADC_RegularChannelConfig(RHEOSTAT_ADC,RHEOSTAT_ADC_CHANNEL3,3,ADC_SampleTime_56Cycles);ADC_RegularChannelConfig(RHEOSTAT_ADC,RHEOSTAT_ADC_CHANNEL4,4,ADC_SampleTime_56Cycles);//使能DMA请求afterlasttransfer(Single-ADCmode)ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC,ENABLE);//使能ADCDMAADC_DMACmd(RHEOSTAT_ADC,ENABLE);//使能ADCADC_Cmd(RHEOSTAT_ADC,ENABLE);//开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC);首先,我们使用了DMA_InitTypeDef定义了一个DMA初始化类型变量,该结构体内容我们在DMA篇已经做了非常详细的讲解;另外还使用ADC_InitTypeDef和ADC_CommonInitTypeDef结构体分别定义一个ADC初始化和ADC通用类型变量,这两个结构体我们之前已经有详细讲解。调用RCC_APB2PeriphClockCmd()开启ADC时钟以及RCC_AHB1PeriphClockCmd()开启DMA时钟。我们需要对DMA进行必要的配置。首先设置外设基地址就是ADC的规则数据寄存器地址;存储器的地址就是我们指定的数据存储区空间,ADC_ConvertedValue是我们定义的一个全局数组名,它是一个无符号16位含有4个元素的整数数组;ADC规则转换对应只有一个数据寄存器所以地址不能递增,而我们定义的存储区是专门用来存放不同通道数据的,所以需要自动地址递增。ADC的规则数据寄存器只有低16位有效,实际存放的数据只有12位而已,所以设置数据大小为半字大小。ADC配置为连续转换模式DMA也设置为循环传输模式。设置好DMA相关参数后就使能DMA的ADC通道。第458页共996
零死角玩转STM32—F429接下来我们使用ADC_CommonInitTypeDef结构体变量ADC_CommonInitStructure来配置ADC为独立模式、分频系数为4、不需要设置DMA模式、20个周期的采样延迟,并调用ADC_CommonInit函数完成ADC通用工作环境配置。我们使用ADC_InitTypeDef结构体变量ADC_InitStructure来配置ADC1为12位分辨率、使能扫描模式、启动连续转换、使用内部软件触发无需外部触发事件、使用右对齐数据格式、转换通道为4,并调用ADC_Init函数完成ADC3工作环境配置。ADC_RegularChannelConfig函数用来绑定ADC通道转换顺序和采样时间。分别绑定四个ADC通道引脚并设置相应的转换顺序。ADC_DMARequestAfterLastTransferCmd函数控制是否使能ADC的DMA请求,如果使能请求,并调用ADC_DMACmd函数使能DMA,则在ADC转换完成后就请求DMA实现数据传输。ADC_Cmd函数控制ADC转换启动和停止。最后,如果使用软件触发需要调用ADC_SoftwareStartConvCmd函数进行使能配置。主函数代码清单30-10主函数1intmain(void)2{3/*初始化USART1*/4Debug_USART_Config();56/*初始化滑动变阻器用到的DAC7,ADC数据采集完成后直接由DMA运输数据到ADC_ConvertedValue变量8DMA直接改变ADC_ConvertedValue的值*/9Rheostat_Init();1011printf(\----这是一个ADC实验(多通道采集)----\\r\\n\);1213while(1){14Delay(0xffffff);15ADC_ConvertedValueLocal[0]=(float)(ADC_ConvertedValue[0]*3.3/4096);16ADC_ConvertedValueLocal[1]=(float)(ADC_ConvertedValue[1]*3.3/4096);17ADC_ConvertedValueLocal[2]=(float)(ADC_ConvertedValue[2]*3.3/4096);18ADC_ConvertedValueLocal[3]=(float)(ADC_ConvertedValue[3]*3.3/4096);1920printf(\CH1_PF6value=%fV\\r\\n\,ADC_ConvertedValueLocal[0]);21printf(\CH2_PF7value=%fV\\r\\n\,ADC_ConvertedValueLocal[1]);22printf(\CH3_PF8value=%fV\\r\\n\,ADC_ConvertedValueLocal[2]);23printf(\CH4_PF9value=%fV\\r\\n\,ADC_ConvertedValueLocal[3]);2425printf(\);26}27}主函数先调用USARTx_Config函数配置调试串口相关参数,函数定义在bsp_debug_usart.c文件中。接下来调用Rheostat_Init函数进行ADC初始化配置并启动ADC。Rheostat_Init函数是定义在bsp_adc.c文件中,它只是简单的分别调用Rheostat_ADC_GPIO_Config()和Rheostat_ADC_Mode_Config()。Delay函数只是一个简单的延时函数。第459页共996
零死角玩转STM32—F429我们配置了DMA数据传输所以它会自动把ADC转换完成后数据保存到数组ADC_ConvertedValue内,我们只要直接使用数组就可以了。经过简单地计算就可以得到每个通道对应的实际电压。最后就是把相关数据打印至串口调试助手。30.5.3下载验证
将待测电压通过杜邦线接在对应引脚上,用USB线连接开发板“USBTOUART”接口跟电脑,在电脑端打开串口调试助手,把编译好的程序下载到开发板。在串口调试助手可看到不断有数据从开发板传输过来,此时我们改变输入电压值,那么对应的数据也会有变化。30.6三重ADC交替模式采集实验
AD转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;而在转换阶段只是将采集到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。独立模式的ADC采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。双重或者三重ADC的机制使用两个或以上ADC同时采样两个或以上不同通道的数据或者使用两个或以上ADC交叉采集同一通道的数据。双重或者三重ADC模式较独立模式一个最大的优势就是转换速度快。我们这里只介绍三重ADC交替模式,关于双重或者三重ADC的其他模式与之类似,可以参考三重ADC交替模式使用。三重ADC交替模式是针对同一通道的使用三个ADC交叉采集,就是在ADC1采样完等几个时钟周期后ADC2开始采样,此时ADC1处在转换阶段,当ADC2采样完成再等几个时钟周期后ADC3就进行采样此时ADC1和ADC2处在转换阶段,如果ADC3采样完成并且ADC1已经转换完成那么就可以准备下一轮的循环,这样充分利用转换阶段时间达到增快采样速度的效果。AD转换过程见图30-6,利用ADC的转换阶段时间另外一个ADC进行采样,而不用像独立模式必须等待采样和转换结束后才进行下一次采样及转换。第460页共996
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库STM32库开发实战指南-M4:30-ADC—电压采集(4)在线全文阅读。
相关推荐: