STM32hal库学习(F1)-ADC

ADC简介

ADC:

模数转换器

常见ADC类型

ADC电路类型

优点

缺点

并联比较型

转换速度最快

成本高、功耗高,分辨率低

逐次逼近型

结构简单,功耗低

转换速度较慢

并联比较型

分压部分+比较部分+编码部分

逐次逼近型

控制电路+数码寄存器+D/A转换器+电压比较

特点:分辨率和采样速度相互矛盾,

           分辨率越高,采样速率越低

ADC的特性参数

分辨率(刻度划分)

表示ADC能辨别的最小模拟量,用二进制位数表示,比如:8、10、12、16位

转换时间

表示完成一次A/D转换所需要的时间,转换时间越短,采样速率越高

精度(物理量的精准程度)

最小刻度基础上叠加各种误差的参数,精度受ADC性能、温度和气压等影响

量化误差

用数字量近似表示模拟量,采用四舍五入原则,此过程产生的误差为量化误差

STM32各系列ADC的主要特征

主要特性

F1

F4

F7

H7

ADC类型

逐次逼近型

分辨率

12

6/8/10/12

6/8/10/12

8/10/12/14/16

ADC时钟频率

14MHzmax

36MHzmax

采样时间

采样时间越长, 转换结果相对越准确, 但是转换速度就越慢

转换时间

ADC时钟频率、分辨率和采样时间等有关

供电电压

VSSA 0VVDDA 2.4V~3.6V(全速运行)

参考电压

VREF 0VVREF+一般为3.3V

输入电压

VREFVINVREF+

ADC工作原理

F1结构框图

F4结构框图

F1输入通道

ADC1

IO

ADC2

IO

ADC3

IO

通道0

PA0

通道0

PA0

通道0

PA0

通道1

PA1

通道1

PA1

通道1

PA1

通道2

PA2

通道2

PA2

通道2

PA2

通道3

PA3

通道3

PA3

通道3

PA3

通道4

PA4

通道4

PA4

通道4

PF6

通道5

PA5

通道5

PA5

通道5

PF7

通道6

PA6

通道6

PA6

通道6

PF8

通道7

PA7

通道7

PA7

通道7

PF9

通道8

PB0

通道8

PB0

通道8

PF10

通道9

PB1

通道9

PB1

通道9

连接内部VSS

通道10

PC0

通道10

PC0

通道10

PC0

通道11

PC1

通道11

PC1

通道11

PC1

通道12

PC2

通道12

PC2

通道12

PC2

通道13

PC3

通道13

PC3

通道13

PC3

通道14

PC4

通道14

PC4

通道14

连接内部VSS

通道15

PC5

通道15

PC5

通道15

连接内部VSS

通道16

连接内部温度传感器

通道16

连接内部VSS

通道16

连接内部VSS

通道17

连接内部Vrefint

通道17

连接内部VSS

通道17

连接内部VSS

F1转换序列及其优先级

F1规则序列

规则序列寄存器控制关系汇总

寄存器

寄存器位

功能

取值

SQR3

SQ1 [ 4 : 0 ]

设置第1个转换的通道

通道0~17

SQ2 [ 4 : 0 ]

设置第2个转换的通道

通道0~17

SQ3 [ 4 : 0 ]

设置第3个转换的通道

通道0~17

SQ4 [ 4 : 0 ]

设置第4个转换的通道

通道0~17

SQ5 [ 4 : 0 ]

设置第5个转换的通道

通道0~17

SQ6 [ 4 : 0 ]

设置第6个转换的通道

通道0~17

SQR2

SQ7 [ 4 : 0 ]

设置第7个转换的通道

通道0~17

SQ8 [ 4 : 0 ]

设置第8个转换的通道

通道0~17

SQ9 [ 4 : 0 ]

设置第9个转换的通道

通道0~17

SQ10 [ 4 : 0 ]

设置第10个转换的通道

通道0~17

SQ11 [ 4 : 0 ]

设置第11个转换的通道

通道0~17

SQ12 [ 4 : 0 ]

设置第12个转换的通道

通道0~17

SQR1

SQ13 [ 4 : 0 ]

设置第13个转换的通道

通道0~17

SQ14 [ 4 : 0 ]

设置第14个转换的通道

通道0~17

SQ15 [ 4 : 0 ]

设置第15个转换的通道

通道0~17

SQ16 [ 4 : 0 ]

设置第16个转换的通道

通道0~17

SQL [ 3 : 0 ]

设置规则序列要转换的通道数

0~15

F1注入序列

注入序列寄存器控制关系汇总

寄存器

寄存器位

功能

取值

JSQR

JSQ1 [ 4 : 0 ]

设置第1个转换的通道

通道0~17

JSQ2 [ 4 : 0 ]

设置第2个转换的通道

通道0~17

JSQ3 [ 4 : 0 ]

设置第3个转换的通道

通道0~17

JSQ4 [ 4 : 0 ]

设置第4个转换的通道

通道0~17

JL [ 1 : 0 ]

设置注入序列要转换的通道数

0~3

注入序列的转换顺序是从JSQx[ 4 : 0 ]x=4-JL[1:0])开始

F1触发源

ADON位触发转换(仅F1系列拥有)

ADC_CR2寄存器的ADON位为1时,再单独ADON位写1,只能启动规则组转换

外部触发

F4/F7触发源

F1转换时间

F4/F7转换时间

F1数据寄存器

F4/F7数据寄存器

F1/F4/F7中断

转换模式

CONT

0

1

转换模式

单次转换模式

连续转换模式

转换组/转换模式

单次转换模式(只触发一次转换)

连续转换模式(自动触发下一次转换)

注意:只有规则组才能触发该模式

