泓泰

怎么解决esp32adc十二位分辨率,adc函数库

admin

本文目录一览

怎么解决esp32adc十二位分辨率

怎么解决esp32adc十二位分辨率,adc函数库-第1张-游戏信息-泓泰

这个实验的功能演示 ESP32 ADC 的使用方法。 这个实验的代码为工程“3_11_adc”目录。

3.11.1. 实验内容

(1) 学习 ESP32 ADC 功能的使用
(2) 学习光敏电阻的使用
(3) 学习显示屏的使用

3.11.2. 硬件设计和原理

打开我们提供的电路图,在文件:\原理图\ESP32 开发板电路图 V1.3.pdf 里,
光敏电阻的特性是有光照的时候,电阻会变小。上图中 R15 是光敏电阻,在没有光照射到光敏电阻的 情况下,R15 的阻值是无限大,ADC 采集到最大的电压也就是 R9 和 R10 的分压,即是 1.06V,当有光照射 到光敏电阻的情况下,光照越强,ADC 采集到的电压越低。
从上面的原理图可以看出,光敏电阻的 ADC 采集通过拨码开关后,是接在 IO34 上的,使用 ADC 光敏 时一定要打开底板上的拨码开关7,如下图:

ESP32 有 2 个 12 位的 ADC,共计 18 通道,ADC2 比较特殊的一点就是:ADC2 和 wifi 共用,wifi 的优 先级更高,所以 ADC2 只有在 WIFI 模块不用的情况下可以使用。
ESP32 的 18 个通道的 ADC 如下:

打开我们提供的另一个文档:.\手册和文档\ESP32-S_产品规格书.pdf,关于管脚定义部分,

通过上图,我们知道接光敏电阻的 IO34 是接在 ADC1 的第 6 通道上,写代码的时候我们对 ADC1 的第
6 通道编程,就可以取出光照强度。

3.11.3. ESP32 ADC 函数介绍

? 配置 ADC
对于 ADC1,通过调用函数 adc1_config_width() 和 adc1_config_channel_atten() 来配置所需的精度和衰减。
函数定义:
esp_err_t adc1_config_width(adc_bits_width_t width_bit); 参数说明:
adc_bits_width_t width_bit:设置 ADC 的分辨率,这是一个枚举,具体定义在后面有说明 返回值:ESP_OK(成功)。

typedef enum {
ADC_WIDTH_BIT_9 = 0, //ADC 的分辨率是 9 位,即最大值为 2 的 9 次方,即 512
ADC_WIDTH_BIT_10 = 1, //ADC 的分辨率是 10 位,即最大值为 2 的 10 次方,即 1024
ADC_WIDTH_BIT_11 = 2, //ADC 的分辨率是 11 位,即最大值为 2 的 11 次方,即 2048
ADC_WIDTH_BIT_12 = 3, //ADC 的分辨率是 12 位,即最大值为 2 的 12 次方,即 4096 ADC_WIDTH_MAX,
} adc_bits_width_t;1234567

函数定义:
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten); 参数说明:
adc1_channel_t channel:配置 ADC 的通道,这是一个枚举,具体定义在后面有说明 adc_atten_t atten:配置 ADC 的参考电压,这是一个枚举,具体定义在后面有说明
返回值:ESP_OK(成功)。

typedef enum {
ADC1_CHANNEL_0 = 0, /*! ADC1 channel 0 is
ADC1_CHANNEL_1,
ADC1_CHANNEL_2, ADC1_CHANNEL_3, ADC1_CHANNEL_4, ADC1_CHANNEL_5, ADC1_CHANNEL_6, ADC1_CHANNEL_7, ADC1_CHANNEL_MAX,
} adc1_channel_t;
ADC_ATTEN_DB_2_5 = 1,
ADC_ATTEN_DB_6 = 2,
ADC_ATTEN_DB_11 =
12345678

对于 ADC2,通过 adc2_config_channel_atten() 配置衰减. 每次读取时都会配置 ADC2 的读取宽度。
函数定义:
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten); 参数说明:
adc2_channel_t channel:配置 ADC 的通道,这是一个枚举,具体定义在后面有说明 adc_atten_t atten:配置 ADC 的参考电压,这是一个枚举,在 ADC1 配置函数里有说明
返回值:ESP_OK(成功)。

typedef enum {
ADC2_CHANNEL_0 = 0, /*! ADC2 channel 0 is GPIO4 */ ADC2_CHANNEL_1, /*! ADC2 channel 1 is GPIO0 */ ADC2_CHANNEL_2, /*! ADC2 channel 2 is GPIO2 */ ADC2_CHANNEL_3, /*! ADC2 channel 3 is GPIO15 */ ADC2_CHANNEL_4, /*! ADC2 channel 4 is GPIO13 */ ADC2_CHANNEL_5, /*! ADC2 channel 5 is GPIO12 */
ADC2_CHANNEL_6, /*! ADC2 channel 6 is GPIO14 */ ADC2_CHANNEL_7, /*! ADC2 channel 7 is GPIO27 */ ADC2_CHANNEL_8, /*! ADC2 channel 8 is GPIO25 */ ADC2_CHANNEL_9, /*! ADC2 channel 9 is GPIO26 */ ADC2_CHANNEL_MAX,
} adc2_channel_t;12345

