>[success] **技术支持说明**
> 1.**客服**提供简单的技术支持,一般自主学习为主
> 2.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/nb-iot)
> 3.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解!
<br/>
## **ADC理论基础**
* **模拟信号**:模拟信号是指用连续变化的物理量所表达的信息,特点是信号值的变化是连续的,如下图所示。
![](https://img.kancloud.cn/b1/a0/b1a0f9f2c0eb819a2b82a4d1a7779a66_900x572.png =300x)
###
* **数字信号**:数字信号是指用一系列断续变化的脉冲数字量所表达的信息,特点是信号值会特然变化,如下图所示。
![](https://img.kancloud.cn/4b/34/4b34e93dc3ef07702a312a0395e0cbb0_570x362.png =300x)
###
* **ADC**:即模数转换,指模拟信号转换为数字信号的过程。举个例子,例如下图中的黑色线为一个模拟信号,可以通过特定的规则或者算法将其转换为阶梯状的数字信号。
![](https://img.kancloud.cn/e4/d5/e4d5ef0c5987d1471a96804c56b95ce9_562x326.png =400x)
<br/>
  本节课将会以STM32F030F4P6的PA0这个IO口作为模拟信号的输入口,然后把这个模拟信号转换为数字信号。
<br/>
## **ADC 的 HCL API 设计**
ADC的HAL API比较简单,只需要初始化和读取数据的API即可,如图所示。
![](https://img.kancloud.cn/be/d9/bed95327435b24b6b99199b228ca911d_364x180.png =250x)
<br/>
## **编写代码**
笔者在本节课配套的源代码中新建了 hal\_adc.h 和 hal\_adc.c文件,如图所示。
![](https://img.kancloud.cn/f5/cb/f5cba07e78b50b4ab800f42bc155265c_266x592.png =250x)
###
打开本节课配套的工程,笔者把hal\_adc.c以及必要的标准库文件添加进工程了,如图所示。
![](https://img.kancloud.cn/02/fa/02fae4365ff768edc8db5431501a4e57_375x661.png =250x)
<br/>
hal_adc.h文件的代码如下:
```
#ifndef __HAL_ADC_H__
#define __HAL_ADC_H__
/*
*初始化ADC
*/
void halAdcInit(void);
/*
*读取ADC值
*/
unsigned int halAdcRead(void);
#endif /* __HAL_ADC_H__ */
```
<br/>
hal_adc.c文件代码如下:
```
#include "hal_adc.h"
#include "stm32f0xx_adc.h"
/*
*初始化ADC
*/
void halAdcInit()
{
GPIO_InitTypeDef gpioCfg;//定义GPIO配置
ADC_InitTypeDef adcCfg;//定义ADC配置
/* 配置PA0 */
gpioCfg.GPIO_Pin = GPIO_Pin_0;//指定引脚为Pin 0
gpioCfg.GPIO_Mode = GPIO_Mode_AN;
gpioCfg.GPIO_PuPd = GPIO_PuPd_NOPULL;
/* 配置ADC */
adcCfg.ADC_Resolution = ADC_Resolution_12b;//ADC值的分辨率为12位
adcCfg.ADC_ContinuousConvMode = DISABLE;//不要进行持续的转换。在halAdcRead函数每次读取ADC值时,会重新启动转换过程
adcCfg.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
adcCfg.ADC_DataAlign = ADC_DataAlign_Right;
adcCfg.ADC_ScanDirection = ADC_ScanDirection_Backward;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
ADC_DeInit(ADC1);
GPIO_Init(GPIOA, &gpioCfg);//出初始化PA0
ADC_Init(ADC1, &adcCfg);//初始化ADC1
/* Convert the ADC1 Vref with 55.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_55_5Cycles);
ADC_GetCalibrationFactor(ADC1);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
ADC_StartOfConversion(ADC1);
}
/*
*读取ADC值
*
*@return ADC值
*/
unsigned int halAdcRead()
{
ADC_StartOfConversion(ADC1);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}
```
<br/>
## **使用ADC HAL API**
编写好ADC HAL API后,ADC的使用非常简单。在配套工程的main.c文件中添加如下代码:
###
```
/*
* 通过串口接收到信息时的回调函数
* @param byte - 接收到的数据
*/
static void onUartIRQ(unsigned char byte)
{}
int main(void)
{
halSystemInit();//系统初始化
halUartInit(115200);//串口通信初始化,并设置波特率为115200
halUartSetIRQCallback(onUartIRQ);//注册串口通信回调函数,当通过串口接收到信息时自动调用此函数
halAdcInit();//ADC初始化
/* 每隔1秒读取一次ADC值并通过串口发送出去 */
while (1)
{
halSystemDelayUs(1000 * 1000);//延时1000*1000微秒,即1秒
char debug[32];
sprintf(debug, "ADC=%d\n", halAdcRead());//读取ADC值,并格式化保存到debug变量中
halUartWrite((uint8_t *)debug, strlen(debug));//把debug通过串口发送出去
}
}
```
###
上述代码使用了格式化函数sprintf和字符串长度计算函数strlen,这两个函数在以下头文件中:
###
```
#include <stdio.h>
#include <string.h>
```
<br/>
**代码测试**
1.编译链接工程代码,把生成的Hex文件烧录到开发板中;
2.按如图所示把开发板的拨码开关的第1~4位打到右边,第5、6位打到左边,如图所示。
![](https://img.kancloud.cn/34/9c/349cceae4177926416445b6daf932d24_664x827.png =200x)
###
3.然后打开串口助手,可以看到由PA0这个IO口输入的模拟信号经过ADC后的值,如图所示。
![](https://img.kancloud.cn/bb/e1/bbe1b4698dc51b9bbfa09de6ec2fe7f1_724x639.png =500x)
<br/>
**进一步解释**
在按键相关章节曾经讲解过,STM32F030F4P6的PA0是与一个按键链接的,如图所示。
![](https://img.kancloud.cn/7f/25/7f255c0346cc531b0a02fc34645643c1_1671x1884.png =200x)
###
* 按键没有被按下时,PA0输入高电平(3.3v)
* 按键被按下后,PA0接地(GND),并且输入低电平(0v)
也就是说,PA0输入0到3.3v的模拟信号。main函数中的halAdcRead函数作用是读取某个时刻的模拟信号值,并且这个值映射到[0,4095]这个取值范围中后返回给mian函数。在ADC初始化函数halAdcInit中,把ADC分辨设置为12位,因此对应的ADC值取值范围即为[0,4095]。读者也可以把分辨率设置为8位,此时取值范围就是[0,255]。
<br/>
**进一步扩展**
ADC初始化函数halAdcInit被配置为对由PA0输入的模拟信号转换为数字信号,读者也可以更改其中的配置以更换到别的IO口。
<br/>
<br/>
## **商务合作**
如有以下需求,可扫码添加管理员好友,注明“**商务合作**”
* 项目定制开发,技术范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等;
* 入驻平台,成为讲师;
* 接项目赚外快;
* 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/)
![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =150x)
(非商务合作**勿扰**,此处**非**技术支持)
- 课程介绍
- 配套资源下载
- 配套开发套件简介
- 简介
- 硬件组成 & 技术参数
- 电路原理图 & PCB图
- 拨码开关使用说明
- 第一部分:无线通信 开发指南
- 1.1.1 NB-IoT:技术简介
- 1.1.2 NB:CH34x USB转串口驱动安装
- 1.1.3 NB:AT 指令开发与测试
- 1.1.4 NB:基础指令集简介
- 1.1.5 NB:云端服务器
- 1.1.5.1 PuTTY 简介与安装
- 1.1.5.2 登录云端服务器
- 1.1.6 NB:移远官方工具简介
- 1.1.7 NB:使用UDP协议与云端服务器通信
- 1.1.8 NB:使用TCP协议与云端服务器通信
- 1.1.9 NB:使用MQTT协议与云端服务器通信
- 进阶课程
- 第二部分:STM32 开发指南
- 2.1 搭建开发环境
- 2.1.1 Keil MDK 简介与安装
- 2.1.2 STM32 Pack 简介与安装
- 2.1.3 CH34x 驱动简介与安装
- 2.1.4 其他开发工具
- 2.2 STM32 开发基础
- 2.2.1 新建工程
- 2.2.2 实现第1个程序
- 2.2.3 Hex 文件烧录详解
- 2.3 移植官方标准工程模板
- 2.4 GPIO实验——LED灯
- 2.5 系统延时应用
- 2.6 GPIO实验——按键
- 2.7 GPIO中断实验——按键触发
- 2.8 使用定时器TIM3
- 2.9 串口通信实验
- 2.10 ADC 实验
- 2.11 OLED显示器实验
- 2.12 SDK 设计思想
- 2.13 SDK 架构解析
- 2.14 多任务应用
- 2.15 输入型任务:按键输入
- 2.16 输入型任务:串口接收
- 课外篇:项目实战
- 基于STM32+NB-IoT的温湿度采集
- 系统简介
- 系统搭建
- 系统详解
- 1.代码编译与架构说明
- 2.DHT11温湿度传感器
- 3. 数据通信任务说明
- 版权声明与免责声明