规则组

转换结果被储存在ADC_DR

EOC(转换结束)标志位被置1

如果设置了EOCIE位,则产生中断

然后ADC停止

转换结果被储存在ADC_DR

EOC(转换结束)标志位被置1

如果设置了EOCIE位,则产生中断

注入组

转换结果被储存在ADC_DRJx

JEOC(转换结束)标志位被置1

如果设置了JEOCIE位,则产生中断

然后ADC停止

转换结果被储存在ADC_DRJx

JEOC(转换结束)标志位被置1

如果设置了JEOCIE位,则产生中断

自动注入:将JAUTO位置1

扫描模式

SCAN

0

1

扫描模式

关闭扫描模式

使用扫描模式

关闭扫描模式

使用扫描模式

ADC只转换ADC_SQRx

ADC_JSQR选中的第一个通道进行转换

ADC会扫描所有被ADC_SQRx

ADC_JSQR选中的所有通道

模式组合

单次转换模式(不扫描)

只转换一个通道,而且是一次,需等待下一次触发

单次转换模式(扫描)

ADC_SQRx ADC_JSQR 选中的所有通道都转换一次

连续转换模式(不扫描)

只会转换一个通道,转换完后会自动执行下一次转换

连续转换模式(扫描)

ADC_SQRx ADC_JSQR 选中的所有通道都转换一次,并自动进入下一轮转换

具体例子

单次转换模式(不扫描)

使用ADC单通道,并要求进行一次转换

单次转换模式(扫描)

使用ADC多通道,并要求所有通道都转换一次就停止

连续转换模式(不扫描)

使用ADC单通道,并要求对该通道连续转换

连续转换模式(扫描)

使用ADC多通道,并要求所有通道都转换一次后,自动启动下一轮转换

ADC相关寄存器

ADC_CR1(ADC控制寄存器1)

ADC_CR2(ADC控制寄存器2)

ADC_SMPR1(ADC采样时间寄存器1)

ADC_SMPR2(ADC采样时间寄存器2)

ADC_SQR1(ADC规则序列寄存器1)

ADC_SQR2(ADC规则序列寄存器2)

ADC_DR(ADC规则数据寄存器)

配置步骤

单通道ADC采集配置步骤

HAL库函数介绍

函数

主要寄存器

主要功能

HAL_ADC_Init()

CR1CR2

配置ADC工作参数

HAL_ADCEx_Calibration_Start()

CR2

ADC校准

HAL_ADC_MspInit()

存放NVICCLOCKGPIO初始化代码

HAL_RCCEx_PeriphCLKConfig()

RCC_CFGR

设置扩展外设时钟,如:ADCRTC

HAL_ADC_ConfigChannel()

SQRxSMPRx

配置ADC相应通道的相关参数

HAL_ADC_Start()

CR2

启动A/D转换

HAL_ADC_PollForConversion()

SR

等待规则通道转换完成

HAL_ADC_GetValue()

DR

获取规则通道A/D转换结果

//相关结构体
typedef struct 
{ 
    ADC_TypeDef *Instance; 			/* ADC 寄存器基地址 */ 
	ADC_InitTypeDef Init; 		    /* ADC 参数初始化结构体变量 */ 
	DMA_HandleTypeDef *DMA_Handle; 	/* DMA 配置结构体 */
	…… 
} ADC_HandleTypeDef;

typedef struct
 { 
	uint32_t DataAlign; 					/* 设置数据的对齐方式 */ 
	uint32_t ScanConvMode; 				    /* 扫描模式 */ 
   	FunctionalState ContinuousConvMode; 	/* 开启单次转换模式或者连续转换模式 */ 	                
    uint32_t NbrOfConversion; 				/* 设置转换通道数目 */ 
	FunctionalState DiscontinuousConvMode; 	/* 是否使用规则通道组间断模式 */ 
	uint32_t NbrOfDiscConversion; 			/* 配置间断模式的规则通道个数 */ 
	uint32_t ExternalTrigConv; 				/* ADC 外部触发源选择 */ 
} ADC_InitTypeDef;

typedef struct 
{ 
	uint32_t Channel; 		/* ADC 转换通道 */ 
	uint32_t Rank; 			/* ADC 转换顺序 */ 
	uint32_t SamplingTime; 	/* ADC 采样周期 */ 
}  ADC_ChannelConfTypeDef;
//ADC.c
#include "ADC.h"

ADC_HandleTypeDef ADC_Handler;            // ADC句柄
ADC_ChannelConfTypeDef ADC_ChannelConfig; // ADC通道配置句柄

void ADC_Init()
{
    ADC_Handler.Instance = ADC1;                            // ADC1
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_DISABLE;       // 不开启扫描模式
    ADC_Handler.Init.ContinuousConvMode = DISABLE;          // 不开启连续模式
    ADC_Handler.Init.NbrOfConversion = 1;                   // 通道数量1
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不开启间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 间断模式数量0
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发ADC
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化,调用HAL_ADC_MspInit()
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_ChannelConfig.Channel = ADC_CHANNEL_1;                   // PA1 ,ADC1通道1
    ADC_ChannelConfig.Rank = ADC_REGULAR_RANK_1;                 // 放在第一个转换位置
    ADC_ChannelConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 239.5个转换周期,21us
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_ChannelConfig);     // ADC1通道配置
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1) // 判断是不是ADC1
    {
        GPIO_InitTypeDef GPIO_InitStructure;                // GPIO初始化结构体
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLK_InitStructure; // ADC时钟选择结构体

        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
        __HAL_RCC_ADC1_CLK_ENABLE();  // 使能ADC1时钟

        GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;      // 开启模拟功能
        GPIO_InitStructure.Pin = GPIO_PIN_1;             // PA1
        GPIO_InitStructure.Pull = GPIO_NOPULL;           // 不上下拉
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);       // GPIOA初始化

        RCC_ADC_CLK_InitStructure.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设时钟选择ADC
        RCC_ADC_CLK_InitStructure.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // 6分频:12M
        HAL_RCCEx_PeriphCLKConfig(&RCC_ADC_CLK_InitStructure);              // 外设时钟配置
    }
}