? 读取 ADC
对于 ADC1,读取函数有两个,他们的参数和返回值是完全一样的,二选一使用即可,定义如下:
int adc1_get_voltage(adc1_channel_t channel); int adc1_get_raw(adc1_channel_t channel); 参数说明:
adc1_channel_t channel:配置 ADC 的通道,这是一个枚举,在 ADC1 配置函数里有说明 返回值:采样到通道的 ADC 值。

对于 ADC2,使用下面的函数读取 ADC 值,定义如下:
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* raw_out); 参数说明:
adc2_channel_t channel:配置 ADC2 的通道号,这是一个枚举,在 ADC2 配置函数里有说明 adc_bits_width_t width_bit:设置 ADC 的分辨率
int* raw_out:这是一个返回值,表示读取到的 ADC 值 返回值:ESP_OK(成功),ESP_ERR_TIMEOUT(wifi 正在使用)。
3.11.4. 代码讲解

使用 vs code 展开本实验的工程目录,如下图:

我们的这个实验,ADC 采集的代码是写在源文件 app_main.c 里,components 文件夹是关于 LCD 的驱 动代码,LCD 显示屏在 3.4 章有比较详情的讲解。
我们打开 app_main.c,首先看 ADC 的初始化:

void adc_Init()
{
//12 位分辨率 adc1_config_width(ADC_WIDTH_12Bit);1234

99

//设置通道 6 和 1.1V 参考电压 adc1_config_channel_atten(ADC1_TEST_CHANNEL,ADC_ATTEN_0db);
}
其中 ADC1_TEST_CHANNEL 定义如图:
//ADC 所接的通道
#define ADC1_TEST_CHANNEL ADC1_CHANNEL_6

接着看 app_main()主函数,函数里初始化了 LCD 和 ADC,然后通过 while(1)周期读取 ADC 的值,代 码如下:

//用户函数入口,相当于 main 函数
void app_main()
{
int read_raw;
char adc_buff[50]={0};

//显示屏初始化 Lcd_Init(); adc_Init();

//显示屏提示信息
.......略......;
while(1)
{
read_raw=adc1_get_voltage(ADC1_TEST_CHANNEL);//采集 ADC

//ADC 的结果转换成电压
//参考电压是 1.1V,所以是 1100mV,12 位分辨率,所以是 4096 sprintf(adc_buff, "adc=%d,%dmv", read_raw, (read_raw*1100)/4096); Gui_DrawFont_GBK16(6,90,VIOLET,BLACK,(u8 *)adc_buff);//显示屏输出 vTaskDelay(10);
}
}12345678910111213141516171819

3.11.5. 实验过程

配置 串口、波特率、编绎和程序 的详细过程请往回看 3.1.4,在这个实验里都是一笔带过。 (1) 把开发板通过 USB 线接到电脑上,通过设备管理器查看生成的串口。开发板在我们演示电脑上生
成的是 COM3。
(2) 在 menuconfig 菜单里配置 程序串口。提供的例程配置的串口是 COM3,波特率为 921600。
(3) 通过 make all 编绎工程。
(4) 当编绎通过之后,使用命令 make flash 把程序 到开发板上。或者参考 2.3.2 节,使用工具 。
(5) 按下开发板的复位键,让程序运行起来,观察显示屏最后一行的显示,用于遮挡光敏传感器观察 LCD 变化。如果没有LCD,串口也有输出。

keil工程Error: L6218E: Undefined symbol main (referred from rtentry2.o).

1,main这个符号未定义。

解决:写成 void mian(),而不是 main()。

2,大多数是因为未加main.c文件于工程中或main单词拼写错误。

解决:仔细检查程序代码,看是否出现拼写错误,修改main单词。

如果自己的程序并没有出现上述这两种情况,可能是因为《ARM处理器裸机开发实战——机制而非策略》这本书自定的启动代码是根据ADS1.2软件编写的{自定义的启动代码里定义了Main(),而自己定义的函数为main},自己现在的运行环境为MDK软件,应该需要的是main()函数。

扩展资料:

改进程序:

#include lpc213x.h

#include lcd.h
#include stdio.h

unsigned int read_adc();

void mian()
{ unsigned int adc_result; char buffer[16]; PINSEL1|=0x00800000; AD0CR=0x00200301; while(1) { adc_result=read_adc(); sprintf(buffer,"result=%d",adc_result); lcd_init(); lcd_gotoxy(0,0); lcd_print(buffer); }

}
unsigned int read_adc()
{ int true; unsigned int result; AD0CR|=0x01000000; true=AD0GDR1; while(!true) result=(AD0GDR5); result=0x3FF; return result;
}

main函数:

又称主函数,是程序执行的起点,main是相对来说的,如同音学理论之主调于泛音,泛音即程序中的除main之外的其他函数,迎合人们的思考方式而生成的而非必定的模式.有主有次,执行起来条清缕析,既可将程序模块化又实现了一个闭合的整体。

