精华内容
下载资源
问答
  • MCU:STM32F303VC,在SPI通信中,可以同时开启发送和接收DMA请求,自动数据的发送和接收,完成数据的交换。
  • STM32 HAL库之DMA模式ADC

    2021-01-06 08:28:54
    HAL_ADC_Init() 用户自行调用 加载ADC属性 //ADC句柄声明 ADC_HandleTypeDef AdcHandle; AdcHandle.Instance = ADC1; AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; AdcHandle.Init.LowPowerAutoWait ...
  • STM32 通道ADC采集详解(DMA模式和非DMA模式

    万次阅读 多人点赞 2018-10-26 19:06:20
    ADC相关问题: 1.采集到的值如何转化计算? STM32系列芯片大都是12位只有少部分是16位的,如:F373芯片。 12位分辨率意味着我们采集电压的精度可以达到:Vref / 4096。...扫描模式用于通道...

    ADC相关问题:

    1.采集到的值如何转化计算?

      STM32系列芯片大都是12位只有少部分是16位的,如:F373芯片。

      12位分辨率意味着我们采集电压的精度可以达到:Vref / 4096。

       采集电压= Vref * ADC_DR / 4096;

       VREF:参考电压

       ADC_DR:读取到ADC数据寄存器的值
     

    2.什么是通道扫描模式?

    扫描模式用于多通道采集时,一轮采集为根据通道设定的顺序依次采集每个开启的通道。但要注意的是每个通道采集到的值都是存放在寄存器ADCx-> DR中,而只有当一轮采集完即所有设定的通道都采集完后采集完成标志才会被置位,所以不使用DMA传输方式的时候会出现采集到的数据被覆盖的现象。

     

    3.采集周期,转换周期

    转换时间=采样时间+12.5个时钟周期;

    采样时间根据ADC_RegularChannelConfig()配置。

    4.连续转换模式

    将所有开启的通道采集转换完一轮后自动开启下一轮的采集转换。

    5.一次采集完成后会触发中断吗?

    ADC使能中断的话当通道规则组都采集转化完成一轮后会产生中断ADC1_2_IRQHandler(void)

    6.规则组跟注入组

    规则组是程序按照配置规则转换,注入组是根据外部触发中断来转换,在执行规则通道组扫描转换时,如有例外处理则可启用注入通道组的转换。

    DMA相关问题:

    1.什么是DMA循环模式?

    完成一轮DMA传输后自动开启下一轮传输。

    2.怎么算一轮DMA传输完成?

    3.ADC怎么触发DMA?

    传输请求函数触发

    例如:

    ADC_DMACmd(ADC1,Enable); 

    4.DMA有哪些传输方向?

    内存  到  内存

    内存  到  外设

    外设  到  内存

    5.DMA传输会触发哪些中断?

     


    以下为ADC多通道采集(非DMA模式和DMA模式)的示例


    非DMA模式(配置16个通道)

    void adc_gpio_init(void)
    {
        GPIO_InitTypeDef t_gpio;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);//使能 GPIOA GPIOB GPIOC 时钟
        t_gpio.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//GPIOA
        t_gpio.GPIO_Mode=GPIO_Mode_AIN;//模拟输入模式
        GPIO_Init(GPIOA,&t_gpio);//初始化GPIOA
        
        t_gpio.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;//GPIOB 
        GPIO_Init(GPIOB,&t_gpio);//初始化GPIOB
        
        t_gpio.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//GPIOC  
        GPIO_Init(GPIOC,&t_gpio);//初始化GPIOC      
    }
    
    
    void adc_init(void)
    {
        ADC_InitTypeDef t_adc;
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//使能ADC1时钟 
        
        t_adc.ADC_Mode = ADC_Mode_Independent;               //独立模式:ADC1与ADC2独立
        t_adc.ADC_ScanConvMode = DISABLE;                      //禁用通道扫描
        t_adc.ADC_ContinuousConvMode = DISABLE;                //禁用连续转换
        t_adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发
        t_adc.ADC_DataAlign = ADC_DataAlign_Right;             //数据位右对齐
        t_adc.ADC_NbrOfChannel = 1;                            //转换通道数为1
        ADC_Init(ADC1,&t_adc);                                 //初始化ADC1
        
        RCC_ADCCLKConfig(RCC_PCLK2_Div8);//配置ADC时钟为PCLK2的8分频
     
        ADC_Cmd(ADC1,ENABLE); //使能ADC1
            
        ADC_ResetCalibration(ADC1);          
        while(ADC_GetResetCalibrationStatus(ADC1));     
        ADC_StartCalibration(ADC1); //校准
        while(ADC_GetCalibrationStatus(ADC1)){}; 
    }
    
    uint16_t read_adc_value(uint8_t ch)
    {
        uint16_t adc_value = 0;
        
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_7Cycles5 );   //设置ADC1通道ch的转换周期为7.5个采样周期,采样次序为1
    
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能软件触发
        
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )){};//等待转换完成
            
        adc_value = ADC_GetConversionValue(ADC1); //获取转换值
      
        return adc_value;
    }

    DMA模式

     

    ADC配置(配置4个通道)

    void ADC_Multichannel_Config(void)
    {
        ADC_InitTypeDef  ADC_InitStructure; 
        
        ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值
        
        /* ADC1 configuration ------------------------------------------------------*/ 
        
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode =ENABLE; //ADC为扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //ADC为连续转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发转换关闭
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 
        ADC_InitStructure.ADC_NbrOfChannel = 4; //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
        
        /* ADC1 regular channel11 configuration */ 
        //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
        //ADC1,ADC通道x,规则采样顺序值为y,采样时间为239.5周期
        
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_239Cycles5 );
        ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 4, ADC_SampleTime_239Cycles5);
        // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)     
        ADC_DMACmd(ADC1, ENABLE); 
        /* Enable ADC1 */    
        ADC_Cmd(ADC1, ENABLE);    //使能指定的ADC1
         /* Enable ADC1 reset calibaration register */      
        ADC_ResetCalibration(ADC1);  //复位指定的ADC1的校准寄存器 
        
        /* Enable ADC1 reset calibaration register */      
        ADC_ResetCalibration(ADC1);  //复位指定的ADC1的校准寄存器 
        /* Start ADC1 calibaration */
        ADC_StartCalibration(ADC1);  //开始指定ADC1的校准状态 
        /* Check the end of ADC1 calibration */
        while(ADC_GetCalibrationStatus(ADC1)); 
        //获取指定ADC1的校准程序,设置状态则等待
    }
    

    DMA配置(ADC1传输到内存变量ADC_Value)

    void DMA_Configuration(void) 
    {
        /* ADC1  DMA1 Channel Config */  
        DMA_InitTypeDef DMA_InitStructure;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA时钟
    
        DMA_DeInit(DMA1_Channel1);   //将DMA的通道1寄存器重设为缺省值:ADC1连接DMA通道1
        DMA_InitStructure.DMA_PeripheralBaseAddr =  (u32)&ADC1->DR;  //DMA外设ADC基地址
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_Value;      //DMA内存基地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //内存作为数据传输的目的地
        DMA_InitStructure.DMA_BufferSize = N*4;  //此值为完整一轮DMA传输的次数
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据位宽度16位,即DMA传输尺寸
        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_InitStruct中参数DMA通道
    }
    

     

    展开全文
  • ADC规则组通道转换时,只能读取到最后一个通道的数据,因此ADC的通道转换天生适合DMA模式,当每个通达转换完毕后,发送DMA请求,通过DMA直接传输到设定的内存缓存区中,从而解决了ADC通道转换数据被覆盖的问题...
  • STM32L151,HAL库,ADC通道使用DMA中断传输,解决ADC通道错乱问题。OLED显示,STM32 stop低功耗模式
  • 本文使用ADC转换电位器输出的电压值,并用DMA模式传输转换的结果,每8次采样转换取平均值,做一个简单的数字滤波。
  • DMA发送模式 线程循环查询发送环形缓冲区数据,然后启动MDA传输 DMA传输完成中断,连续发送 定时器中断周期发送 DMA接收模式 DMA缓存半满中断(如CPU硬件支持,可使用DMA双缓存机制) DMA缓存传输完成中断 串口空闲...
  • 一、非DMA模式(转)  说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/article/details/70227385,下面第二部分我会...

     

    一、非DMA模式(转)

      说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/article/details/70227385,下面第二部分我会补充自己的DMA模式的方法。

      Stm32 ADC 的转换模式还是很灵活,很强大,模式种类很多,那么这也导致很多人使用的时候没细心研究参考手册的情况下容易混淆。不知道该用哪种方式来实现自己想要的功能。网上也可以搜到很多资料,但是大部分是针对之前老版本的标准库的。昨天帮客户解决这个问题,正好做个总结:使用stm32cubeMX配置生成多通道采集的例子。

    软件:STM32Cumebx  MDK

    硬件:eemaker板(基于stm32F103c8的)

    在百度搜索ADC多通道采集,大部分的都是基于采用dma模式才实现的。而我讲的使用非dma方法。首先有几个概念要搞清楚:

      扫描模式(想采集多通道必须开启):是一次对所选中的通道进行转换,比如开了ch0,ch1,ch4,ch5。Ch0转换完以后就会自动转换通道0,1,4,5直到转换完。但是这种连续性并不是不能被打断。这就引入了间断模式,可以说是对扫描模式的一种补充。它可以把0,1,4,5这四个通道进行分组。可以分成0,1一组,4,5一组。也可以每个通道配置为一组。这样每一组转换之前都需要先触发一次。

      Stm32 ADC的单次模式和连续模式。这两中模式的概念是相对应的。这里的单次模式并不是指一个通道。假如你同时开了ch0,ch1,ch4,ch5这四个通道。单次模式转换模式下会把这四个通道采集一边就停止了。而连续模式就是这四个通道转换完以后再循环过来再从ch0开始。

      另外还有规则组和注入组的概念,因为我这个例程只用到了规则组,就不多介绍这两个概念,想要弄清楚请自行查阅手册。

    下面进入正题,配置stm32cubeMX。

    Stm32cubeMx配置ADC多通道采集

    先使能几个通道,我这里设置为0、1、4、5.

    然后就要配置ADC的参数:

    Stm32cubeMx配置ADC多通道采集

      目前经过我的测试,要想用非dma和中断模式只有这样配置可以正确进行多通道转换:扫描模式+单次转换模式+间断转换模式(每个间断组一个通道)。

      分析配置成这样的模式,扫描模式是在配置为多个通道必须打开的,stm32cubeMX上也默认好了,只能enable。单次转换模式是我不需要不停的去采集每个通道值,而是把四个通道采集完以后就让它停止。这里间断配置是关键,间断模式可以让扫描的四个通道进行分成四个组,stm32cubeMX参数里面number of Discontinous Conversions是配置间断组每个组有几个通道的,这里必须配置为1(否则在获取ad值得时候只能读取到每个间断组最后一个通道)。

    生成mdk工程代码。这时候还没有完成,只是实现了ADC的初始化,需要采集这四个通道值得函数还要自己写。下面这个是我main函数的while循环:

    for(i=1;i<5;i++)
    
    {
    
    HAL_ADC_Start(&hadc1);
    
    HAL_ADC_PollForConversion(&hadc1,0xffff);//等待ADC转换完成
    
    adcBuf[i]=HAL_ADC_GetValue(&hadc1);
    
    printf("------ch:%d--%d-------\r\n",i,adcBuf[i]);
    
    }
    
    HAL_ADC_Stop(&hadc1);
    
    HAL_Delay(1000);

      调用hal库接口函数也需要注意,HAL_ADC_Start一定要放在for里面,即每一个通道都要触发。四个通道都采集完了,再去调用HAL_ADC_Stop(&hadc1);结束本次ADC采集。

     

    二、DMA模式

      下面就是我自己的DMA模式的ADC多通道转换了。

      先配置一些ADC的基本配置:

      引脚

     

      时钟

      这个时钟可以结合ADC设置里配置的采样时间结合计算出ADC转换的时间,进而换算出频率。

      接着配置DMA

      ADC是12位的,其实DMA只需要用Half Word就可以了,但实际中HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
    该函数中pData为32位的,也就是DMA必须配置为Word才可以。

     配置ADC基本设置 

      这里要注意选择对不同的通道,一开始我就是没留意到这个问题,就只有一个通道 Channel10 在转换,后来查看就是Rank1、2、3全配置成  Channel10 了,所以只有这个通道在转换,这里这个提醒大家注意一下。

      中断配置

      最后在main文件的main函数里的while循环里加入下面代码

    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&AD_DMA, 5); //启用DMA的ADC转换,AD_DMA 0~3 对应ADC 0~3,这里注意最后一个参数的大小
    printf("AD_DMA_0 = %d\r\n",AD_DMA[0]);
    printf("AD_DMA_1 = %d\r\n",AD_DMA[1]);
    printf("AD_DMA_2 = %d\r\n",AD_DMA[2]);
    HAL_Delay(500);

      注意:在while循环前要加ADC校准

        HAL_ADCEx_Calibration_Start(&hadc1);    //AD校准

      串口打印结果如下,至于怎样串口打印这里就不多说了,想知道的可以看https://www.cnblogs.com/xingboy/p/9522940.html

       

    补充:使用定时器与DMA中断定时采集

      上面只是单纯的一直采集的,如果想要用到中断的话就可以按下面的方式来,ADC配置跟上面说的DMA模式一样:

      先配置定时器中断,怎么配置可以参考我的另一个文章https://www.cnblogs.com/xingboy/p/9897500.html

      接着在 main 函数的 while 循环前打开定时器中断

        HAL_TIM_Base_Start_IT(&htim3); //启动定时器中断

      然后重写定时器中断回调函数

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
        HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&AD_DMA, 5); //启用DMA的ADC转换,AD_DMA 0~3 对应ADC 0~3,这里注意最后一个参数的大小
    }

      这里要注意了,我调试的时候发现HAL_ADC_Start_DMA()函数中最后一个参数的大小起码要比你定义的AD_DMA数组大2,不过不能大于2倍,前面的使用这个函数的时候也是要这样,数据太小,会导致后面的AD通道采集不了数据,大于2倍程序会一直卡住,至于为什么这样子我也还没搞懂,知道的可以告诉我一声。【补充:关于这个参数大小的问题,我查了一些资料,一般ADC每次读进来的数据都是2个字节大小的半字,所以3个通道读进来的一般一次6个字节这样,4个通道类似,而这里的最后一个参数代表的就是要传输的字节数,所以这个参数要根据通道个数设置,通常ADC读入一个半字,也就是uint16_t,你设为Word,那么会去读一个uint32_t是4个字节,其实这个我也还不是很懂,不知道对不对的欢迎大家指出

      最后写DMA中断服务函数

    void DMA1_Channel1_IRQHandler(void)
    {
      /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
        
        /*自己添加代码部分*/
        HAL_ADC_Stop_DMA(&hadc1); //停止DMA的ADC转换,AD_DMA 0~3 对应ADC 0~3
        HAL_TIM_Base_Stop_IT(&htim3);//关闭定时器
        printf("AD_DMA_0 = %d\r\n",AD_DMA[0]);
        printf("AD_DMA_1 = %d\r\n",AD_DMA[1]);
        printf("AD_DMA_2 = %d\r\n",AD_DMA[2]);
        HAL_TIM_Base_Start_IT(&htim3); //重新开启定时器
        
      /* USER CODE END DMA1_Channel1_IRQn 0 */
      HAL_DMA_IRQHandler(&hdma_adc1);
      /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
        //__HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc1)); //清楚标志位
      /* USER CODE END DMA1_Channel1_IRQn 1 */
    } 

      这样子,就可以实现1S采集多少次ADC了,而不用单纯控制采样频率来控制1S的ADC采集次数了,个人觉得单纯控制采样频率比较难算。

    补充:单通ADC采集参考:https://www.cnblogs.com/xingboy/p/10018749.html

     

     补充一个 4 通道采集 DMA 模式:

      

      

      

      

      

           定义一个数组存放DMA数据

    uint16_t AD_DMA[4];

      直接在 main 函数的 while 前面开启 ADC校验跟采集

    HAL_ADCEx_Calibration_Start(&hadc1);              //AD校准
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&AD_DMA, 8); //启用DMA的ADC转换,AD_DMA 0~3 对应ADC 0~3  

      while函数里打印DMA的值

            printf("AD0 = %d\r\n",AD_DMA[0]);
            printf("AD1 = %d\r\n",AD_DMA[1]);
            printf("AD2 = %d\r\n",AD_DMA[2]);
            printf("AD3 = %d\r\n",AD_DMA[3]);
            HAL_Delay(1000);

      打印结果如下

        

     

     

     

     

     

      

    转载于:https://www.cnblogs.com/xingboy/p/10212308.html

    展开全文
  • 本资源通过STM32F103对内置ADC进行配置,12个通道通过DMA进行数据采集,并通过LCD显示
  • STM32CubeMX实现DMA模式下的AD转换
  • 本文主要对stm32 ad双通道dma模式进行了简要说明,希望对你的学习有所帮助。
  • 今天尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了。
  • 本程序实现STM32 DMA中断模式下ADC通道数据采集,并经过简单的均值滤波,亲测可用。 若有错误之处,希望读者指出,大家共同学习,一起进步!
  • ADC DMA模式.rar

    2021-05-14 15:52:55
    使用DMA来配置ADC
  • stm32ADC的DMA模式

    千次阅读 2019-03-11 23:21:12
     //每次传输大小16位,使用DMA循环传输模式  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValue;//数据缓冲区的地址 ...

    //变量定义

    __IO uint16_t ADCConvertedValue[10];

    //ADC 外设的数据寄存器

    #define ADC1_DR_Address    ((uint32_t)0x4001244C)

    //ADC_DR(ADC规则数据寄存器),偏移量=0x4c  ADC1(0x40012400-0x400127ff)

    //ADC1_GPIO配置

    void ADC1_GPIO_Configuration(void)

    {

      GPIO_InitTypeDef GPIO_InitStructure;

      /* Configure PC.01 (ADC Channel11) as analog input -------------------------*/

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;        

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //adc模式必须是模拟输入

      GPIO_Init(GPIOC, &GPIO_InitStructure);//执行上面的操作

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;        

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //adc模式必须是模拟输入

      GPIO_Init(GPIOA, &GPIO_InitStructure);//执行上面的操作

      //注意,内部温度对应 16通道,无引脚,只需开启adc时钟即可。

      //内部参考电压,对应17 通道。无引脚。只需开启时钟

    }

    //============================================================================================

    //外设ADC,DMA时钟开启

     void ADC1_DMA_RCC_Configuration(void)

    {

      /* Enable peripheral clocks ------------------------------------------------*/

      /* Enable DMA1 clock */

      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

      /* Enable ADC1 and GPIOC clock */

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC| RCC_APB2Periph_GPIOA, ENABLE);

    }

    //===============================================================================================

    //ADC1  DMA 配置

    void ADC1_DMA_Init(void)

    {

    ADC_InitTypeDef ADC_InitStructure;

    DMA_InitTypeDef DMA_InitStructure;

    /* DMA1 channel1 configuration ----------------------------------------------*/

      DMA_DeInit(DMA1_Channel1); //选择DMA的通道1

      //设定从ADC外设的数据寄存器(ADC1_DR_Address)转移到内存(ADCConcertedValue)

      //每次传输大小16位,使用DMA循环传输模式

      DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

      DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValue;//数据缓冲区的地址

      //外设为数据源

      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

      //数据缓冲区,大小2半字

      DMA_InitStructure.DMA_BufferSize = 10;

      // 外设地址固定

      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

      //内存地址增加,多组adc时,使能,数据传输时,内存增加

      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

      //半字

      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

      //DMA循环传输

      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

      //优先级高

      DMA_InitStructure.DMA_Priority = DMA_Priority_High;

      //??

      DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

      //执行

      DMA_Init(DMA1_Channel1, &DMA_InitStructure); 

      /* Enable DMA1 channel1 */

      DMA_Cmd(DMA1_Channel1, ENABLE); 

      /* ADC1 configuration ------------------------------------------------------*/

      //ADC独立模式         相对于双重模式

      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

      //扫描模式用于多通道采集

      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_InitStructure.ADC_NbrOfChannel =10;

      //执行

      ADC_Init(ADC1, &ADC_InitStructure); 

      //配置ADC时钟,为PCLK2的8分频,即9Hz

      RCC_ADCCLKConfig(RCC_PCLK2_Div8);

      /* ADC1 regular channel11 configuration */

      //配置ADC1的通道11为55.5个采样周期

      //默认组,adc1 ,通道11,排序为1,55.5周期

      //ADC1,ch17,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_17,1, ADC_SampleTime_239Cycles5);

      //ADC1,ch16,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_16,2, ADC_SampleTime_239Cycles5);

      //ADC1,ch4,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_4,3, ADC_SampleTime_239Cycles5);

      //ADC1,ch5,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_5,4, ADC_SampleTime_239Cycles5);

      //ADC1,ch6,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_6,5, ADC_SampleTime_239Cycles5);

      //ADC1,ch7,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_7,6, ADC_SampleTime_239Cycles5);

      //ADC1,ch10,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_10,7, ADC_SampleTime_239Cycles5);

      //ADC1,ch11,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_11,8, ADC_SampleTime_239Cycles5);

      //ADC1,ch12,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_12,9, ADC_SampleTime_239Cycles5);

      //ADC1,ch13,序号1,55.5.。。

      ADC_RegularChannelConfig(ADC1, ADC_Channel_13,10, ADC_SampleTime_239Cycles5);

      //----------------------使能温度传感器----------------------------

      ADC_TempSensorVrefintCmd(ENABLE);

      /* Enable ADC1 DMA */

      //使能ADC_DMA

      ADC_DMACmd(ADC1, ENABLE); 

      /* Enable ADC1 */

      //使能ADC

      ADC_Cmd(ADC1, ENABLE);

      /* Enable ADC1 reset calibration register */

      //使能ADC1的复位校准寄存器 

      ADC_ResetCalibration(ADC1);

      /* Check the end of ADC1 reset calibration register */

      //等待校准完成

      while(ADC_GetResetCalibrationStatus(ADC1));

      /* Start ADC1 calibration */

      //使能ADC1的开始校准寄存器

      ADC_StartCalibration(ADC1);

      /* Check the end of ADC1 calibration */

      //等待完成

      while(ADC_GetCalibrationStatus(ADC1));    

      /* Start ADC1 Software Conversion */

      //使用软件触发,由于没有采用外部触发

      ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    }

     

    展开全文
  • PIO模式和DMA模式的区别

    千次阅读 2019-06-11 17:40:32
    硬盘和内存之间数据传送的两种方式:一是PIO模式,二是DNA... DMA模式下,CPU并不全程参与数据的传送工作,只需下达命令即可。DMA方式下有控制器和通道,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送...

            硬盘和内存之间数据传送的两种方式:一是PIO模式,二是DNA模式

            PIO模式下通过CPU来控制硬盘和内存之间的数据传输,是一种通过CPU执行I/O端口指令来进行数据的读写的数据交换模式。;

            DMA模式下,CPU并不全程参与数据的传送工作,只需下达命令即可。DMA方式下有控制器和通道,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率。DMA模式与PIO模式的区别就在于,DMA模式不过分依赖CPU,可以大大节省系统资源,二者在传输速度上的差异并不十分明显。DMA模式又可以分为Single-Word DMA(单字节DMA)和Multi-Word DMA(多字节DMA)两种,其中所能达到的最大传输速率也只有16.6MB/s。

            DMA需要传送数据时和程序中断来临时先处理哪一个?

            DMA 传送方式的优先级高于程序中断,两者的区别主要表现在对CPU的干扰程度不同。程序中断请求不但使CPU停下来,而且要CPU执行中断服务程序为中断请求服务,这个请求包括了对断点和现场的处理以及CPU与外设的传送,所以CPU付出了很多的代价;DMA请求仅仅使CPU暂停一下,不需要对断点和现场的处理,并且是由DMA控制外设与主存之间的数据传送,无需CPU的干预,DMA只是借用了一点CPU的时间而已。还有一个区别就是,CPU对这两个请求的响应时间不同,对程序中断请求一般都在执行完一条指令的时钟周期末尾响应,而对DMA的请求,由于考虑它的高效性,CPU在每条指令执行的各个阶段之中都可以让给DMA使用,是立即响应。 DMA主要由硬件来实现,此时高速外设和内存之间进行数据交换不通过CPU的控制,而是利用系统总线。DMA方式是I/O系统与主机交换数据的主要方式之一,另外还有程序查询方式和中断方式。

    展开全文
  • STM32 DMA 循环模式DMA_Mode_Circular详解

    千次阅读 2021-08-09 18:19:10
    目前在网上还没看到详细讲解DMA循环模式的文章,参考手册中只有简单的一段话。仅靠这么一段话,不一定对DMA模式有深入的了解。本文详细阐述了DMA普通模式与循环模式,相信可以加深你对DMA的理解。
  • 非常高效的代码移植功能,利用STM32F103的DMA模式进行数据发送操作
  • stm32 nucleo cube生成 usart+dma+pwm输入模式 代码,完整版,里边还有外部中断的排至,没有注销,分享出来。 usart_tx + dma, pwm输入模式 + DMA ,上传的文件名与功代码能不符,看好。
  • 利用STM32内的DMA方式实现ADC的三路数据采集
  • void ADC_Volt_Detect_Config() { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure;... DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; ADC_Common...
  • 研究一种基于片上可编程系统(SoPC)技术的视频数据传输方案。该方案自定制了一个四口SDRAM控制器,并将其中的两口设计成符合流模式传输规范的接口,作为一个SoPC外设挂在Avalon总线上,方便重复使用。
  • stm32通道ADC非DMA程序

    热门讨论 2014-05-23 17:46:05
    stm32通道ADC非DMA程序
  • 硬盘DMA模式和PIO模式

    千次阅读 2018-03-13 11:41:44
    硬盘DMA模式和PIO模式 DMA的英文拼写是“Direct Memory Access”(存储器直接访问)。这是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据,既不通过CPU,也不需要CPU干预。整个数 据传输操作在...
  • ADC规则组通道转换-DMA模式

    千次阅读 2018-11-11 16:49:33
    直接存储器存取技术(Direct Memory Access)简称DMADMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省CPU的资源可以做...
  • STM32F1uartDMA模式任意长度接收发送
  • xilinx fpga PCIe IP核DMA传输参考代码。
  • STM32 DMA模式ADC通道采集

    千次阅读 2018-11-08 17:34:06
    ADC通道采集时,采集转换之后数据会自动赋给我们传进去的参数ADC_ConvertedValue,然后进行下一个通道或者下一次的数据采集转换。   采集周期太快会出现采集数据失败的情况,所以在不影响使用的情况下ADC...
  • UART5_DMA_Rx.rar

    2019-12-14 11:15:47
    STM32F407串口DMA接收测试工程 测试方法:PC串口工具发送10字节(固定字节数)数据,并返回数据到串口助手
  • 也就是说,在循环模式下,当DMA传输了一个数据,DMA_CNDTRx传输数量寄存器相应减一,当DMA_CNDTRx传输数量寄存器减为0时,DMA_CNDTRx寄存器将恢复为相应的初始值,不用软件干预,那么,这不就是循环队列的方式吗?

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,277
精华内容 16,910
关键字:

多字dma模式