ADC测量电压值
实现目标使用两个按键控制串口的输出和ADC的转换。使用DMA将ADC数据存放在内存中,然后计算对应的电压值。然后由串口1发送至上位机。
主要讲一下对于按键和串口的配置与之前都一样只是在按键的中断函数中添加了控制的内容,控制ADC的转换开始和关闭,控制DMA的开启和关闭,通过标志flag来控制串口打印的内容。
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1) == SET)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
EXTI_ClearITPendingBit(EXTI_Line1);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
DMA_Cmd(DMA1_Channel1,ENABLE);
flag = 1;
}
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13) == SET)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);
EXTI_ClearITPendingBit(EXTI_Line13);
ADC_SoftwareStartConvCmd(ADC1,DISABLE);
DMA_Cmd(DMA1_Channel1,DISABLE);
flag = 0;
}
}
ADC使用DMA的DMA配置
DMA的配置与之前大同小异,首先搞清楚ADC1使用的DMA1的哪一个通道,查阅资料通道1。接下来就是开启时钟,初始化DMADMA_DeInit(DMA1_Channel1);
配置外设的地址(u32)&ADC1->DR
对于传输的大小,注意是半字,不是一个字节。具体的配置如下:
void DMA1_Channel1_Config(void)
{
DMA_InitTypeDef dma_s;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_DeInit(DMA1_Channel1);
dma_s.DMA_BufferSize = 10;
dma_s.DMA_DIR = DMA_DIR_PeripheralSRC;
dma_s.DMA_M2M = DMA_M2M_Disable;
dma_s.DMA_MemoryBaseAddr = (u32)&ADC_Value;
dma_s.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma_s.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_s.DMA_Mode = DMA_Mode_Circular;
dma_s.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;
dma_s.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dma_s.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_s.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1,&dma_s);
DMA_Cmd(DMA1_Channel1,ENABLE);
}
测量电压ADC的配置
ADC的配置中涉及到ADC_InitTypeDef的结构体,结构的每一个成员就是ADC要配置的内容。
- ADC_ContinuousConvMode:ADC是否连续转换
- ADC_DataAlign:数据的对齐方式左对齐或者右对齐
- ADC_ExternalTrigConv:adc转换是否外部触发
- ADC_Mode:adc的模式一般为独立模式
- ADC_NbrOfChannel:adc转换的通道数目
- ADC_ScanConvMode:adc是否开启扫描模式,当多通道扫描时开启
配置完成以后,需要对adc的时钟进行相应的配置。adc的时钟频率越高转换速度越快,但adc时钟有上限值,不能超过14MHz。adc的时钟图如下:
adc转换的时间不仅与时钟有关,还与采样周期有关。每个不同的adc通过都可以设置不同的采样周期。利用库函数ADC_RegularChannelConfig()
来进行配置。函数中四个参数例:
ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5);
第三个参数表示扫描的顺序。例如,通过1,2,3的参数分别为3,2,1的话,扫描顺序为通道3、通道2、通道1.最后一个参数配置本通道的采样周期。adc采样时间计算公式为:T=采样周期+12.5周期。12.5个周期为固定数值。通道的转换时间t=T*1/时钟。
最后就是ADC的自校准:
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1))
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
因为ADC模式设置为软件触发方式,所以可以在任何地方通过函数ADC_SoftwareStartConvCmd(ADC1,ENABLE);
来触发adc开始转换。