当前位置:   article > 正文

STM32——DMA笔记_dma外设adc基地址

dma外设adc基地址

一、DMA是什么

DMA 传输将数据从一个 地址空间复制到另外一个地址空间。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的 内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工 作。DMA 传输方式无需 CPU 直接 控制传输,通过硬件为 RAM 与 I/O 设备 开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。

二、DMA的作用

“搬运”,将外部数据搬运进MCU,这件事不需要CPU去做,CPU可以去处理别的事情。

 三、DMA1的通道对应的“搬用源”

四、DMA的相关配置

 其中主要配置前三个标红的框,第四个紫色框根据一次搬运的长度选择,有一个8位、16位、32位。

u16 ADC1_Value[C_Channel_Sample][C_ADC_Channel] = { 0 };    // DMA搬运数据存放处(数组)

DMA的配置:

  1. void DMA_Init_JX(void)
  2. {
  3. DMA_InitTypeDef DMA_InitStructure;
  4. //NVIC_InitTypeDef NVIC_InitStructure;
  5. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA时钟
  6. // DMA_CH1(ADC1)参数设置
  7. //--------------------------------------------------------------------------------------------------------------------------
  8. DMA_DeInit(DMA1_Channel1); // 将DMA的通道1寄存器重设为缺省值
  9. DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; // DMA外设ADC基地址
  10. DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC1_Value; // DMA内存基地址
  11. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 内存作为数据传输的目的地
  12. DMA_InitStructure.DMA_BufferSize = C_ADC_Channel * C_Channel_Sample; // DMA通道的DMA缓存的大小
  13. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址寄存器不变
  14. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址寄存器递增
  15. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 数据宽度为16
  16. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 数据宽度为16
  17. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 工作在循环缓存模式
  18. DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道 x拥有高优先级
  19. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // DMA通道x没有设置为内存到内存传输
  20. DMA_Init(DMA1_Channel1, &DMA_InitStructure); // 根据DMA_InitStruct中指定的参数初始化DMA的通道
  21. //--------------------------------------------------------------------------------------------------------------------------
  22. DMA_Cmd(DMA1_Channel1, ENABLE); // 启动DMA通道
  23. }

ADC通道的配置:

  1. void ADC1_Rocker_Init(void)
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. ADC_InitTypeDef ADC_InitStructure;
  5. // NVIC_InitTypeDef NVIC_InitStructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE); // 使能PA端口和ADC1时钟
  7. // 模拟输入:PA1、PA2、PA3、PA6
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_6;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入引脚
  10. //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // 输入模式无需设置端口速度
  11. GPIO_Init(GPIOA, &GPIO_InitStructure);
  12. // 配置ADC1_CH1、ADC1_CH2、ADC1_CH3、ADC1_CH6
  13. // ADC工作条件:ADC的时钟频率<=14MHz && ADC采样频率<=1MHz
  14. // ADC的总转换周期(必须>=1us) = (采样周期(1.5239.5) + 12.5(固定转换周期)) / ADC时钟频率
  15. // 当:ADC的时钟频率==12MHz、采样周期==1.5,ADC转换周期≈1.17us
  16. //---------------------------------------------------------------------------------------------------------------------
  17. RCC_ADCCLKConfig(RCC_PCLK2_Div6); // ADC时钟6分频:72M/6=12M
  18. ADC_DeInit(ADC1); // 复位ADC1
  19. // 设置ADC1的工作模式
  20. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC工作模式:ADC1和ADC2工作在独立模式
  21. ADC_InitStructure.ADC_ScanConvMode = ENABLE; // "扫描转换模式"使能。即:ADC工作在多通道模式
  22. ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // "连续转换模式"失能。即:ADC工作在单次转换模式
  23. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换由软件启动(也可以设置为外部触发)
  24. ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC数据对齐方式:右对齐
  25. ADC_InitStructure.ADC_NbrOfChannel = C_ADC_Channel; // 设置顺序进行规则转换的ADC通道的数目
  26. ADC_Init(ADC1, &ADC_InitStructure); // 初始化ADC1
  27. // 为了能够正确地配置每一个 ADC 通道,用户在调用 ADC_Init()之后,
  28. // 必须调用ADC_xxxChannelConfig()来配置每个所使用通道的转换次序和采样时间。
  29. //--------------------------------------------------------------------
  30. ADC_RegularChannelConfig(ADC1, N_ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); // 参数:ADC1,要设置的ADC通道序号,规则组采样顺序,采样周期
  31. // 此函数:配置的是"ADC1"的通道"1",它在规则组中的采样顺序是"1",采样周期是"ADC_SampleTime_239Cycles5"
  32. ADC_RegularChannelConfig(ADC1, N_ADC_Channel_3, 2, ADC_SampleTime_239Cycles5);
  33. // 此函数:配置的是"ADC1"的通道"3",它在规则组中的采样顺序是"2",采样周期是"ADC_SampleTime_239Cycles5"
  34. //---------------------------------------------------------------------------------------------------------------------
  35. /*
  36. //ADC1的中断NVIC设置
  37. //---------------------------------------------------------------------------------
  38. NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; // ADC1中断
  39. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级3
  40. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3
  41. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能ADC1_2_IRQn中断
  42. NVIC_Init(&NVIC_InitStructure); // 初始化NVIC寄存器
  43. ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE ); // 允许ADC1的EOC中断
  44. //---------------------------------------------------------------------------------
  45. */
  46. // 开启ADC的DMA支持
  47. ADC_DMACmd(ADC1, ENABLE); // 要实现DMA功能,还需独立配置DMA通道等参数
  48. ADC_Cmd(ADC1, ENABLE); // 使能ADC1
  49. ADC_ResetCalibration(ADC1); // 使能ADC1复位校准
  50. while(ADC_GetResetCalibrationStatus(ADC1)); // 等待ADC1复位校准结束
  51. ADC_StartCalibration(ADC1); // 开启ADC1校准
  52. while(ADC_GetCalibrationStatus(ADC1)); // 等待ADC1校准结束
  53. }

ADC采集:

在配置时,配置为软件触发方式。在使用ADC时,使用程序使能ADC1转换,也就是第一句。

搬运时DMA一次搬运16位数据,前8位为ADC1通道1的值,放在二维数组的第一列

                                                   后8位为ADC1通道3的值,放在二维数组的第二列

  1. void ADC1_Value_average(void)
  2. {
  3. // 摇杆检测
  4. //------------------------------------------------------------------------
  5. ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件使能ADC1转换
  6. // 转换完成后,DMA自动将数据搬运到指定位置
  7. //while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); // 等待转换结束
  8. AM_ADC_Channel1_Sample += ADC1_Value[C_ADC_Sample][0]; // 得到
  9. AM_ADC_Channel3_Sample += ADC1_Value[C_ADC_Sample][1];
  10. C_ADC_Sample++ ; // ADC实际采样次数
  11. // 判断是否已经采样10
  12. if(C_ADC_Sample >= C_Channel_Sample)
  13. {
  14. C_ADC_Sample = 0;
  15. AV_ADC_Channel1_Sample = AM_ADC_Channel1_Sample / C_Channel_Sample; // 求通道1的平均值
  16. AM_ADC_Channel1_Sample = 0 ;
  17. AV_ADC_Channel3_Sample = AM_ADC_Channel3_Sample / C_Channel_Sample; // 求通道3的平均值
  18. AM_ADC_Channel3_Sample = 0 ;
  19. }
  20. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/584426
推荐阅读
相关标签
  

闽ICP备14008679号