分享

【青风带你学stm32f051系列教程】第10课 ADC采样/DMA通道 | 爱板网

 weikong66 2013-03-28
【青风带你学stm32f051系列教程】第10课 ADC采样/DMA通道
2013年01月18日 ? 教程 ? 评论数 1 ? 被围观 994+

第10 课   ADC采样/DMA通道

模数转换器 (ADC) 外设用于将连续的模拟电压转换成离散的数字量。Stm32f051包含一个分辨率为12位的ADC模块,同时具有19个ADC通道,其中16个外部采样通道和3个内部信号源。ADC采样通道源和ADC管脚如下表所示:

本实验我们采样ADC_IN选取其中一个管脚作为输入引脚,需要对 ADC进行配置。需要配置的几个参数:ADC转化分辨率 ,配置采样的采样方式和扫描方向。这几个参数的配置在stm32f0xx_ad.H中使用一个结构体进行了说:

1
2
3
4
5
6
7
8
9
10
typedef struct
{
uint32_t ADC_Resolution; // 配置ADC的转化分辨率
FunctionalState ADC_ContinuousConvMode; // 配置选择连续采样或单次采样
uint32_t ADC_ExternalTrigConvEdge; // ADC内部边缘触发
uint32_t ADC_ExternalTrigConv; //ADC 内部触发
uint32_t ADC_DataAlign; // 设置ADC是左对齐或者右对齐
uint32_t ADC_ScanDirection; // 设置ADC扫描方向
}ADC_InitTypeDef;

使用中给出一组操作,基于直接存储器访问DMA的控制方式:称为为直接存储器访问模式:DMA。这种方式是为了更为有效地利用处理器和总线可用带宽而设计的。他不需要CPU的情况完成操作。下大大提高了运行效率。

DMA控制器依赖于处理器内核,但DMA不影响总线传输,因为DMA控制器总是在系统总线空闲的时候使用总线。该总线实现处理器和DMA控制器之间最优化设计,使两者之间的冲突降到最低,因此传输性能得到提高。

提供了存储单元到存储单元,外设到存储单元,存储单元到外设等转换模式。DMA为每种支持的外设功能提供专用通道,可以各自独立进行配置。其配置模式多种多样,时候于各自不同的设置要求。

采样库函数配置了DMA的几个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct
{
 uint32_t DMA_PeripheralBaseAddr; //配置外设地址
 uint32_t DMA_MemoryBaseAddr; // 配置内存映射地址
 uint32_t DMA_DIR; // 制定外设的源或者目的地
 uint32_t DMA_BufferSize; // DMA缓冲设置
 uint32_t DMA_PeripheralInc; //设置外设地址是否增加或不增加
 uint32_t DMA_MemoryInc; // 设置内存地址是否增加或不增加
 uint32_t DMA_PeripheralDataSize; //外设数据宽度设置
 uint32_t DMA_MemoryDataSize; //内存数据宽度设置
 uint32_t DMA_Mode; // DMA模式
 uint32_t DMA_Priority; // DMA优先级
 uint32_t DMA_M2M; // memory-to-memory 传输模式设置
}DMA_InitTypeDef;

硬件准备:

硬件配置入下图所示,采用PA1作为引脚,对变阻器输入的信号进行转换:

 

软件准备:

软件采用库函数进行配置,用户需要配置编写adc.c驱动函数,工程目录如下图所示:

首先我们需要初始化AD配置,在adc.c文件中,我们编写ADC1_DMA_Init()函数,通过配置DMA通道和ADC外设,首先DMA配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DMA1 Channel1 Config */
 DMA_DeInit(DMA1_Channel1);//选择频道
 DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;//设置外设地址
 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RegularConvData_Tab;//设置内存映射地址
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize =4;//缓冲为4
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//关外设地址计数
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//关内存地址计数
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//半字节
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStruct.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;//关内存到内存
DMA_Init(DMA1_Channel1, &DMA_InitStruct);
  
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);//频道使能
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);//配置DMA循环模式
/* Enable ADC_DMA */
 ADC_DMACmd(ADC1, ENABLE);

然后对ADC参数进行配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 初始 ADC 配置 */
 ADC_StructInit(&ADC_InitStruct);
 /* 配置ADC1 在连续模式下分辨率为12 bits */
 ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
 ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
 ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Backward;
 ADC_Init(ADC1, &ADC_InitStruct);
/* Convert the ADC1 Vref with 55.5 Cycles as sampling time */
 ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_55_5Cycles);
 /* ADC 刻度 */
 ADC_GetCalibrationFactor(ADC1);
 ADC_DMACmd(ADC1, ENABLE);
 /* 使能ADC1 */
 ADC_Cmd(ADC1, ENABLE);
 /* 等待ADCEN 标志 */
 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
  
 /* ADC1 定期变换 */
 ADC_StartOfConversion(ADC1);
  
 

写好初始化函数后,在子函数内就可以直接调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "stm32f0xx.h"
#include "adc.h"
#include "systick.h"
#include "w25x16.h"
#include "ili9328.h"
// ADC1转换的电压值通过MDA方式传到flash
extern __IO uint16_t RegularConvData_Tab;
  
// 局部变量,用于存从flash读到的电压值
__IO uint16_t ADC_ConvertedValueLocal;
  
void delay(__IO uint32_t nCount)
{
 for(; nCount != 0; nCount--);
}
  
int main(void)
{
 SystemInit();
 ADC1_DMA_Init();
 LCD_init(); // 液晶显示器初始化
 SPI_FLASH_Init();
 LCD_Clear(WHITE); // 全屏显示白色
 POINT_COLOR = BLACK; // 定义笔的颜色为黑色
 BACK_COLOR = WHITE; // 定义笔的背景色为白色
 LCD_DrawRectage(0, 0, 320, 20, DARKBLUE); // 画一个深蓝色边框的矩形
 LCD_ShowString(2,2,"实验十");
 LCD_ShowString(100,2,"adc采样实验");
 while(1)
 {
 ADC_ConvertedValueLocal= RegularConvData_Tab;
 delay(0xffffee);
 LCD_ShowString(20,40,"adc采样值:");
 LCD_ShowNum(100,40,ADC_ConvertedValueLocal,4);
 }
}
  
 

实验现象:

调节滑动变阻器,AD转换后成不同的值,结果如下图所示:

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多