uint32_t ADC_GET()
{
    HAL_ADC_Start(&ADC_Handler);                 // 开启ADC1
    HAL_ADC_PollForConversion(&ADC_Handler, 10); // 等待ADC转化,10ms
    return HAL_ADC_GetValue(&ADC_Handler);       // 返回ADC获得值
}

uint32_t ADCx;
float temp;

void ADC_Show()
{
    ADCx = ADC_GET();
    LCD_ShowxNum(134, 110, ADCx, 5, 16, 0); // 显示ADCx

    temp = (float)ADCx * 3.3 / 4096;
    ADCx = temp;
    LCD_ShowxNum(134, 130, ADCx, 1, 16, 0); // 显示整数部分

    temp -= ADCx;
    temp *= 1000;
    LCD_ShowxNum(150, 130, temp, 3, 16, 0X80); // 显示及小鼠部分
}
//ADC.h
#ifndef __ADC_H
#define __ADC_H

#include "sys.h"
#include "lcd.h"

void ADC_Init();
uint32_t ADC_GET();
void ADC_Show();

#endif
//main.c
//精英开发板
//PA1采集电位器电压
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "ADC.h"

int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
    KEY_Init();                     // 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");
	LCD_ShowString(30, 110, 200, 16, 16, "ADC1_CH1_VAL:");
	LCD_ShowString(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V");
	ADC_Init();
	while (1)
	{
		ADC_Show();
		delay_ms(5);
	}
}	

单通道ADC采集(DMA读取)配置步骤

HAL库函数介绍

函数

主要寄存器

主要功能

HAL_ADC_Init()

CR1CR2

配置ADC工作参数

HAL_ADCEx_Calibration_Start()

CR2

ADC校准

HAL_ADC_MspInit()

存放NVICCLOCKGPIO初始化代码

HAL_RCCEx_PeriphCLKConfig()

RCC_CFGR

设置扩展外设时钟,如:ADCRTC

HAL_ADC_ConfigChannel()

SQRxSMPRx

配置ADC相应通道的相关参数

HAL_DMA_Start_IT()

CCRx

启动DMA、开启传输完成中断

HAL_ADC_Start_DMA()

CR2

触发ADC转换、使用DMA传输数据

//相关结构体
typedef struct 
{ 
	uint32_t Direction; 			/* 传输方向 */ 
	uint32_t PeriphInc; 			/* 外设(非)增量模式 */ 
	uint32_t MemInc; 				/* 存储器(非)增量模式 */ 
	uint32_t PeriphDataAlignment; 	/* 外设数据宽度 */ 
	uint32_t MemDataAlignment; 		/* 存储器数据宽度 */ 
	uint32_t Mode; 					/* 操作模式 */ 
	uint32_t Priority; 				/* DMA通道优先级 */ 
}DMA_InitTypeDef; 
//ADC.c
#include "ADC.h"

DMA_HandleTypeDef DMA_Handler;            // DMA句柄
ADC_HandleTypeDef ADC_Handler;            // ADC句柄
ADC_ChannelConfTypeDef ADC_Channelconfig; // ADC通道配置
uint8_t adc_dma_sta = 0;                  // ADC_DMA传输标志
uint16_t i;
uint16_t adcx;
uint32_t sum;
float temp;
uint16_t adc_dma_buf[ADC_DMA_BUF_SIZE];

void ADC_Init(uint32_t mar)
{
    __HAL_RCC_DMA1_CLK_ENABLE();                                    // 使能DMA1时钟
    DMA_Handler.Instance = DMA1_Channel1;                           // DMA1通道1
    DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;              // DMA从外设到寄存器
    DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;    // DMA寄存器数据长度:半字
    DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                      // 寄存器地址增量
    DMA_Handler.Init.Mode = DMA_NORMAL;                             // 不开启循环模式
    DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // DMA外设数据长度:半字
    DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                  // 外设地址不增量
    DMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;                  // 中断优先级高
    HAL_DMA_Init(&DMA_Handler);                                     // DMA初始化
    __HAL_LINKDMA(&ADC_Handler, DMA_Handle, DMA_Handler);           // 将DMA的结构体成员赋予ADC的DMA结构体

    ADC_Handler.Instance = ADC1;                            // ADC1
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_DISABLE;       // 不开启扫描模式
    ADC_Handler.Init.ContinuousConvMode = ENABLE;           // 开启连续模式
    ADC_Handler.Init.NbrOfConversion = 1;                   // 转换通道数目1
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不开启间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 间断模式规则通道数目1
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // ADC软件触发
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化,调用HAL_ADC_MspInit()
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_Channelconfig.Channel = ADC_CHANNEL_1;                   // ADC通道1
    ADC_Channelconfig.Rank = ADC_REGULAR_RANK_1;                 // ADC准换顺序1
    ADC_Channelconfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // ADC采样周期239.5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channelconfig);     // ADC通道配置

    HAL_DMA_Start_IT(&DMA_Handler, (uint32_t)&ADC1->DR, mar, 0); // DMA使能并开启中断,传输数量0
    HAL_ADC_Start_DMA(&ADC_Handler, &mar, 0);                    // ADC使能DMA通道
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1) // 判断是不是ADC1
    {
        GPIO_InitTypeDef GPIO_InitStructure;               // GPIO初始化结构体
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLKInitStructure; // ADC时钟配置结构体

        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA
        __HAL_RCC_ADC1_CLK_ENABLE();  // 使能ADC1

        GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;      // 模拟功能
        GPIO_InitStructure.Pin = GPIO_PIN_1;             // PA1 ADC1 CHANNERL 1
        GPIO_InitStructure.Pull = GPIO_NOPULL;           // 不上下拉
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; // 高速,这里无所谓
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);       // PA1初始化

        RCC_ADC_CLKInitStructure.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设时钟选择:ADC
        RCC_ADC_CLKInitStructure.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // ADC时钟6分频
        HAL_RCCEx_GetPeriphCLKConfig(&RCC_ADC_CLKInitStructure);           // ADC时钟配置

        HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3); // 开启DMA1通道1数据流中断
        HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);         // 使能DMA1通道1数据流中断
    }
}

