您的位置:首页 > 其它

基于stm32f103zet6的DMA学习

2013-03-12 19:51 369 查看
stm32内部集成的ADC介绍

一、参考电压的范围为 

/*2.4V≦ V
≦3.6V

所以它的输入模拟电压范围0 <= V <=V*/

二、需要测量负电压或测量的电压信号超出范围时,要先经过运算电路进行平移或利用电阻分压。

三、我采用的是51单片机上面的10k的电阻来模拟输入

四、规则通道和注入通道

/*所谓规则,那么就是按常理出牌的,我们可以称之为正常的通道,那么与之对应的是注入通道,就是

在规则通道正在转换的时候是可以被注入通道打断,转而去执行注入通道转换的,当注入通道转换完

成之后,才继续去进行规则通道里面的转换,TM32ADC的规则通道组最多包含16 个转换,而注入通道

组最多包含 4 个通道*/

五、初始化ADC这是必须的,比东有一个结构体来初始化这个ADC

1、首先确定从哪里输入我们的模拟量呢?

这里涉及到ADC通道的知识,每个ADC通道都对应着一个GPIO引脚端口

PC0对应的默认复用功能是ADC1、ADC2、ADC3的通道10

所以最开始应该配置GPIO,现在可以来做个猜测

2、配置GPIO

GPIO_Mode = GPIO_Mode_AIN 

GPIO_Pin = GPIO_Pin_10

GPIO_Speed = GPIO_Speed_50MHz   

以上就是模拟输入

六、然后是配置ADC,也就是初始化ADC了,

找到这样一个结构体

ADC_InitTypeDef 

结构体成员有{

FunctionalState  ADC_ContinuousConvMode 

uint32_t  ADC_DataAlign 

uint32_t  ADC_ExternalTrigConv 

uint32_t  ADC_Mode 

uint8_t  ADC_NbrOfChannel 

FunctionalState  ADC_ScanConvMode 

}

1、ADC_ContinuousConvMode的取值有

Specifies whether the conversion is performed in Continuous or Single mode.

This parameter can be set to ENABLE or DISABLE

此参数用来配置是否开启循环采集ENABLE or DISABLE

2、ADC_DataAlign明显意思是数据对齐,它的取值有

#define  ADC_DataAlign_Left   ((uint32_t)0x00000800) 

#define  ADC_DataAlign_Right   ((uint32_t)0x00000000) 

#define  IS_ADC_DATA_ALIGN(ALIGN) 

左对齐,右对齐。。

3、ADC_ExternalTrigConv外部中断触发方式?它的取值有

#define  ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO   ((uint32_t)0x000C0000) 

#define  ADC_ExternalTrigConv_None   ((uint32_t)0x000E0000) 

#define  ADC_ExternalTrigConv_T1_CC1   ((uint32_t)0x00000000) 

#define  ADC_ExternalTrigConv_T1_CC2   ((uint32_t)0x00020000) 

#define  ADC_ExternalTrigConv_T1_CC3   ((uint32_t)0x00040000) 

#define  ADC_ExternalTrigConv_T2_CC2   ((uint32_t)0x00060000) 

#define  ADC_ExternalTrigConv_T2_CC3   ((uint32_t)0x00020000) 

#define  ADC_ExternalTrigConv_T3_CC1   ((uint32_t)0x00000000) 

#define  ADC_ExternalTrigConv_T3_TRGO   ((uint32_t)0x00080000) 

#define  ADC_ExternalTrigConv_T4_CC4   ((uint32_t)0x000A0000) 

#define  ADC_ExternalTrigConv_T5_CC1   ((uint32_t)0x000A0000) 

#define  ADC_ExternalTrigConv_T5_CC3   ((uint32_t)0x000C0000) 

#define  ADC_ExternalTrigConv_T8_CC1   ((uint32_t)0x00060000) 

#define  ADC_ExternalTrigConv_T8_TRGO   ((uint32_t)0x00080000) 

触发方式很丰富,当然 ADC_ExternalTrigConv_None这就表示不采用外部中断方式触发(那么软件触发)

4、ADC_Mode ADC的模式?

Configures the ADC to operate in independent or dual mode. 

This parameter can be a value of ADC_mode

它的取值有