在C语言当中,一个程序,无论复杂或简单,总体上都是一个“函数”;这个函数就称为“main() 函数”,也就是“主函数”。比如有个“做菜”程序,那么“ 做菜 ”这个过程就是“主函数”。在主函数中,根据情况,你可能还需要调用“买菜,切菜,炒菜”等子函数。

main函数在程序中大多数是必须存在的,但是依然有例外情况,比如windows编程中可以编写一个动态链接库(dll)模块,这是其他windows程序可以使用的代码。

由于DLL模块不是独立的程序,因此不需要main函数。再比如,用于专业环境的程序-----如机器人中的控制芯片--可能不需要main函数。

参考资料来源:main函数-百度百科

各位大神,求教啊,stm32 adc 多通道采集出错

/******************** (C) COPYRIGHT 2012 WildFire Team ***************************
* 文件名 :adc.c
* 描述 :adc应用函数库
* 实验平台:野火STM32开发板
* 硬件连接:----------------------------------------------------
* | |
* | PC1 - ADC1 连接外部电压(通过一个滑动变阻器分压而来)|
* | |
* ----------------------------------------------------
* 库版本 :ST3.5.0
*
* 作者 :wildfire team
* 论坛 :http://www.amobbs.com/forum-1008-1.html
* 淘宝 :http://firestm32.taobao.com
**********************************************************************************/
#include "adc.h"

#define ADC1_DR_Address ((u32)0x40012400+0x4c)
__IO uint16_t AD_Value[2]; //定义数组AD_Value[2]; 存放2个通道的值

__IO uint16_t ADC_ConvertedValue;
//__IO u16 ADC_ConvertedValueLocal;

/*
* 函数名:ADC1_GPIO_Config
* 描述 :使能ADC1和DMA1的时钟,初始化PC.01
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
static void ADC1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* Enable ADC1 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);

/* Configure PC.01 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, GPIO_InitStructure); // PC0,输入时不用设置速率
/* Configure PC.01 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, GPIO_InitStructure); // PC2,输入时不用设置速率
}

/* 函数名:ADC1_Mode_Config
* 描述 :配置ADC1的工作模式为MDA模式
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
static void ADC1_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟

/* DMA channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)AD_Value;//内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//BufferSize=2,因为ADC转换序列有2个通道
//如此设置,使序列1结果放在AD_Value[0],序列2结果放在AD_Value[1]
DMA_InitStructure.DMA_BufferSize = 64;
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;
//循环模式开启,Buffer写满后,自动回到初始地址开始传输
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);
DMA_Cmd(DMA1_Channel1, ENABLE); //配置完成后,启动DMA通道

/* ADC1 configuration */

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE ; //禁止扫描模式,扫描模式用于多通道采集
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式,即不停地进行ADC转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 2; //要转换的通道数目2
ADC_Init(ADC1, ADC_InitStructure);

/*配置ADC时钟,为PCLK2的8分频,即9Hz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
/*配置ADC1的通道11为55. 5个采样周期,序列为1 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_55Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);

/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);

/*复位校准寄存器 */
ADC_ResetCalibration(ADC1);
/*等待校准寄存器复位完成 */
while(ADC_GetResetCalibrationStatus(ADC1));

/* ADC校准 */
ADC_StartCalibration(ADC1);
/* 等待校准完成*/
while(ADC_GetCalibrationStatus(ADC1));

/* 由于没有采用外部触发,所以使用软件触发ADC转换 */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/*
* 函数名:ADC1_Init
* 描述 :无
* 输入 :无
* 输出 :无
* 调用 :外部调用
*/
void ADC1_Init(void)
{
ADC1_GPIO_Config();
ADC1_Mode_Config();
}

/******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/

STC公司单片机为什么宏定义的地址,比喻#define ADC_POWER 0x80 ;为什么不可以直接拿来用呢?

估计 ADC_POWER 所在的寄存器不可位寻址,所以不能直接对其置1或清0
该寄存器地址不是8的整倍数
一般#define ADC_POWER 7 ;
然后 置1 清0可以这样操作
ADC_CONTR|=1ADC_POWER
ADC_CONTR=~(1ADC_POWER )
当然也可以
#define ADC_POWER 0x80 ;
ADC_CONTR|= ADC_POWER
ADC_CONTR= ~ADC_POWER
本人也犯过类似错误
#define ADC_POWER 0x80 ; 宏定义ADC_POWER的数值是 0x80,正确的
ADC_POWER=1 让一个数值等于另一个数值,所以是错误的
ADC_POWER 并不是特殊功能寄存器 它只是殊功能寄存器ADC_CONTR中的一位
声明特殊功能寄存器的方法是sfr ADC_CONTR=0xBC

STM32F407怎么对ADC采集的12位数据进行FFT?

FFT算法,需要你自己做了,网上有现成的例子。
你要做的是:配置好ADC采用通道;
再根据需要配置一个定时器触发ADC采样通道,读取数据存到缓存中;
根据缓存中的数据做FFT算法;
主要问题是:这个定时器设置的周期需要你自己决定,因为多久做一次FFT,需要多少采样数据都是你来决定的

标签: #怎么解决esp32adc十二位分辨率#adc函数库