1、实验目的
1)使用 TIM1 触发 ADC,ADC 采集的数据通过DMA 传至内存,然后通过串口打印出采集的数据;
2)学会 DMA 传输数据并将数据进行保存;
3)验证ADC 的采样率与实际设置的是否相符。
2、硬件资源
1)指示灯
2)ADC
3)DMA
4)TIM
5)杜邦线
3、软件设计
void Adc_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable DMA1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel1); /* 复位DMA1寄存器到缺省状态 */ DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; /* 选择ADC1的数据寄存器作为源 */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Sample.Ch1Buf; /* 目标地址 */ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; /* 设置DMA传输方向,外设(ADC)作为源 */ DMA_InitStructure.DMA_BufferSize = SAMPLE_COUNT; /* 设置缓冲区大小 */ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /* 外设地址不自增 */ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /* 存储器地址需要自增 */ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; /* 选择外设传输单位:16bit */ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; /* 选择内存传输单位:16bit */ DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; /* 无需循环模式 */ DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* 选择DMA优先级 */ DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /* DMA传输类型,不是内存到内存 */ DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Enable DMA1 channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); /* 配置ADC1 */ /* ADCCLK = PCLK2/2 */ RCC_ADCCLKConfig(RCC_PCLK2_Div2); /* ADCCLK = PCLK2/2 = 36MHz */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; /* 连续转换静止 */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3; /* 选择TIM1的CC3做触发 */ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /* 数据右对齐,高位为0 */ ADC_InitStructure.ADC_NbrOfChannel = 1; /* 1个通道 */ ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channels configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5); /* Enable ADC1 external trigger conversion */ ADC_ExternalTrigConvCmd(ADC1, ENABLE); /* 使能 ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* 使能 ADC1 复位校准寄存器 */ ADC_ResetCalibration(ADC1); /* 检测复位校准寄存器 */ while(ADC_GetResetCalibrationStatus(ADC1)); /* 开始 ADC1 校准 */ ADC_StartCalibration(ADC1); /* 等待校准结束 */ while(ADC_GetCalibrationStatus(ADC1)); /* 配置采样触发定时器,使用TIM1 CC1 */ ADC_SampleRate(ADC_Sample.SampleFreq); /* 修改采样频率 */ } /* * Function Name : ADC_SampleRate * Description : 修改ADC的采样频率 * Input : - freq: 采样频率 单位Hz * Output : None * Return : None * Attention : None */ void ADC_SampleRate(uint32_t freq) { /* 配置定时器1第3通道CC3作为ADC1的触发源 */ uint16_t Period; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_Cmd(TIM1, DISABLE); /* 采样频率计算公式 : period = 72000000 / freq ; 1200 == 60KHz 采样频率 */ Period = 72000000 / freq; /* Enable TIM1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = Period; TIM_TimeBaseStructure.TIM_Prescaler = 0; /* 计数频率 = 72000 000 / 18 = 4000 000 */ TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /* TIM1 channel1 configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period / 2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC3Init(TIM1, &TIM_OCInitStructure); /* TIM1 counter enable */ TIM_Cmd(TIM1, ENABLE); /* TIM1 main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); }
由两部分组成:ADC 转换时间 + 定时器的触发需要的时间
4、验证
验证程序是自己通过 DAC 产生一个正弦波,频率为 10KHz,设置ADC的采样频率为900KHz,通过串口打印出来的数据,可以确定一个周期的点数在90个左右,符合要求。