Posted
: 2020-08-06
Status
:
Completed
Previous
:
STM32标准外设库串口使用DMA发送/接收不定长数据SPL篇7
Next
:
STM32标准外设库TIM应用SPL篇9
Manage Run-Time Environment
Device->StdPeriph Drivers->ADC
my_adc.h
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
#ifndef __MY_ADC_H
#define __MY_ADC_H
#include "stm32f10x.h"
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响
/********************ADC1输入通道(引脚)配置**************************/
#define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_CLK RCC_APB2Periph_ADC1
#define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADC_PORT GPIOC
// 转换通道个数
#define NOFCHANEL 3
#define ADC_PIN GPIO_Pin_1
#define ADC_CHANNEL1 ADC_Channel_11 //管脚GPIOC_1
#define ADC_CHANNEL2 ADC_Channel_16 //芯片温度
#define ADC_CHANNEL3 ADC_Channel_17 //内部参考电压
// ADC1 对应 DMA1通道1
#define ADC_x ADC1
#define ADC_DMA_CHANNEL DMA1_Channel1
#define ADC_DMA_CLK RCC_AHBPeriph_DMA1
#define ADC_DR_Address (ADC1_BASE+0x4c)
/**************************函数声明********************************/
void ADCx_Init(void);
#endif
my_adc.c
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "my_adc.h"
__IO uint16_t ADC_ConvertedValue[NOFCHANEL] = {0};
/**
* @brief ADC GPIO 初始化
* @param 无
* @retval 无
*/
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// ADC GPIO 初始化
ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
}
/**
* @brief 配置ADC工作模式
* @param 无
* @retval 无
*/
static void ADCx_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
// 打开DMA时钟
RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE);
// 打开ADC时钟
ADC_APBxClock_FUN( ADC_CLK, ENABLE);
// ADC 模式配置
// 只使用一个ADC,属于单模式
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 = NOFCHANEL;
// 初始化ADC
ADC_Init(ADC_x, &ADC_InitStructure);
// 配置ADC时钟RCC_PCLK2的8分频,即9MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
// 配置ADC 通道的转换顺序和采样时间
ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL1, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL2, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL3, 3, ADC_SampleTime_239Cycles5);
//使能温度传感器和内部参考电压
ADC_TempSensorVrefintCmd(ENABLE);
// 使能ADC DMA 请求
ADC_DMACmd(ADC_x, ENABLE);
// 开启ADC ,并开始转换
ADC_Cmd(ADC_x, ENABLE);
// 初始化ADC 校准寄存器
ADC_ResetCalibration(ADC_x);
// 等待校准寄存器初始化完成
while(ADC_GetResetCalibrationStatus(ADC_x));
// ADC开始校准
ADC_StartCalibration(ADC_x);
// 等待校准完成
while(ADC_GetCalibrationStatus(ADC_x));
// 由于没有采用外部触发,所以使用软件触发ADC转换
ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
// 复位DMA控制器
DMA_DeInit(ADC_DMA_CHANNEL);
// 配置 DMA 初始化结构体
// 外设基址为:ADC 数据寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC_DR_Address;
// 存储器地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
// 数据源来自外设
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
// 缓冲区大小,应该等于数据目的地的大小
DMA_InitStructure.DMA_BufferSize = NOFCHANEL;
// 外设寄存器只有一个,地址不用递增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// 存储器地址递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
// 外设数据大小为半字,即两个字节
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
// 内存数据大小也为半字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
// 循环传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
// 禁止存储器到存储器模式,因为是从外设到存储器
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
// 初始化DMA
DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
// 使能 DMA 通道
DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
}
/**
* @brief ADC初始化
* @param 无
* @retval 无
*/
void ADCx_Init(void)
{
ADCx_GPIO_Config();
ADCx_Mode_Config();
}
1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//浮空输入
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
/**
* @brief ADC Init structure definition
*/
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** @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) //交替触发模式
ADC_ScanConvMode
单通道AD 转换使用DISABLE
,如果是多通道AD 转换使用ENABLE
。
ADC_ContinuousConvMode
使用ENABLE
配置为使能自动连续转换;使用DISABLE
配置为单次转换,转换一次后停止需要手动控制才重新启动转换。
ADC_ExternalTrigConv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion
* @{
*/
#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */
ADC_DataAlign
1
2
3
4
5
6
/** @defgroup ADC_data_align
* @{
*/
#define ADC_DataAlign_Right ((uint32_t)0x00000000) //右对齐
#define ADC_DataAlign_Left ((uint32_t)0x00000800) //左对齐
ADC_NbrOfChannel
我们选择ADC时钟为9M,采样周期为ADC_SampleTime_239Cycles5
1
2
3
4
5
6
7
8
/** @defgroup ADC_clock_source
* @{
*/
#define RCC_PCLK2_Div2 ((uint32_t)0x00000000) //2分频
#define RCC_PCLK2_Div4 ((uint32_t)0x00004000) //4分频
#define RCC_PCLK2_Div6 ((uint32_t)0x00008000) //6分频
#define RCC_PCLK2_Div8 ((uint32_t)0x0000C000) //8分频
1
2
3
4
5
6
7
8
9
10
11
12
/** @defgroup ADC_sampling_time
* @{
*/
#define ADC_SampleTime_1Cycles5 ((uint8_t)0x00)
#define ADC_SampleTime_7Cycles5 ((uint8_t)0x01)
#define ADC_SampleTime_13Cycles5 ((uint8_t)0x02)
#define ADC_SampleTime_28Cycles5 ((uint8_t)0x03)
#define ADC_SampleTime_41Cycles5 ((uint8_t)0x04)
#define ADC_SampleTime_55Cycles5 ((uint8_t)0x05)
#define ADC_SampleTime_71Cycles5 ((uint8_t)0x06)
#define ADC_SampleTime_239Cycles5 ((uint8_t)0x07)
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
/** @defgroup ADC_channels
* @{
*/
#define ADC_Channel_0 ((uint8_t)0x00)
#define ADC_Channel_1 ((uint8_t)0x01)
#define ADC_Channel_2 ((uint8_t)0x02)
#define ADC_Channel_3 ((uint8_t)0x03)
#define ADC_Channel_4 ((uint8_t)0x04)
#define ADC_Channel_5 ((uint8_t)0x05)
#define ADC_Channel_6 ((uint8_t)0x06)
#define ADC_Channel_7 ((uint8_t)0x07)
#define ADC_Channel_8 ((uint8_t)0x08)
#define ADC_Channel_9 ((uint8_t)0x09)
#define ADC_Channel_10 ((uint8_t)0x0A)
#define ADC_Channel_11 ((uint8_t)0x0B)
#define ADC_Channel_12 ((uint8_t)0x0C)
#define ADC_Channel_13 ((uint8_t)0x0D)
#define ADC_Channel_14 ((uint8_t)0x0E)
#define ADC_Channel_15 ((uint8_t)0x0F)
#define ADC_Channel_16 ((uint8_t)0x10)
#define ADC_Channel_17 ((uint8_t)0x11)
#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16)
#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17)
通道 | ADC1-IO | ADC2-IO | ADC3-IO |
---|---|---|---|
ADC_Channel_0 | PA0 | PA0 | PA0 |
ADC_Channel_1 | PA1 | PA1 | PA1 |
ADC_Channel_2 | PA2 | PA2 | PA2 |
ADC_Channel_3 | PA3 | PA3 | PA3 |
ADC_Channel_4 | PA4 | PA4 | N |
ADC_Channel_5 | PA5 | PA5 | N |
ADC_Channel_6 | PA6 | PA6 | N |
ADC_Channel_7 | PA7 | PA7 | N |
ADC_Channel_8 | PB0 | PB0 | N |
ADC_Channel_9 | PB1 | PB1 | VSS |
ADC_Channel_10 | PC0 | PC0 | PC0 |
ADC_Channel_11 | PC1 | PC1 | PC1 |
ADC_Channel_12 | PC2 | PC2 | PC2 |
ADC_Channel_13 | PC3 | PC3 | PC3 |
ADC_Channel_14 | PC4 | PC4 | VSS |
ADC_Channel_15 | PC5 | PC5 | VSS |
ADC_Channel_16 | TempSensor | VSS | VSS |
ADC_Channel_17 | Vrefint | VSS | VSS |
main.c
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "stm32f10x.h"
#include "my_gpio.h"
#include "my_usart.h"
#include "my_data_queue.h"
#include "my_process_data.h"
#include "my_adc.h"
extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL];
Channel ch[2];
float VREF,VSENSE;
float temp;
float adcValue;
/* 软件延时 */
void Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
Key_GPIO_Config();
/* 初始化USART 配置模式为 9600 8-N-1 */
USART_Config();
/*初始化接收数据队列*/
RX_Queue_Init();
/*初始化ADC*/
ADCx_Init();
printf( "\r\n Print current Temperature \r\n");
while (1)
{
Delay(0xffffee); // 延时
VREF=1.2f*4095/ADC_ConvertedValue[2];
VSENSE=VREF*ADC_ConvertedValue[1]/4095;
temp=(1.43f-VSENSE)*1000/4.3+25;
adcValue=VREF*ADC_ConvertedValue[0]/4095;
printf( "\r\n The IC current tem= %.2fC\r\n", temp);
printf( "\r\n The IC current VDDA= %.2fV\r\n", VREF);
printf( "\r\n The IC current ADC= %.2fV\r\n", adcValue);
Process_Usart_Data(ch);
if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON)
{
/*LED1反转*/
LED1_TOGGLE;
}
if (Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN) == KEY_ON)
{
LED2_TOGGLE;
}
if(ch[0].state==1&&ch[0].start_up==0)
{
ch[0].stop_up=0;
ch[0].start_up=1;
LED1(ON);
}
if(ch[0].state==2&&ch[0].stop_up==0)
{
ch[0].stop_up=1;
ch[0].start_up=0;
LED1(OFF);
}
if(ch[1].state==1&&ch[1].start_up==0)
{
ch[1].stop_up=0;
ch[1].start_up=1;
LED2(ON);
}
if(ch[1].state==2&&ch[1].stop_up==0)
{
ch[1].stop_up=1;
ch[1].start_up=0;
LED2(OFF);
}
}
}