void ADC_DMA_ENABLE(uint16_t cndtr)
{
    __HAL_ADC_DISABLE(&ADC_Handler);      // ADC失能
    __HAL_DMA_DISABLE(&DMA_Handler);      // DMA失能
    while (DMA1_Channel1->CCR & (1 << 0)) // 等待DMA允许传输完成中断
        ;
    DMA1_Channel1->CNDTR = cndtr;   // 写入传输数量
    __HAL_ADC_ENABLE(&ADC_Handler); // 使能ADC
    __HAL_DMA_ENABLE(&DMA_Handler); // 使能DMA
    HAL_ADC_Start(&ADC_Handler);    // 开启ADC
}

void DMA1_Channel1_IRQHandler()
{
    if (DMA1->ISR & (1 << 1)) // DMA1通道1完成了传输完成事件
    {
        adc_dma_sta = 1;      // ADC_DMA标志
        DMA1->IFCR |= 1 << 1; // 清除DMA1通道1传输完成标志
    }
}

void ADC_SHOW()
{
    if (adc_dma_sta == 1)
    {
        /* 计算DMA 采集到的ADC数据的平均值 */
        sum = 0;

        for (i = 0; i < ADC_DMA_BUF_SIZE; i++) /* 累加 */
        {
            sum += adc_dma_buf[i];
        }

        adcx = sum / ADC_DMA_BUF_SIZE; /* 取平均值 */

        /* 显示结果 */
        LCD_ShowxNum(134, 110, adcx, 4, 16, 0); /* 显示ADCC采样后的原始值 */

        temp = (float)adcx * (3.3 / 4096);      /* 获取计算后的带小数的实际电压值,比如3.1111 */
        adcx = temp;                            /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
        LCD_ShowxNum(134, 130, adcx, 1, 16, 0); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */

        temp -= adcx;                              /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
        temp *= 1000;                              /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
        LCD_ShowxNum(150, 130, temp, 3, 16, 0X80); /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */

        adc_dma_sta = 0;                  /* 清除DMA采集完成状态标志 */
        ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE); // 准备下一次ADC读取
    }
}
//ADC.h
#ifndef __ADC_H
#define __ADC_H

#include "sys.h"
#include "lcd.h"
#define ADC_DMA_BUF_SIZE  100 /* ADC DMA采集 BUF大小 */

void ADC_Init(uint32_t mar);
void ADC_DMA_ENABLE(uint16_t cndtr);
void ADC_SHOW();

#endif
//main.c
//精英开发板
//PA1采集电位器电压,DMA采集
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "ADC.h"

extern uint16_t adc_dma_buf[ADC_DMA_BUF_SIZE];
int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
	KEY_Init();						// 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");
	ADC_Init((uint32_t)&adc_dma_buf);
	LCD_ShowString(30, 110, 200, 16, 16, "ADC1_CH1_VAL:");
	LCD_ShowString(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V"); /* 先在固定位置显示小数点 */
	ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE);
	while (1)
	{
		ADC_SHOW();
	}
}

多通道ADC采集(DMA读取)配置步骤

//ADC.c
#include "ADC.h"

DMA_HandleTypeDef DMA_handler;             // DMA句柄
ADC_HandleTypeDef ADC_Handler;             // ADC句柄
ADC_ChannelConfTypeDef ADC_Channel_Config; // ADC通道配置
uint8_t ADC_DMA_STA;                       // ADC_DMA标志

