ADC模数转换
时钟频率不能超过14MHz
12位分辨率 0-4095 0-3.3v
3.3/4096
通道:18各通道。16个外部 +2个内部 最多支持23个通道
规则转换:最多转换16通道 --通道排序
采样频率:根据传感器设置
单词转换/连续转换
扫描模式:扫描 --多通道
转换的触发条件 --外部触发/硬件触发
数据存储:左对齐 右对齐
转换完成 EOC置位
校准:
复位校准寄存器 (初始化校准寄存器) --有标志位为1的时候开始复位,完成后变为0
校准寄存器 写1开始校准,校准完成变为0
在M3系列中,ADC只能存一个数据,同时转换两个数值的话处理不了了。只能借助DMA进行双通道。
但是在M4系列中,ADC设置每一个转换完成就有一个标志位。
ADC在转换完成后会产生DMA请求,但是只有ADC1与ADC3产生
ADC装换完成会产生中断,可以用中断进行处理数据。
// ADC 转换结束产生中断,在中断服务程序中读取转换值
ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//我们使能了 ADC 转换完成中断,需要配置中断源和中断优先级
void ADC_IRQHandler(void)
{
if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET)
{
// 读取 ADC 的转换值
ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
}
ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}
配置过程
-
确定ADC模块和引脚:首先,确定你所使用的芯片上的ADC模块和对应的引脚。芯片手册或数据表中会提供这些信息。
-
选择参考电压:ADC需要一个参考电压作为测量信号的基准。你需要选择适当的参考电压源,并将其连接到ADC模块的参考电压引脚上。参考电压可以是内部参考电压(如芯片提供的参考电压源),也可以是外部参考电压(通过连接外部电位器或其他参考电压源提供)。
-
配置ADC控制寄存器:ADC模块通常有一组寄存器用于配置转换参数。具体的配置步骤将取决于你使用的芯片型号和厂商。一般来说,你需要配置以下参数:
- ADC通道选择:选择要使用的ADC通道。
- 数据对齐方式:选择数据在寄存器中的对齐方式,如左对齐或右对齐。
- 采样时间:设置每次转换的采样时间长度,以确保足够的稳定时间。
- 分辨率:指定ADC的分辨率,即转换结果所占的位数。
- 转换模式:选择单次转换或连续转换模式。
- 触发方式:选择转换触发方式,可以是软件触发或外部信号触发等。
-
配置GPIO引脚:如果需要,在使用外部触发时,你可能需要配置相关的GPIO引脚,以接收外部触发信号。
-
启动ADC转换:在完成配置后,你可以启动ADC的转换过程。具体的启动方式也会因芯片和配置而有所不同,可以通过写入特定的寄存器或触发特定的命令来实现。
-
读取转换结果:一旦转换完成,你可以从ADC转换结果寄存器中读取所测量的数据。
1) 初始 ADC 用到的 GPIO;
2) 设置 ADC 的工作参数并初始化;
3) 设置 ADC 工作时钟;
4) 设置 ADC 转换通道顺序及采样时间;
5) 配置使能 ADC 转换完成中断,在中断内读取转换完数据;
6) 使能 ADC;
7) 使能软件触发 ADC 转换。 ADC 转换结果数据使用中断方式读取,这里没有使用 DMA 进行数据传输。
代码编写
/*
函数功能:ADC初始化,光敏电阻
函数参数:无
返 回 值:无
gz -- PA5 --ADC1_IN5
*/
void SensorInit(void)
{
//使能 PA ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//PA5 配置为模拟输入
GPIO_InitTypeDef GPIO_Struct={0};
GPIO_Struct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_Struct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA,&GPIO_Struct);
//配置ADC
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADCCLK不能超过14MHz 72/6=12M
ADC_InitTypeDef ADC_InitStruct={0};
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发转换
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//独立模式 单个
ADC_InitStruct.ADC_NbrOfChannel = 1;//要转换的通道数量
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描模式:单通道
ADC_Init(ADC1,&ADC_InitStruct);
//设置规则通道的转换顺序和采样时间 参数:通道 第一个转换 采样时间(根据外设配置)
ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_239Cycles5);
//使能ADC1
ADC_Cmd(ADC1,ENABLE);
//复位校准寄存器
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1)==SET);//判断复位校准寄存器
//开始校准
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1)==SET);
//开始转换
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
//读值
uint16_t GetADCValue(void)
{
uint16_t value=0;
//查看转换是否完成标志位 EOC,转换完成才能读取数值
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET)
{
}
value =ADC_GetConversionValue(ADC1); //读值
return value;
}
DMA直接存储器
作用:提供外设与存储器之间,存储器到存储器进行高速数据传输。(外设与外设不可以)
两个DMA , 有12各通道(DMA1有7个,DMA2有5个)
DMA2可以执行存储器到存储器的传输。
仲裁器决定这两个DMA的先后顺序
特性:
可以硬件产生DMA请求,也可以软件产生
在同一DMA模块中,可以设置通道优先级(高中低)。当优先级一致时,由硬件通道号决定,号越小越有先。
要求数据搬运必须对齐。传输宽度为8字节传输到16位的空间时是不可以的。(M4芯片就没有要求)
事件标志(中断源):传输完成时,传输出错,传输一半。
一次最多搬运65535
流程:
硬件转化完成通过总线矩阵产生DMA请求,DMA得到请求,便通过总线矩阵搬运数据。
DMA处理:
发生一个事件外设产生一个请求事件,DMA根据仲裁器设置的优先级来进行处理。开始访问发起请求的外设,DMA发送一个应答信号。外设接到后便不再发送请求。DMA开始搬运数据。
搬运数据流程:
- 从外设或者寄存器取数据【取地址需要设置地址增量(地址偏移)】
- 将加载的数据存储到外设或者存储单元【存地址需要设置地址增量(地址偏移)】
- DTR计数器在数据传输后进行递减操作。该计数器包涵需执行的事务数。
搬运要设置搬运模式:单次/循环
在产生事件后,外设向DMA控制器发送请求信号,DMA控制器根据通道优先级处理请求,只要DMA控制器访问外设,DMA控制器就会向外设发送信号。外设获得DMA控制器的确认信号后,便会立即释放其请求。一旦外设请求失效,DMA控制器就会释放确认信号。如果有更多请求,外设可以启动下一个事务。
注意:DMA在进行搬运数据时只能一个一个的搬运!并且搬运的通道是对应的。
通道配置过程
uint16_t dmabuff[3]={0};//存储器基地址
void ADCDmaInit(void)
{
//1.使能时钟 DMA1
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//2.配置DMA
DMA_InitTypeDef DMA_InitStruct={0};
DMA_InitStruct.DMA_BufferSize = 3; //DMA传输的数据个数 (要传输数据的整数倍)
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//外设作为数据源
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;//非存储器到存储器
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStruct.DMA_Priority = DMA_Priority_High;//优先权:高
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设基地址(DR数据寄存器)
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度16位(根据要搬运的外设数据宽度这里是ADC的数据是16位,所以宽度为16位)
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不增量在固定位置搬运(这里是ADC的DR数据寄存器)
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)dmabuff;//存储器基地址
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据宽度16位半字
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址增量(这里增的原因是数据有两个,不增的话只能保存一个)
DMA_Init(DMA1_Channel1,&DMA_InitStruct);//DMA1的通道1初始化
//3.DMA使能
DMA_Cmd(DMA1_Channel1,ENABLE);
//4.开启ADC的DMA请求
ADC_DMACmd(ADC1,ENABLE);
}
配置DMA过程
-
确定DMA控制器和通道:首先,确定你所使用的硬件平台上的DMA控制器和通道。DMA控制器可以是独立的芯片,也可以是集成在其他设备中的模块。
-
分配DMA缓冲区:DMA需要一个缓冲区来存储数据,该缓冲区应该位于主内存中,并且应该是物理连续的。你可以使用malloc()等函数来动态分配内存,或者直接在静态存储区定义一个缓冲区。
-
配置DMA控制寄存器:DMA控制器通常有一组寄存器用于配置传输参数。具体的配置步骤将取决于你使用的DMA控制器型号和厂商。一般来说,你需要配置以下参数:
- DMA通道号:选择要使用的DMA通道。
- 传输方向:指定数据传输的方向,如从外设到内存(读)或从内存到外设(写)。
- 数据宽度:设置每个传输的数据宽度,如8位、16位或32位。
- 传输模式:选择传输模式,如单次传输、循环传输或块传输等。
- DMA缓冲区地址:设置DMA缓冲区的物理地址。
- 传输长度:指定要传输的数据长度。
-
配置外设接口:如果你想要使用DMA与外设进行通信,则需要在外设接口上配置相应的寄存器,以使其与DMA控制器进行协同工作。具体配置方式也会因外设类型而异。
-
启动DMA传输:在完成配置后,将启动DMA传输。根据DMA控制器的不同,可能需要写入特定的寄存器或触发特定的信号来启动传输。