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

作者: 青风
上传时间为: 2013-01-19 12:09 AM
2013-01-19
阅读:

第10 课   ADC采样/DMA通道

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

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

[c]

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;

[/c]

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

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

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

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

[c]

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;

[/c]

硬件准备:

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

软件准备:

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

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

[c]

/* 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);

[/c]

然后对ADC参数进行配置:

[c]

/* 初始 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);

 

[/c]

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

[c]

#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); } }

 

[/c]

实验现象:

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

全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示