void ADC_Init(uint32_t mar)
{
    __HAL_RCC_DMA1_CLK_ENABLE();                                    // 使能DMA1时钟
    DMA_handler.Instance = DMA1_Channel1;                           // DMA1通道1
    DMA_handler.Init.Direction = DMA_PERIPH_TO_MEMORY;              // DMA传输方向:外设向寄存器
    DMA_handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;    // DMA寄存器数据长度:半字
    DMA_handler.Init.MemInc = DMA_MINC_ENABLE;                      // DMA寄存器地址增量
    DMA_handler.Init.Mode = DMA_NORMAL;                             // DMA不开启循环模式
    DMA_handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // DMA外设数据长度:半字
    DMA_handler.Init.PeriphInc = DMA_PINC_DISABLE;                  // DMA外设地址不增量
    DMA_handler.Init.Priority = DMA_PRIORITY_VERY_HIGH;             // 优先级非常高
    HAL_DMA_Init(&DMA_handler);                                     // DMA初始化,,回调HAL_ADC_MspInit()
    __HAL_LINKDMA(&ADC_Handler, DMA_Handle, DMA_handler);           // 将DMA结构体成员赋予ADC结构体中的DMA

    ADC_Handler.Instance = ADC1;                            // ADC1
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_ENABLE;        // 使用扫描模式
    ADC_Handler.Init.ContinuousConvMode = ENABLE;           // 连续模式
    ADC_Handler.Init.NbrOfConversion = 6;                   // 通道数量6
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不开启间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 间断模式的规则通道数0
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_Channel_Config.Channel = ADC_CHANNEL_0;                   // 通道0
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_1;                 // 顺序1
    ADC_Channel_Config.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采样周期:239.5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config);     // ADC通道配置

    ADC_Channel_Config.Channel = ADC_CHANNEL_1;               // 通道1
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_2;             // 顺序2
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config); // ADC通道配置

    ADC_Channel_Config.Channel = ADC_CHANNEL_2;               // 通道2
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_3;             // 顺序3
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config); // ADC通道配置

    ADC_Channel_Config.Channel = ADC_CHANNEL_3;               // 通道3
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_4;             // 顺序4
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config); // ADC通道配置

    ADC_Channel_Config.Channel = ADC_CHANNEL_4;               // 通道4
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_5;             // 顺序5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config); // ADC通道配置

    ADC_Channel_Config.Channel = ADC_CHANNEL_5;               // 通道5
    ADC_Channel_Config.Rank = ADC_REGULAR_RANK_6;             // 顺序6
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_Config); // ADC通道配置

    HAL_DMA_Start_IT(&DMA_handler, (uint32_t)&ADC1->DR, mar, 0); // 使能DMA,开启数据流传输完成中断
    HAL_ADC_Start_DMA(&ADC_Handler, &mar, 0);                    // 使能ADC,开启ADC-DMA通道
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1) // 判断是不是ADC1
    {
        GPIO_InitTypeDef GPIO_InitStructure;               // GPIO初始化结构体
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLKInitStructure; // ADC时钟配置结构体

        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA
        __HAL_RCC_ADC1_CLK_ENABLE();  // 使能ADC1

        GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;                                                           // 模拟功能
        GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; // PA0,PA1,PA2,PA3,PA4,PA5
        GPIO_InitStructure.Pull = GPIO_NOPULL;                                                                // 不上下拉
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;                                                      // 高速
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);                                                            // GPIO结构体初始化

        RCC_ADC_CLKInitStructure.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设时钟:ADC
        RCC_ADC_CLKInitStructure.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // ADC时钟6分频
        HAL_RCCEx_PeriphCLKConfig(&RCC_ADC_CLKInitStructure);              // ADC时钟配置

        HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3); // 设置DMA1通道1数据流传输完成中断
        HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);         // 使能DMA1通道1数据流传输完成中断
    }
}

void ADC_DMA_ENABLE(uint16_t cndtr)
{
    __HAL_ADC_DISABLE(&ADC_Handler); // ADC失能
    __HAL_DMA_DISABLE(&DMA_handler); // DMA失能

    while (DMA1_Channel1->CCR & (1 << 0)) // 等待DMA允许传输完成中断
        ;
    DMA1_Channel1->CNDTR = cndtr; // 写入DMA传输数量

    __HAL_ADC_ENABLE(&ADC_Handler); // 使能ADC
    __HAL_DMA_ENABLE(&DMA_handler); // 使能DMA
    HAL_ADC_Start(&ADC_Handler);    // 开启ADC
}

void DMA1_Channel1_IRQHandler()
{
    if (DMA1->ISR & (1 << 1)) // 判断DMA1传输完成
    {
        ADC_DMA_STA = 1;      // ADC_DMA标志
        DMA1->IFCR |= 1 << 1; // 清除DMA1传输完成中断标志
    }
}

uint16_t i, j;
uint16_t adcx;
uint32_t sum;
float temp;
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA BUF */

void ADC_SHOW()
{
    if (ADC_DMA_STA == 1)
    {
        for (j = 0; j < 6; j++) /* 遍历6个通道 */
        {
            sum = 0;                                   /* 清零 */
            for (i = 0; i < ADC_DMA_BUF_SIZE / 6; i++) /* 每个通道采集了50次数据,进行50次累加 */
            {
                sum += g_adc_dma_buf[(6 * i) + j]; /* 相同通道的转换数据累加 */
            }
            adcx = sum / (ADC_DMA_BUF_SIZE / 6); /* 取平均值 */

            /* 显示结果 */
            LCD_ShowxNum(108, 110 + (j * 30), adcx, 4, 12, 0); /* 显示ADC采样后的原始值 */

            temp = (float)adcx * (3.3 / 4096);                 /* 获取计算后的带小数的实际电压值,比如3.1111 */
            adcx = temp;                                       /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
            LCD_ShowxNum(108, 122 + (j * 30), adcx, 1, 12, 0); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */

            temp -= adcx;                                         /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
            temp *= 1000;                                         /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
            LCD_ShowxNum(120, 122 + (j * 30), temp, 3, 12, 0X80); /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
        }
        ADC_DMA_STA = 0;                  /* 清除DMA采集完成状态标志 */
        ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE); /* 启动下一次ADC DMA采集 */
    }
}
//ADC.h
#ifndef __ADC_H
#define __ADC_H

#include "sys.h"
#include "lcd.h"
void ADC_Init(uint32_t mar);
void ADC_DMA_ENABLE(uint16_t cndtr);
void ADC_SHOW();

#define ADC_DMA_BUF_SIZE 50 * 6 /* ADC DMA采集 BUF大小, 应等于ADC通道数的整数倍 */

#endif
//main.c
//精英开发板
//PA0,PA1,PA2,PA3,PA4,PA5采集电压,DMA读取
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "ADC.h"

