A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组)
规则组最多可以有16个转换,注入组最多有4个转换
规则组和注入组执行优先级对比
触发转换的方法有两种:
(1)ADON位触发转换(仅限F1系列)
当ADC_CR2寄存器的ADON位为1时,再单独给ADON位写1,只能启动规则组转换
(2)外部事件触发转换
外部事件触发转换分为:规则组外部触发和注入组外部触发
不同模式组合的作用
实验需要用杜邦线把RV1和ADC给连接起来
1,功能描述
通过ADC1通道1(PA1)采集电位器的电压,并显示ADC转换的数字量及换算后的电压值
2,确定最小刻度
VREF+ = 3.3V 0V≤VIN≤3.3V 最小刻度 = 3.3 / 4096 F4/F7/H7系列还需要考虑ADC分辨率
3,确定转换时间
采样时间239.5个ADC时钟周期为例,可以得到转换时间为21us
4,模式组合
单次转换模式、不使用扫描模式
1,配置ADC工作参数、ADC校准
HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
2,ADC MSP初始化
HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
3,配置ADC相应通道相关参数
HAL_ADC_ConfigChannel()
4,启动A/D转换
HAL_ADC_Start()
5,等待规则通道转换完成
HAL_ADC_PollForConversion()
6,获取规则通道A/D转换结果
HAL_ADC_GetValue()
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;
#include "./BSP/ADC/adc.h"
ADC_HandleTypeDef g_adc_handle;
/* ADC单通道*/
void adc_init(void)
{
ADC_ChannelConfTypeDef adc_ch_conf = {0};
g_adc_handle.Instance = ADC1;
g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;
g_adc_handle.Init.ContinuousConvMode = DISABLE;
g_adc_handle.Init.NbrOfConversion = 1;
g_adc_handle.Init.DiscontinuousConvMode = DISABLE;
g_adc_handle.Init.NbrOfDiscConversion = 0;
g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件触发
HAL_ADC_Init(&g_adc_handle);
HAL_ADCEx_Calibration_Start(&g_adc_handle);
adc_ch_conf.Channel = ADC_CHANNEL_1;
adc_ch_conf.Rank = ADC_REGULAR_RANK_1;
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_handle, &adc_ch_conf);
}
/* ADC MSP初始换函数*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_1;
gpio_init_struct.Mode = GPIO_MODE_ANALOG; /* 模拟功能 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化LED0引脚 */
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);
}
}
/* 获得ADC转换后的结果函数*/
uint32_t adc_get_result(void)
{
HAL_ADC_Start(&g_adc_handle);
HAL_ADC_PollForConversion(&g_adc_handle, 10);
return (uint16_t)HAL_ADC_GetValue(&g_adc_handle);
}
#ifndef __ADC_H
#define __ADC_H
#include "./SYSTEM/sys/sys.h"
void adc_init(void);
uint32_t adc_get_result(void);
#endif
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
int main(void)
{
uint16_t adcx;
float temp;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
adc_init();
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);
lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */
while (1)
{
adcx = adc_get_result();
lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE); /* 显示ADCC采样后的原始值 */
temp = (float)adcx * (3.3 / 4096); /* 获取计算后的带小数的实际电压值,比如3.1111 */
adcx = temp; /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */
temp -= adcx; /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
temp *= 1000; /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE);/* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
LED0_TOGGLE();
delay_ms(100);
}
}
1,功能描述 (通过DMA读取数据)
通过ADC1通道1(PA1)采集电位器的电压,并显示ADC转换的数字量及换算后的电压值
2,确定最小刻度
VREF+ = 3.3V 0V≤VIN≤3.3V 最小刻度 = 3.3 / 4096 (F4/F7/H7系列还需要考虑ADC分辨率)
3,确定转换时间
采样时间239.5个ADC时钟周期为例,可以得到转换时间为21us
4,模式组合
连续转换模式、不使用扫描模式
1,初始化DMA
HAL_DMA_Init()
2,将DMA和ADC句柄联系起来
__HAL_LINKDMA()
3,配置ADC工作参数、ADC校准
HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
4,ADC MSP初始化
HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
5,配置ADC相应通道相关参数
HAL_ADC_ConfigChannel()
6,使能DMA数据流传输完成中断
HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
7,编写DMA数据流中断服务函数
DMAx_Channely_IRQHandler()
8,启动DMA,开启传输完成中断
HAL_DMA_Start_IT()
9,触发ADC转换,DMA传输数据
HAL_ADC_Start_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;
#include "./BSP/ADC/adc.h"
DMA_HandleTypeDef g_dma_adc_handle;
ADC_HandleTypeDef g_adc_dma_handle;
uint8_t g_adc_dma_sta;
/* ADC DMA读取 初始化函数 */
void adc_dma_init(uint32_t mar)
{
ADC_ChannelConfTypeDef adc_ch_conf;
__HAL_RCC_DMA1_CLK_ENABLE();
g_dma_adc_handle.Instance = DMA1_Channel1;
g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;
g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;
g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.Mode = DMA_NORMAL;
g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&g_dma_adc_handle);
__HAL_LINKDMA(&g_adc_dma_handle, DMA_Handle, g_dma_adc_handle);
g_adc_dma_handle.Instance = ADC1;
g_adc_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
g_adc_dma_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;
g_adc_dma_handle.Init.ContinuousConvMode = ENABLE;
g_adc_dma_handle.Init.NbrOfConversion = 1;
g_adc_dma_handle.Init.DiscontinuousConvMode = DISABLE;
g_adc_dma_handle.Init.NbrOfDiscConversion = 0;
g_adc_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
HAL_ADC_Init(&g_adc_dma_handle);
HAL_ADCEx_Calibration_Start(&g_adc_dma_handle);
adc_ch_conf.Channel = ADC_CHANNEL_1;
adc_ch_conf.Rank = ADC_REGULAR_RANK_1;
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_dma_handle, &adc_ch_conf);
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, mar, 0);
HAL_ADC_Start_DMA(&g_adc_dma_handle, &mar ,0);
}
/* ADC MSP初始化函数 */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
GPIO_InitTypeDef gpio_init_struct;
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_1;
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);
}
}
/* 使能一次ADC DMA传输函数 */
void adc_dma_enable(uint16_t cndtr)
{
// ADC1->CR2 &= ~(1 << 0);
//
// DMA1_Channel1->CCR &= ~(1 << 0);
// while (DMA1_Channel1->CCR & (1 << 0));
// DMA1_Channel1->CNDTR = cndtr;
// DMA1_Channel1->CCR |= 1 << 0;
// ADC1->CR2 |= 1 << 0;
// ADC1->CR2 |= 1 << 22;
__HAL_ADC_DISABLE(&g_adc_dma_handle);
__HAL_DMA_DISABLE(&g_dma_adc_handle);
while (__HAL_DMA_GET_FLAG(&g_dma_adc_handle, __HAL_DMA_GET_TC_FLAG_INDEX(&g_dma_adc_handle)));
DMA1_Channel1->CNDTR = cndtr;
__HAL_DMA_ENABLE(&g_dma_adc_handle);
__HAL_ADC_ENABLE(&g_adc_dma_handle);
HAL_ADC_Start(&g_adc_dma_handle);
}
/* ADC DMA采集中断服务函数 */
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & (1<<1))
{
g_adc_dma_sta = 1;
DMA1->IFCR |= 1 << 1;
}
}
#ifndef __ADC_H
#define __ADC_H
#include "./SYSTEM/sys/sys.h"
void adc_dma_init(uint32_t mar);
void adc_dma_enable(uint16_t cndtr);
#endif
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#define ADC_DMA_BUF_SIZE 100 /* ADC DMA采集 BUF大小 */
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA BUF */
extern uint8_t g_adc_dma_sta; /* DMA传输状态标志, 0,未完成; 1, 已完成 */
int main(void)
{
uint16_t i;
uint16_t adcx;
uint32_t sum;
float temp;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
adc_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "ADC DMA TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);
lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */
adc_dma_enable(ADC_DMA_BUF_SIZE); /* 启动ADC DMA采集 */
while (1)
{
if (g_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; /* 取平均值 */
/* 显示结果 */
lcd_show_xnum(134, 110, adcx, 4, 16, 0, BLUE); /* 显示ADCC采样后的原始值 */
temp = (float)adcx * (3.3 / 4096); /* 获取计算后的带小数的实际电压值,比如3.1111 */
adcx = temp; /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE); /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */
temp -= adcx; /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
temp *= 1000; /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE); /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
g_adc_dma_sta = 0; /* 清除DMA采集完成状态标志 */
adc_dma_enable(ADC_DMA_BUF_SIZE); /* 启动下一次ADC DMA采集 */
}
LED0_TOGGLE();
delay_ms(100);
}
}
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数