#define  ADC_Mode_AlterTrig   ((uint32_t)0x00090000) 

#define  ADC_Mode_FastInterl   ((uint32_t)0x00070000) 

#define  ADC_Mode_Independent   ((uint32_t)0x00000000) 

#define  ADC_Mode_InjecSimult   ((uint32_t)0x00050000) 

#define  ADC_Mode_InjecSimult_FastInterl   ((uint32_t)0x00030000) 

#define  ADC_Mode_InjecSimult_SlowInterl   ((uint32_t)0x00040000) 

#define  ADC_Mode_RegInjecSimult   ((uint32_t)0x00010000) 

#define  ADC_Mode_RegSimult   ((uint32_t)0x00060000) 

#define  ADC_Mode_RegSimult_AlterTrig   ((uint32_t)0x00020000) 

#define  ADC_Mode_SlowInterl   ((uint32_t)0x00080000) 

貌似是有注入组、和规则组的概念,有些单词不是很熟悉,没关系那就先这样吧!用到了再来

5、ADC_NbrOfChannel采样通道?

明显一般采用的是是16个规则通道,那取值就是1--16

Specifies the number of ADC channels that will be converted using the sequencer for regular

channel group.This parameter must range from 1 to 16

6、ADC_ScanConvMode,字面意思不是很懂,看手册

Specifies whether the conversion is performed in Scan (multichannels) or Single (one channel)

mode. This parameter can be set to ENABLE or DISABLE 

意思是当有多个通道的时候,使用扫描的方式,反之只有单个通道的是那么就是选择单通道了

那么取值就是ENABLE or DISABLE 

至此结构成员分析完毕,下面来猜测一下,应该怎样赋值,声明:单通道采集,右对齐(方便存数据)

软件触发,通道采用10(使用PC0)

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None

ADC_InitStructure.ADC_Mode= ADC_Mode_Independent

ADC_InitStructure.ADC_NbrOfChannel = 11

ADC_InitStructure.ADC_ScanConvMode = DISABLE

下面来对照下,原始代码看看:

  /* ADC1 configuration */

  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 = 1;

  ADC_Init(ADC1, &ADC_InitStructure);

显然错误还是比较多的,没关系,慢慢分析

1、因为是一个通道没必要扫描,所以第2个错了

2、通道数目理解错误。我以为那是指定的哪个通道,原来是number of channel

3、好的最后就是少了一个库函数的调用,这确实是缺乏这种意识呀!

七、既然是使用DMA来传送数据,那么下一步就开始初始化DMA吧!DMA的知识暂时不分析,那个得单独出来

我还是先来了解下DMA的变成思想吧!

1、STM32就是这样完美,每个模块都能有个结构体来组织它的一些参数配置,我甚至觉得它和uboot一样讨人喜欢

这只是我的愚见,也是这样一个结构体 DMA_InitTypeDef DMA_InitStructure;

跟着手册来吧

2、DMA_InitTypeDef{

uint32_t  DMA_BufferSize 

uint32_t  DMA_DIR 

uint32_t  DMA_M2M 

uint32_t  DMA_MemoryBaseAddr 

uint32_t  DMA_MemoryDataSize 

uint32_t  DMA_MemoryInc 

uint32_t  DMA_Mode 

uint32_t  DMA_PeripheralBaseAddr 

uint32_t  DMA_PeripheralDataSize 

uint32_t  DMA_PeripheralInc 

uint32_t  DMA_Priority

}

3、DMA_BufferSize,明显就是数据的大小,看她是怎么描述的

Specifies the buffer size, in data unit, of the specified Channel. The data unit is equal to 

the configuration set in DMA_PeripheralDataSize or DMA_MemoryDataSize members depending in 

the transfer direction 

可以得出DMA_PeripheralDataSize = DMA_MemoryDataSize = DMA_BufferSize

取值可以是

#define  DMA_MemoryDataSize_Byte   ((uint32_t)0x00000000) 

#define  DMA_MemoryDataSize_HalfWord   ((uint32_t)0x00000400) 

#define  DMA_MemoryDataSize_Word   ((uint32_t)0x00000800) 

4、DMA_DIR字面意思不怎么明朗方向?看解释

Specifies if the peripheral is the source or destination. This parameter can be a value of 