extern uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];
int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
    KEY_Init();                     // 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");

	ADC_Init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */

	LCD_ShowString(30, 110, 200, 12, 12, "ADC1_CH0_VAL:");
	LCD_ShowString(30, 122, 200, 12, 12, "ADC1_CH0_VOL:0.000V"); /* 先在固定位置显示小数点 */

	LCD_ShowString(30, 140, 200, 12, 12, "ADC1_CH1_VAL:");
	LCD_ShowString(30, 152, 200, 12, 12, "ADC1_CH1_VOL:0.000V"); /* 先在固定位置显示小数点 */

	LCD_ShowString(30, 170, 200, 12, 12, "ADC1_CH2_VAL:");
	LCD_ShowString(30, 182, 200, 12, 12, "ADC1_CH2_VOL:0.000V"); /* 先在固定位置显示小数点 */

	LCD_ShowString(30, 200, 200, 12, 12, "ADC1_CH3_VAL:");
	LCD_ShowString(30, 212, 200, 12, 12, "ADC1_CH3_VOL:0.000V"); /* 先在固定位置显示小数点 */

	LCD_ShowString(30, 230, 200, 12, 12, "ADC1_CH4_VAL:");
	LCD_ShowString(30, 242, 200, 12, 12, "ADC1_CH4_VOL:0.000V"); /* 先在固定位置显示小数点 */

	LCD_ShowString(30, 260, 200, 12, 12, "ADC1_CH5_VAL:");
	LCD_ShowString(30, 272, 200, 12, 12, "ADC1_CH5_VOL:0.000V"); /* 先在固定位置显示小数点 */

	ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE); /* 启动ADC DMA采集 */

	while (1)
	{
		ADC_SHOW();
	}
}

单通道ADC过采样

//ADC.c
#include "ADC.h"

DMA_HandleTypeDef DMA_Handler;             // DMA句柄
ADC_HandleTypeDef ADC_Handler;             // ADC句柄
ADC_ChannelConfTypeDef ADC_Channel_config; // ADC通道配置
uint8_t ADC_DMA_STA = 0;                   // ADC_DMA传输完成标志

void ADC_Init(uint32_t mar)
{
    __HAL_RCC_DMA1_CLK_ENABLE();                                    // 使能DMA1
    DMA_Handler.Instance = DMA1_Channel1;                           // DMA1通道1
    DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;              // DMA传输方向:外设到寄存器
    DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;    // DMA寄存器数据长度:半字
    DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                      // 寄存器地址增量
    DMA_Handler.Init.Mode = DMA_NORMAL;                             // DMA不循环模式
    DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // DMA外设数据长度:半字
    DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;                  // 外设地址不增量
    DMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;                  // 高优先级
    HAL_DMA_Init(&DMA_Handler);                                     // DMA初始化
    __HAL_LINKDMA(&ADC_Handler, DMA_Handle, DMA_Handler);           // 将DMA结构体赋予ADC结构体中的DMA

    ADC_Handler.Instance = ADC1;                            // ADC1
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_DISABLE;       // 不扫描模式
    ADC_Handler.Init.ContinuousConvMode = ENABLE;           // 连续模式
    ADC_Handler.Init.NbrOfConversion = 1;                   // 转换通道数目:1
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 间断模式规则通道数目0
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化,回调HAL_ADC_MspInit()
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_Channel_config.Channel = ADC_CHANNEL_1;                // 通道1
    ADC_Channel_config.Rank = ADC_REGULAR_RANK_1;              // 顺序1
    ADC_Channel_config.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; // 采样周期:239.5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_Channel_config);  // ADC通道配置

    HAL_DMA_Start_IT(&DMA_Handler, (uint32_t)&ADC1->DR, mar, 0); // 使能DMA,开启数据流传输完成中断
    HAL_ADC_Start_DMA(&ADC_Handler, &mar, 0);                    // 使能ADC,开启ADC-DMA通道
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1) // 判断是不是ADC1
    {
        GPIO_InitTypeDef GPIO_InitStructure;                // GPIO初始化结构体
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLK_InitStructure; // ADC时钟初始化结构体

        __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
        __HAL_RCC_ADC1_CLK_ENABLE();  // 使能ADC1时钟

        GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;      // 模拟功能
        GPIO_InitStructure.Pin = GPIO_PIN_1;             // PA1
        GPIO_InitStructure.Pull = GPIO_NOPULL;           // 不上下拉
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);       // GPIO初始化

        RCC_ADC_CLK_InitStructure.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设时钟:ADC
        RCC_ADC_CLK_InitStructure.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // ADC时钟6分频
        HAL_RCCEx_PeriphCLKConfig(&RCC_ADC_CLK_InitStructure);              // ADC外设时钟配置

        HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3); // 设置DMA1通道1数据流传输完成中断
        HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);         // 使能DMA1通道1数据流传输完成中断
    }
}

void ADC_DMA_ENABLE(uint16_t cndtr)
{
    __HAL_ADC_DISABLE(&ADC_Handler); // ADC失能
    __HAL_DMA_DISABLE(&DMA_Handler); // DMA失能

    while (DMA1_Channel1->CCR & (1 << 0)) // 等待DMA允许传输完成中断
        ;
    DMA1_Channel1->CNDTR = cndtr;   // 写入DMA1通道1数目
    __HAL_ADC_ENABLE(&ADC_Handler); // 使能ADC
    __HAL_DMA_ENABLE(&DMA_Handler); // 使能DMA

    HAL_ADC_Start(&ADC_Handler); // 开启ADC
}

void DMA1_Channel1_IRQHandler()
{
    if (DMA1->ISR & (1 << 1)) // 判断DMA1传输完成
    {
        ADC_DMA_STA = 1;      // ADC_DMA标志
        DMA1->IFCR |= 1 << 1; // 清除DMA1传输完成标志位
    }
}

uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA BUF */
uint16_t i;
uint32_t adcx;
uint32_t sum;
float temp;

void ADC_SHOW()
{
    if (ADC_DMA_STA == 1)
    {
        /* 计算DMA 采集到的ADC数据的平均值 */
        sum = 0;

        for (i = 0; i < ADC_DMA_BUF_SIZE; i++) /* 累加 */
        {
            sum += g_adc_dma_buf[i];
        }

        adcx = sum / (ADC_DMA_BUF_SIZE / ADC_OVERSAMPLE_TIMES); /* 取平均值 */
        adcx >>= 4;                                             /* 除以2^4倍, 得到12+4位 ADC精度值, 注意: 提高 N bit精度, 需要 >> N */

        /* 显示结果 */
        LCD_ShowxNum(134, 110, adcx, 5, 16, 0); /* 显示ADC采样后的原始值 */
        temp = (float)adcx * (3.3 / 65536);     /* 获取计算后的带小数的实际电压值,比如3.1111 */
        adcx = temp;                            /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
        LCD_ShowxNum(134, 130, adcx, 1, 16, 0); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */

        temp -= adcx;                              /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
        temp *= 1000;                              /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
        LCD_ShowxNum(150, 130, temp, 3, 16, 0X80); /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */

        ADC_DMA_STA = 0;                  /* 清除DMA采集完成状态标志 */
        ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE); /* 启动下一次ADC DMA采集 */
    }
}
//ADC.h
#ifndef __ADC_H
#define __ADC_H

#include "sys.h"
#include "lcd.h"
#define ADC_OVERSAMPLE_TIMES 256                   /* ADC过采样次数, 这里提高4bit分辨率, 需要256倍采样 */
#define ADC_DMA_BUF_SIZE      ADC_OVERSAMPLE_TIMES * 10 /* ADC DMA采集 BUF大小, 应等于过采样次数的整数倍 */

void ADC_Init(uint32_t mar);
void ADC_DMA_ENABLE(uint16_t cndtr);
void ADC_SHOW();

#endif
//main.c
//精英开发板
//PA1采集电压,用过采样256倍分辨率提高4位,总共16位
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "ADC.h"

extern uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA BUF */

int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
    KEY_Init();                     // 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");

	ADC_Init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */
	LCD_ShowString(30, 110, 200, 16, 16, "ADC1_CH1_VAL:");
	LCD_ShowString(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V"); /* 先在固定位置显示小数点 */	
	ADC_DMA_ENABLE(ADC_DMA_BUF_SIZE); /* 启动ADC DMA采集 */

	while (1)
	{
		ADC_SHOW();
	}
}

内部温度传感器

STM32内部温度传感器简介

主要特性

F1

F4

F7

H7

温度范围

-40~125℃

精度(MAX)

±2℃

±3℃

采样时间

≥17.1us

≥10us

≥9us

ADC通道

ADC1_IN16

ADC1_IN16(F407)

ADC1_IN18(F429)

ADC1_IN18

ADC3_INP18

上电控制位

TSVREFE

VSENSEEN

F1温度计算方法

F4/F7温度计算方法

H7温度计算方法

//Temp.c
#include "TEMP.h"

ADC_HandleTypeDef ADC_Handler;            // ADC句柄
ADC_ChannelConfTypeDef ADC_ChannelConfig; // ADC通道配置句柄

void TEMP_Init()
{
    ADC_Handler.Instance = ADC1;                            // ADC1
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_DISABLE;       // 不开启扫描模式
    ADC_Handler.Init.ContinuousConvMode = ENABLE;           // 连续模式
    ADC_Handler.Init.NbrOfConversion = 1;                   // 通道数量1
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 不间断模式规则通道数目0
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化,回调HAL_ADC_MspInit()
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_ChannelConfig.Channel = ADC_CHANNEL_16;                  // ADC通道16
    ADC_ChannelConfig.Rank = ADC_REGULAR_RANK_1;                 // 顺序1
    ADC_ChannelConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采集周期:239.5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_ChannelConfig);     // ADC通道配置
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC1) // 判断是不是ADC1
    {
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLK_InitStructure; // ADC时钟初始化结构体

        __HAL_RCC_ADC1_CLK_ENABLE(); // 使能ADC1

        RCC_ADC_CLK_InitStructure.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设选择:ADC
        RCC_ADC_CLK_InitStructure.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // ADC时钟6分频
        HAL_RCCEx_PeriphCLKConfig(&RCC_ADC_CLK_InitStructure);              // ADC时钟配置初始化
    }
}

uint32_t ADC_GET()
{
    HAL_ADC_Start(&ADC_Handler);                 // 开启ADC1
    HAL_ADC_PollForConversion(&ADC_Handler, 10); // 等待ADC转化,10ms
    return HAL_ADC_GetValue(&ADC_Handler);       // 返回ADC获得值
}

uint16_t ADC_GET_TEMP()
{
    uint32_t adcx;
    uint16_t result;
    double TEMP;

    adcx = ADC_GET();                   
    TEMP = adcx * 3.3 / 4096;           // 电压值
    TEMP = (1.43 - TEMP) / 0.0043 + 25; // 温度值
    result = TEMP * 100;                // 温度值摄氏度
    return result;
}

void TEMP_SHOW()
{
    uint16_t TEMP;
    TEMP = ADC_GET_TEMP(); /* 得到温度值 */
    if (TEMP < 0)
    {
        TEMP = -TEMP;
        LCD_ShowString(30 + 10 * 8, 120, 16, 16, 16, "-"); /* 显示负号 */
    }
    else
    {
        LCD_ShowString(30 + 10 * 8, 120, 16, 16, 16, " "); /* 无符号 */
    }
    LCD_ShowxNum(30 + 11 * 8, 120, TEMP / 100, 2, 16, 0);    /* 显示整数部分 */
    LCD_ShowxNum(30 + 14 * 8, 120, TEMP % 100, 2, 16, 0X80); /* 显示小数部分 */
}
//Temp.h
#ifndef __TEMP_H
#define __TEMP_H

