STM32 F103 ADC功能学习

一、添加ADC外设到项目中(省略)

二、阅读ADC外设的头文件

在STM32中库编程中所有的外设的功能设置都是以结构体来组织的,ADC的结构体只有1个,如下:

typedef struct
{
  uint32_t ADC_Mode;                      /*!< Configures the ADC to operate in independent or
                                               dual mode. 
                                               This parameter can be a value of @ref ADC_mode */

  FunctionalState 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 */

  FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion is performed in
                                               Continuous or Single mode.
                                               This parameter can be set to ENABLE or DISABLE. */

  uint32_t ADC_ExternalTrigConv;          /*!< Defines the external trigger used to start the analog
                                               to digital conversion of regular channels. This parameter
                                               can be a value of @ref ADC_external_trigger_sources_for_regular_channels_conversion */

  uint32_t ADC_DataAlign;                 /*!< Specifies whether the ADC data alignment is left or right.
                                               This parameter can be a value of @ref ADC_data_align */

  uint8_t ADC_NbrOfChannel;               /*!< 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. */
}ADC_InitTypeDef;

其中第一个是ADC_Mode,他的取值集合如下:

/** @defgroup ADC_mode 
  * @{
  */

#define ADC_Mode_Independent                       ((uint32_t)0x00000000)
#define ADC_Mode_RegInjecSimult                    ((uint32_t)0x00010000)
#define ADC_Mode_RegSimult_AlterTrig               ((uint32_t)0x00020000)
#define ADC_Mode_InjecSimult_FastInterl            ((uint32_t)0x00030000)
#define ADC_Mode_InjecSimult_SlowInterl            ((uint32_t)0x00040000)
#define ADC_Mode_InjecSimult                       ((uint32_t)0x00050000)
#define ADC_Mode_RegSimult                         ((uint32_t)0x00060000)
#define ADC_Mode_FastInterl                        ((uint32_t)0x00070000)
#define ADC_Mode_SlowInterl                        ((uint32_t)0x00080000)
#define ADC_Mode_AlterTrig                         ((uint32_t)0x00090000)

#define IS_ADC_MODE(MODE) (((MODE) == ADC_Mode_Independent) || \\
                           ((MODE) == ADC_Mode_RegInjecSimult) || \\
                           ((MODE) == ADC_Mode_RegSimult_AlterTrig) || \\
                           ((MODE) == ADC_Mode_InjecSimult_FastInterl) || \\
                           ((MODE) == ADC_Mode_InjecSimult_SlowInterl) || \\
                           ((MODE) == ADC_Mode_InjecSimult) || \\
                           ((MODE) == ADC_Mode_RegSimult) || \\
                           ((MODE) == ADC_Mode_FastInterl) || \\
                           ((MODE) == ADC_Mode_SlowInterl) || \\
                           ((MODE) == ADC_Mode_AlterTrig))
/**
  * @}
  */

其中ADC_Mode_Independent这些都是什么意思呢?我们不清楚,但我们知道这个结构体是在ADC初始化函数中要用到的,那我们就去初始化函数中看看:

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
{
  uint32_t tmpreg1 = 0;
  uint8_t tmpreg2 = 0;
  /* Check the parameters */
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  assert_param(IS_ADC_MODE(ADC_InitStruct->ADC_Mode));
  assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode));
  assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode));
  assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv));   
  assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign)); 
  assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfChannel));

  /*---------------------------- ADCx CR1 Configuration -----------------*/
  /* Get the ADCx CR1 value */
  tmpreg1 = ADCx->CR1;
  /* Clear DUALMOD and SCAN bits */
  tmpreg1 &= CR1_CLEAR_Mask;
  /* Configure ADCx: Dual mode and scan conversion mode */
  /* Set DUALMOD bits according to ADC_Mode value */
  /* Set SCAN bit according to ADC_ScanConvMode value */
  tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8));
  /* Write to ADCx CR1 */
  ADCx->CR1 = tmpreg1;

  /*---------------------------- ADCx CR2 Configuration -----------------*/
  /* Get the ADCx CR2 value */
  tmpreg1 = ADCx->CR2;
  /* Clear CONT, ALIGN and EXTSEL bits */
  tmpreg1 &= CR2_CLEAR_Mask;
  /* Configure ADCx: external trigger event and continuous conversion mode */
  /* Set ALIGN bit according to ADC_DataAlign value */
  /* Set EXTSEL bits according to ADC_ExternalTrigConv value */
  /* Set CONT bit according to ADC_ContinuousConvMode value */
  tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv |
            ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
  /* Write to ADCx CR2 */
  ADCx->CR2 = tmpreg1;

  /*---------------------------- ADCx SQR1 Configuration -----------------*/
  /* Get the ADCx SQR1 value */
  tmpreg1 = ADCx->SQR1;
  /* Clear L bits */
  tmpreg1 &= SQR1_CLEAR_Mask;
  /* Configure ADCx: regular channel sequence length */
  /* Set L bits according to ADC_NbrOfChannel value */
  tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1);
  tmpreg1 |= (uint32_t)tmpreg2 << 20;
  /* Write to ADCx SQR1 */
  ADCx->SQR1 = tmpreg1;
}

这个函数的作用就是根据ADC初始化结构体的成员值去设置ADC相关寄存器,我们可以看到ADC_mode这个成员变量所在的语句是以下几行代码:

