对于F4ADC配置有几点疑问希望大家帮忙解答一下:
问题1:这个表的意思是否是说明F4在供电电压大于2.4V时其最大时钟是36MHZ?当其时钟在30MHZ时,外部触发采样频率最大为1764KHZ?
如果上面这个问题是对的话,那么对于库函数的几项操作有点疑问:
这个说明给出了ADC转换时间的计算方式,那么对应的我配置如下:
//ADC时钟为APB2的4分频->84/4=21MHZ(F407ADC在2.4-3.6V供电电压下最大速率36M,稳定速度为30M)
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;
//配置ADC1规则组(得出其单次采样时间为->(3+12)/21≈0.7us)
ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_3Cycles);
//两次采样的间隔时间为5个ADC时钟周期(5/21≈0.24us)
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
问题2:按照如上数据理论值计算其最大采样频率:0.7+0.24≈1us->1MHZ,是否是这样计算的?
问题3:我想用ADC+DMA+TIM触发的方式来做一个简易的示波器,方法就是通过TIM的定时触发ADC采样,将采样值装入DMA缓存中,DMA装满后触发LCD刷新程序。
有一个概念我不是很清楚,比如我一屏采100个点,要能显示400HZ的正弦信号,是不是说我ADC采样速率至少要100*400=40KHZ的速率呢?
补充内容 (2017-5-12 17:49):
更正一个几年前的错误,
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
此项配置仅仅用于双重或三重交错模式下才有效,也就是说之前的计算是错误的
[mw_shl_code=c,true]#define ADC1_DR_Address ((uint32_t)ADC1_BASE+0x4c) __IO uint16_t ADC1OscConver[1000]; /* 功能:配置adc1IO口 */ static void Adc1IoConfig(void) { /* IO口配置 */ GPIO_InitTypeDef GPIO_InitStructure; //开C口时钟, RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //复位配置 GPIO_StructInit(&GPIO_InitStructure); //设置为模拟输入模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //不带上拉 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //将以上设置应用于寄存器 GPIO_Init(GPIOC,&GPIO_InitStructure); } /* 功能:tim2触发器初始化 */ static void Tim2Config(void) { /* tim配置 */ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //打开TIM时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //初始化配置结构,不受其它配置干扰 TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure); //对APB1时钟不分频,由system_stm32f4xx.c可知 //APB1=AHB/4=SYSCLK/4=168M/4=42M,则TIM3=APB1*2=84M TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //分频值=168M/(Prescaler+1)/2=0.5us TIM_TimeBaseInitStructure.TIM_Prescaler=42-1; //溢出时间确定 TIM_TimeBaseInitStructure.TIM_Period=44; //向上计数方式 TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //将以上配置应用于定时器 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); //数据更新作为触发源 TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update); } /* 功能:ADC1的示波器功能配置 备注:使用tim2做触发 */ void Adc1OscConfig(void) { /* dma配置 */ DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //开启MDA2时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //初始化各寄存器配置 DMA_DeInit(DMA2_Stream0); DMA_StructInit( &DMA_InitStructure); //选取DMA通道0,数据流0 DMA_InitStructure.DMA_Channel=DMA_Channel_0; //数据传入地址->ADC基地址加上DR寄存器偏移地址 DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)ADC1_DR_Address; //数据送入地址 DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)ADC1OscConver; //数据传送方向为外设到SRAM DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory; //数据缓冲区1 DMA_InitStructure.DMA_BufferSize=1000; //外设地址固定 DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //内存地址自增 DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //数据类型为半字 DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//DMA_PeripheralDataSize_Byte;//DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//DMA_MemoryDataSize_Byte;//DMA_MemoryDataSize_HalfWord; //循环传输 DMA_InitStructure.DMA_Mode=DMA_Mode_Circular; //高优先级 DMA_InitStructure.DMA_Priority=DMA_Priority_Low; //不使用FIFO模式 DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single; // DMA_DoubleBufferModeCmd(DMA2_Stream0, DISABLE); //将以上设置应用于DMA2,通道0,数据流0 DMA_Init(DMA2_Stream0,&DMA_InitStructure); //使能DMA DMA_Cmd(DMA2_Stream0, ENABLE); //选择DMA2通道数据流0 NVIC_InitStructure.NVIC_IRQChannel=DMA2_Stream0_IRQn;//DMA2_Stream0_IRQHandler; //抢占式优先级为0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //响应式优先级为12 NVIC_InitStructure.NVIC_IRQChannelSubPriority=4; //通道使能 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //将以上配置应用于NVIC NVIC_Init(&NVIC_InitStructure); //使能DMA传输完成中断 DMA_ITConfig(DMA2_Stream0,DMA_IT_TC,ENABLE); /* 功能:ADC配置 */ ADC_InitTypeDef ADC_InitStructure; //开启ADC1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //12位转换精度 ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//ADC_Resolution_8b;//ADC_Resolution_12b; //使用单通道转换模式 ADC_InitStructure.ADC_ScanConvMode=DISABLE; //不使用多次转换模式 ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//ENABLE;//DISABLE; //使用外部上升沿触发模式 ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_Rising;//ADC_ExternalTrigConvEdge_Rising;//ADC_ExternalTrigConvEdge_None; //TIM3溢出触发 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;//ADC_ExternalTrigConv_T1_CC1; //选择右对齐方式 ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; //选用转换通道数为1个 ADC_InitStructure.ADC_NbrOfConversion=1; //将以上设置应用于对应寄存器 ADC_Init(ADC1,&ADC_InitStructure); //使能ADC在DMA模式下的连续转换 ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE); //使能ADC的DMA模式 ADC_DMACmd(ADC1,ENABLE); //配置ADC1规则组(得出其单次采样时间为3+12)/21≈0.7us)->12bit ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_3Cycles);//ADC_SampleTime_3Cycles/ADC_SampleTime_480Cycles //使能ADC ADC_Cmd(ADC1,ENABLE); } /* 功能:各ADC共同功能配置 */ static void AdcSenCommConfig(void) { ADC_CommonInitTypeDef ADC_CommonInitStructure; //ADC为独立模式 ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent; //ADC时钟为APB2的2分频->84/4=21MHZ(F407ADC在2.4-3.6V供电电压下最大速率36M,稳定速度为30M) ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div8; //使用ADC的DMA复用 ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_2; //两次采样的间隔时间为5个ADC时钟周期(5/21≈0.24us) ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles; //将以上设置应用于对应的寄存器 ADC_CommonInit(&ADC_CommonInitStructure); } /* 功能:开始ADC1示波器采样 */ void StartAdc1OscSam(void) { TIM_Cmd(TIM2, ENABLE); } /* 功能:停止ADC1示波器采样 */ void StopAdc1OscSam(void) { TIM_Cmd(TIM2, DISABLE); }[/mw_shl_code]
如果要切换采样时间,可以:
[mw_shl_code=c,true]#define OSC_TIME(val) TIM_SetCounter(TIM2,0);TIM_SetAutoreload(TIM2,val)[/mw_shl_code]
为什么要开中断,来使能DMA传输完成?开中断有什么意义?
一周热门 更多>