#include "sys.h"
#include "lcd.h"
void TEMP_Init();
uint32_t ADC_GET();
uint16_t ADC_GET_TEMP();
void TEMP_SHOW();

#endif
//main.c
//精英开发板
//采集ADC1通道16的电压,进而换算成温度
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "Temp.h"

int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
    KEY_Init();                     // 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");
	TEMP_Init();
	LCD_ShowString(30, 70, 200, 16, 16, "Temperature TEST");
	LCD_ShowString(30, 120, 200, 16, 16, "TEMPERATE: 00.00C");
	while (1)
	{
		TEMP_SHOW();
		LED0 = 1;
	}
}

光敏传感器实验

光敏二极管简介

//LightSensor.C
#include "LightSensor.h"

ADC_HandleTypeDef ADC_Handler;            // ADC句柄
ADC_ChannelConfTypeDef ADC_ChannelConfig; // ADC通道配置

void ADC_Init()
{
    ADC_Handler.Instance = ADC3;                            // ADC3
    ADC_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
    ADC_Handler.Init.ScanConvMode = ADC_SCAN_DISABLE;       // 不开启扫描模式
    ADC_Handler.Init.ContinuousConvMode = ENABLE;           // 不开启连续模式
    ADC_Handler.Init.NbrOfConversion = 1;                   // 通道数目1
    ADC_Handler.Init.DiscontinuousConvMode = DISABLE;       // 不间断模式
    ADC_Handler.Init.NbrOfDiscConversion = 0;               // 间断模式规则通道数目0
    ADC_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
    HAL_ADC_Init(&ADC_Handler);                             // ADC初始化,回调HAL_ADC_MspInit()
    HAL_ADCEx_Calibration_Start(&ADC_Handler);              // ADC校准

    ADC_ChannelConfig.Channel = ADC_CHANNEL_6;                   // ADC通道6
    ADC_ChannelConfig.Rank = ADC_REGULAR_RANK_1;                 // 顺序1
    ADC_ChannelConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采集周期:239.5
    HAL_ADC_ConfigChannel(&ADC_Handler, &ADC_ChannelConfig);     // ADC通道配置
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == ADC3) // 判断是不是ADC3
    {
        GPIO_InitTypeDef GPIO_InitStructure;       // GPIO初始化结构体
        RCC_PeriphCLKInitTypeDef RCC_ADC_CLK_Init; // ADC时钟配置结构体

        __HAL_RCC_GPIOF_CLK_ENABLE(); // 使能GPIOF时钟
        __HAL_RCC_ADC3_CLK_ENABLE();  // 使能ADC3时钟

        GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;     // 模拟功能
        GPIO_InitStructure.Pin = GPIO_PIN_8;            // PF9,ADC1通道6
        GPIO_InitStructure.Pull = GPIO_NOPULL;          // 不上下拉
        GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; // 高速
        HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);

        RCC_ADC_CLK_Init.PeriphClockSelection = RCC_PERIPHCLK_ADC; // 外设时钟:ADC
        RCC_ADC_CLK_Init.AdcClockSelection = RCC_ADCPCLK2_DIV6;    // ADC时钟6分频
        HAL_RCCEx_PeriphCLKConfig(&RCC_ADC_CLK_Init);              // ADC时钟配置
    }
}

uint32_t ADC_GET()
{
    HAL_ADC_Start(&ADC_Handler);                 // 开启ADC
    HAL_ADC_PollForConversion(&ADC_Handler, 10); // 等待ADC转化,10ms
    return HAL_ADC_GetValue(&ADC_Handler);       // 返回ADC获得值
}

void LIGHT_SHOW()
{
    uint32_t TEMP;
    uint32_t LIGHT;

    TEMP = ADC_GET();
    TEMP /= 40;
    if (TEMP > 100)
        TEMP = 100;
    LIGHT = 100 - TEMP;                              // 光照强度值
    LCD_ShowxNum(30 + 10 * 8, 110, LIGHT, 3, 16, 0); /* 显示ADC的值 */
}
//LightSensor.h
#ifndef __LIGHTSENSOR_H
#define __LIGHTSENSOR_H

#include "sys.h"
#include "lcd.h"
void ADC_Init();
uint32_t ADC_GET();
void LIGHT_SHOW();

#endif
//main.c
//精英开发板
//采集PF8,ADC3通道6的电压,进而换算成0-100的光线强度
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "usmart.h"
#include "KEY.h"
#include "led.h"
#include "lcd.h"
#include "LightSensor.h"

int main(void)
{
	HAL_Init();						// 初始化HAL库
	Stm32_Clock_Init(RCC_PLL_MUL9); // 设置时钟,72M
	delay_init(72);					// 初始化延时函数
	uart_init(115200);				// 初始化串口
    KEY_Init();                     // 初始化按键
	LED_Init();						// 初始化LED
	LCD_Init();						// 初始化LCD FSMC接口
	usmart_dev.init(84);			// 初始化USMART
	POINT_COLOR = RED;				// 画笔颜色:红色
	LCD_ShowString(30, 50, 200, 16, 16, " YMZ ^_^");
	ADC_Init();
	LCD_ShowString(30, 110, 200, 16, 16, "LSENS_VAL:");
	while (1)
	{
		LIGHT_SHOW();
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

油门子z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值