STM32 ADC—DMA传输

来源:互联网 发布:hp3055网络打印机驱动 编辑:程序博客网 时间:2024/06/06 20:15

因为规则通道转换的值一直存储在一个仅有的数据寄存器中,所以当转换多个规则通道时需要使用DMA,这可以避免丢失已经存储在ADC_DR寄存器中的数据

例程:
将ADC1的通道4,5,6使用DMA传输
总结
1.DMA外设基地址(DMA_MemoryBaseAddr),当只需要读取一个通道的值时,设置成某一自定义变量的地址;当需要读取多个通道的值时,设成某一自定义数组的地址。地址都是32位——(uint32_t)
例如 u16 RecBuff[3];
DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)RecBuff;

2.DMA传送ADC采样值到定义的数组或者变量,如果需要得到采样值,不需要再使用ADC_GetConversionValue(ADCx);直接用数组或变量转化即可
temp1=(float)RecBuff[0]*(3.3/4096);
3.DMA_DIR_PeripheralDST 外设作为数据传输的目的地;
DMA_DIR_PeripheralSRC 外设作为数据传输的来源
4.ADC 设置成连续转换模式,若是多通道,使能扫描
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
5.ADC为12位,将外设数据宽度和存储器数据宽度设为半字
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

ADC1设置步骤
1)开启端口时钟和ADC1时钟
2)复位ADC1,同时设置ADC分频因子
3)初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息
4)使能ADC并校准
5)配置规则通道参数
6)开启软件转换
//7)使能ADC1的DMA传送

DMA设置步骤
1)使能DMA时钟
2)初始化DMA通道参数
3)使能DMA函数
常用的外设DMA使能函数
USART_DMACmd();
ADC_DMACmd();
DAC_DMACmd();
I2C_DMACmd();
SPIO_DMACmd();
SPI_I2S_DMACmd();
TIM_DMACmd();
4)使能DMA通道,启动传输
5)查询DMA传输状态

代码块(STM32F1)

adc.c//初始化ADC//ADC1规则通道456void Adc_Init(void){    ADC_InitTypeDef ADC_InitStructure;     GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟    RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6,ADC最大时间不能超过14M    //PA4,5,6 作为模拟通道输入引脚                             GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5|GPIO_Pin_6;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_Init(GPIOA, &GPIO_InitStructure);    ADC_DeInit(ADC1);  //复位ADC1     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC工作模式:ADC1和ADC2工作在独立模式    ADC_InitStructure.ADC_ScanConvMode = ENABLE;    //模数转换工作在扫描模式    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  //模数转换工作在连续转换模式    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //ADC数据右对齐    ADC_InitStructure.ADC_NbrOfChannel = 3; //顺序进行规则转换的ADC通道的数目    ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器    ADC_Cmd(ADC1, ENABLE);  //使能指定的ADC1    ADC_ResetCalibration(ADC1); //使能复位校准      while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束    ADC_StartCalibration(ADC1);  //开启AD校准    while(ADC_GetCalibrationStatus(ADC1));   //等待校准结束    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1,ADC_SampleTime_239Cycles5);    ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2,ADC_SampleTime_239Cycles5);    ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 3,ADC_SampleTime_239Cycles5);    ADC_DMACmd(ADC1,ENABLE); //使能ADC1的DMA发送    ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能}dam.c//配置DMA1//从存储器->外设模式/16位数据宽度/存储器增量模式//cpar:外设地址//cmar:存储器地址//cndtr:数据传输量void MYDMA_Config(u32 cpar,u32 cmar,u16 cndtr){    DMA_InitTypeDef DMA_InitStructure;    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输时钟    DMA_DeInit(DMA1_Channel1);   //将DMA的通道1寄存器重设为缺省值    DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设基地址    DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //数据传输方向,从外设发送到内存    DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在循环模式    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输    DMA_Init(DMA1_Channel1, &DMA_InitStructure);     DMA_Cmd(DMA1_Channel1, ENABLE);}//得到转换值if(DMA_GetFlagStatus(DMA1_FLAG_TC1)!=RESET){     temp1=(float)RecBuff[0]*(3.3/4096);     temp2=(float)RecBuff[1]*(3.3/4096);     temp3=(float)RecBuff[2]*(3.3/4096);     DMA_ClearFlag(DMA1_FLAG_TC1); //清除通道1传输完成标志}
0 0
原创粉丝点击