下面我们来具体介绍,如何使用DMA来进行ADC操作。
初始化函数包括两部分,DMA初始化和 ADC初始化
我们有多个管理员--DMA 一个管理员当然不止管一个DMA操作。所以DMA有多个Channel
//ADC with DMA Init
#define ADC_Channel ADC_Channel0 #define ADC1_DR_Address ((u32)0x4001244C)
void ADCWithDMAInit() { //DMA init; Using DMA channel 1
DMA_DeInit(DMA1_Channel1); //开启DMA1的第一通道 DMA_InitStruct.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA对应的外设基地址,这个地址走Datasheet查 DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //转换结果的数据大小 DMA_InitStruct.DMA_MemoryBaseAddr = (unsigned long)&ADC_ConvertedValue; // DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式是SRC模式,就是从外设向内存中搬运, DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; //M2M模式禁止,memory to memory,这里暂时用不上,以后介
绍 DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬运的数据尺寸,注意ADC是12位的,
HalfWord就是16位 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable; //接收一次数据后,目标内存地址是否后移--重
要概念,用来采集多个数据的 DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址是否后移 DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //转换模式,循环缓存模式,常用,M2M果果开启了,这个模式失效
。 DMA_InitStruct.DMA_Priority = DMA_Priority_High; //DMA优先级,高 DMA_InitStruct.DMA_BufferSize = 1; //DMA缓存大小,1个 DMA_Init(DMA1_Channel1,&DMA_InitStruct);
// Enable DMA1 DMA_Cmd(DMA1_Channel1, ENABLE); }
void ADCx_Init(unsigned char ADC_Channel) { ADC_DeInit(ADC1); //开启ADC1 ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; //转换模式,为独立转换。转换模式太多了,以后深究 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; //对齐方式,ADC结果是12位的,显然有个对齐左边还是右边
的问题。一般是右对齐 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; //连续转换模式开启 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部出发开关,关闭 ADC_InitStruct.ADC_NbrOfChannel = 2; //开启通道数,2个 ADC_InitStruct.ADC_ScanConvMode = ENABLE; //扫描转换模式开启 ADC_Init(ADC1, &ADC_InitStruct);
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_239Cycles5); //规则组通道设置,关键函数 转
换器ADC1,选择哪个通道channel,规则采样顺序,1到16,以后解释详细含义,最后一个参数是转换时间,越长越准越稳定
// ADC1 to DMA, Enable ADC_DMACmd(ADC1, ENABLE); //ADC命令,和DMA关联。
//ADC1 Enable ADC_Cmd(ADC1,ENABLE); //开启ADC1
//Reset the Calibration of ADC1 ADC_ResetCalibration(ADC1); //重置校准
//wait until the Calibration's finish while(ADC_GetResetCalibrationStatus(ADC1)) //等待重置校准完成 ;
ADC_StartCalibration(ADC1); //开始校准
while(ADC_GetCalibrationStatus(ADC1)) //等待校准完成 ;
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,从选择开始,MCU可以不用管了,ADC将通过DMA不断刷新
制定RAM区 // Attach them; }
最后讲讲滤波算法 滤波的方法以后会开个专题。 特别提一下---没有完美的滤波算法,只有合适的滤波算法。 需要综合考虑信号特点,噪声特点,控制对象等等, 这里用个最简单的滤波算法,均值滤波。 采样16次,取平均值。
//16ms finish a ADC detection // return mv unsigned int ADC_filter(void) { unsigned int result="0"; unsigned char i;
for(i=16;i>0;i--) { Delay_xms(1); result += ADC_ConvertedValue; }
return (unsigned int)(((unsigned long)(result>>4))*3300>>12); }
|
用户1086474 2012-12-8 09:41
用户1642920 2012-7-2 19:14