DMA_data_transfer_direction

数据源和目的源

取值

#define  DMA_DIR_PeripheralDST   ((uint32_t)0x00000010) 

#define  DMA_DIR_PeripheralSRC   ((uint32_t)0x00000000 

从存储器到外设或者从外设到存储器

5、DMA_M2M 这个可以猜测到,DMA的作用出了上面一个还有M to M的没有提及那么

#define  DMA_M2M_Disable   ((uint32_t)0x00000000) 

#define  DMA_M2M_Enable   ((uint32_t)0x00004000) 

可以这样设置了

6、DMA_MemoryBaseAddr、DMA_PeripheralBaseAddr

这两个可以一起看了,字面意思很清楚了,外设地址和存储器(变量)地址,这个得看你的地址了

7、DMA_MemoryInc、DMA_PeripheralInc看变量名不是很了解,中断触发么?看解释

Specifies whether the memory address register is incremented(adj.增加的) or not. 

This parameter can be a value of DMA_memory_incremented_mode

地址增加?理解严重错误,那么就是地址递增的意思吧,那就是可以连续采集多个通道咯?继续分析

8、DMA_Mode:DMA的模式,他有什么模式呢?看解释

Specifies the operation mode of the DMAy Channelx. 

This parameter can be a value of DMA_circular_normal_mode

还有一句:The circular buffer mode cannot be used if the memory-to-memory 

data transfer is configured on the selected Channel 

取值有

#define  DMA_Mode_Circular   ((uint32_t)0x00000020) 

#define  DMA_Mode_Normal   ((uint32_t)0x00000000) 

正常和循环模式,难道是轮采?先这样继续

9、DMA_Priority优先级这个就好理解了,不就是控制优先权么看解释以及取值

Specifies the software priority for the DMAy Channelx. This parameter can be 

a value of DMA_priority_level 

取值

#define  DMA_Priority_High   ((uint32_t)0x00002000) 

#define  DMA_Priority_Low   ((uint32_t)0x00000000) 

#define  DMA_Priority_Medium   ((uint32_t)0x00001000) 

#define  DMA_Priority_VeryHigh   ((uint32_t)0x00003000 

很明朗4个优先级

至此,分析完毕,尝试性猜测

1、DMA_InitStructure.DMA_BufferSize = 1

2、DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST

3、DMA_InitStructure.DMA_M2M = DMA_M2M_Disable 

4、DMA_InitStructure.DMA_MemoryBaseAddr = 一个地址单元的变量单字节 可以使char型的

5、DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte

6、DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable 不需要地址增量

7、DMA_InitStructure.DMA_Mode = DMA_Mode_Circular 不停的采

8、DMA_InitStructure.DMA_PeripheralBaseAddr = 串口的地址?

9、DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte

10、DMA_InitStructure.MA_PeripheralInc = DMA_PeripheralInc_Disable 同样的

11、DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh 给最高的

查看源代码

  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize = 1;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

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

貌似有点不妙的感觉

1、MA_InitStructure.DMA_DIR这个明显是作为数据源

2、DMA_MemoryDataSize_Byte和DMA_PeripheralDataSize_HalfWord有什么区别

百度里面我没有找到,先这样,等做完实验再验证

八、结构体成员初始化完毕之后,还有很多工作要做

1、  /* ADC1 regular channel11 configuration */ 

  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);

  配置规则通道11

2、  /* Enable DMA channel1 */

  DMA_Cmd(DMA1_Channe10, ENABLE);

  使能DMA通道

3、  /* Enable ADC1 DMA */

  ADC_DMACmd(ADC1, ENABLE);

  使能ADC1的DMA控制器

4、  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);

  使能ADC1

5、  /* Enable ADC1 reset calibaration register */   

  ADC_ResetCalibration(ADC1);

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

  while(ADC_GetResetCalibrationStatus(ADC1));//复位校准

  /* Start ADC1 calibaration */

  ADC_StartCalibration(ADC1);

  /* Check the end of ADC1 calibration */

  while(ADC_GetCalibrationStatus(ADC1));//校准

     

  /* Start ADC1 Software Conversion */ 

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发,这时候真正开始转换  

  硬件测试后,结果正确的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  STM32 DMA 串口