/*---------------------------- ADCx CR1 Configuration -----------------*/
  /* Get the ADCx CR1 value */
  tmpreg1 = ADCx->CR1;
  /* Clear DUALMOD and SCAN bits */
  tmpreg1 &= CR1_CLEAR_Mask;
  /* Configure ADCx: Dual mode and scan conversion mode */
  /* Set DUALMOD bits according to ADC_Mode value */
  /* Set SCAN bit according to ADC_ScanConvMode value */
  tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8));
  /* Write to ADCx CR1 */
  ADCx->CR1 = tmpreg1;

这几句代码的作用是:
1、先读出CR1寄存器的值,然后和我们要设置的值做与或者或运算,然后把运算之后的值重新赋值给CR1寄存器,我们返回去看ADC_mode可以选择的值:

#define ADC_Mode_Independent                       ((uint32_t)0x00000000)
#define ADC_Mode_RegInjecSimult                    ((uint32_t)0x00010000)
#define ADC_Mode_RegSimult_AlterTrig               ((uint32_t)0x00020000)
#define ADC_Mode_InjecSimult_FastInterl            ((uint32_t)0x00030000)
#define ADC_Mode_InjecSimult_SlowInterl            ((uint32_t)0x00040000)
#define ADC_Mode_InjecSimult                       ((uint32_t)0x00050000)
#define ADC_Mode_RegSimult                         ((uint32_t)0x00060000)
#define ADC_Mode_FastInterl                        ((uint32_t)0x00070000)
#define ADC_Mode_SlowInterl                        ((uint32_t)0x00080000)
#define ADC_Mode_AlterTrig                         ((uint32_t)0x00090000)

可以看出ADC_mode中每种模式的值都是从第17位开始的,结合以上追溯出的ADC_mode的设置最终是设置CR1寄存器,可以知道ADC_mode设置的其实是CR1寄存器的第16位和十六位以后的值,那么我们打开《STM32参考手册》第171页,可以看到CR1寄存器的解释:


STM32 F103 ADC功能学习_第1张图片
图1-ADC寄存器简介

从这个简介中很明显可以看出CR1寄存器的16-19四个位是DUALMOD[3:0],然后看下面对这三个位的注释为:

STM32 F103 ADC功能学习_第2张图片
图2-CR1寄存器16~19位说明

也就是说是用来选择这些模式的,这就和代码一一对应起来了(我给添加了注释如下):

#define ADC_Mode_Independent                       ((uint32_t)0x00000000)//独立模式
#define ADC_Mode_RegInjecSimult                    ((uint32_t)0x00010000)//混合的同步规则+注入同步模式
#define ADC_Mode_RegSimult_AlterTrig               ((uint32_t)0x00020000)//混合的同步规则+交替触发模式
#define ADC_Mode_InjecSimult_FastInterl            ((uint32_t)0x00030000)//混合同步注入+快速交叉模式
#define ADC_Mode_InjecSimult_SlowInterl            ((uint32_t)0x00040000)//混合同步注入+慢速交叉模式
#define ADC_Mode_InjecSimult                       ((uint32_t)0x00050000)//注入同步模式
#define ADC_Mode_RegSimult                         ((uint32_t)0x00060000)//规则同步模式
#define ADC_Mode_FastInterl                        ((uint32_t)0x00070000)//快速交叉模式
#define ADC_Mode_SlowInterl                        ((uint32_t)0x00080000)//慢速交叉模式
#define ADC_Mode_AlterTrig                         ((uint32_t)0x00090000)//交替触发模式

这样我们就知道如何设置ADC初始化结构体的ADC_Mode这个结构体成员变量了。
对于其他的结构体成员变量设置也是同样的,追溯到源头,你就会看到他的具体作用,然后根据你的需求进行设置。

三、代码编写(省略)

明白了以上的原理,就可以根据自己的需求进行设置了。

四、题外话(关于markdown编辑的使用,以代码框实现为例)

在写这篇文章的时候,是我第一次使用插入代码,搞不懂他们写的文章代码框是怎么加的,在网上搜了之后看到说是三个、、、,然后我就各种尝试,结果发现这三个点是怎么敲出来的呢,普通键盘的ESC下面不是有一个波浪线的键吗,在英文输入法下敲出来的就是我们要的`,连敲三个,代码前面三个后面三个,编辑完就是你说看到的代码框:

STM32 F103 ADC功能学习_第3张图片
图3-代码框的编辑
STM32 F103 ADC功能学习_第4张图片
图4-代码块效果

这是在markdown编辑模式下实现的,所以在实现这样的标签语言前首先要在设置里把编辑模式的富文本模式切换为markdown模式,切换设置见下图:

STM32 F103 ADC功能学习_第5张图片
图5-如何进入设置
STM32 F103 ADC功能学习_第6张图片
图6-编辑文章如何从富文本切换到markdown模式

设置好之后,页面下拉到最下面会有个保存按钮,保存之后新建文章就可以使用标记语言了,包括图片添加,标题设置都是用标记语言实现的,非常简单使用,关于markdown的详细介绍见下面链接:

http://www.jianshu.com/p/1e402922ee32/

喜欢请关注公众号"电子开发学习"


STM32 F103 ADC功能学习_第7张图片
微信公众号二维码

你可能感兴趣的:(STM32 F103 ADC功能学习)