ADC与DMA

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);
}

配置过程

  1. 确定ADC模块和引脚:首先,确定你所使用的芯片上的ADC模块和对应的引脚。芯片手册或数据表中会提供这些信息。

  2. 选择参考电压:ADC需要一个参考电压作为测量信号的基准。你需要选择适当的参考电压源,并将其连接到ADC模块的参考电压引脚上。参考电压可以是内部参考电压(如芯片提供的参考电压源),也可以是外部参考电压(通过连接外部电位器或其他参考电压源提供)。

  3. 配置ADC控制寄存器:ADC模块通常有一组寄存器用于配置转换参数。具体的配置步骤将取决于你使用的芯片型号和厂商。一般来说,你需要配置以下参数:

    • ADC通道选择:选择要使用的ADC通道。
    • 数据对齐方式:选择数据在寄存器中的对齐方式,如左对齐或右对齐。
    • 采样时间:设置每次转换的采样时间长度,以确保足够的稳定时间。
    • 分辨率:指定ADC的分辨率,即转换结果所占的位数。
    • 转换模式:选择单次转换或连续转换模式。
    • 触发方式:选择转换触发方式,可以是软件触发或外部信号触发等。
  4. 配置GPIO引脚:如果需要,在使用外部触发时,你可能需要配置相关的GPIO引脚,以接收外部触发信号。

  5. 启动ADC转换:在完成配置后,你可以启动ADC的转换过程。具体的启动方式也会因芯片和配置而有所不同,可以通过写入特定的寄存器或触发特定的命令来实现。

  6. 读取转换结果:一旦转换完成,你可以从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开始搬运数据。

搬运数据流程:

  1. 从外设或者寄存器取数据【取地址需要设置地址增量(地址偏移)】
  2. 将加载的数据存储到外设或者存储单元【存地址需要设置地址增量(地址偏移)】
  3. 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过程

  1. 确定DMA控制器和通道:首先,确定你所使用的硬件平台上的DMA控制器和通道。DMA控制器可以是独立的芯片,也可以是集成在其他设备中的模块。

  2. 分配DMA缓冲区:DMA需要一个缓冲区来存储数据,该缓冲区应该位于主内存中,并且应该是物理连续的。你可以使用malloc()等函数来动态分配内存,或者直接在静态存储区定义一个缓冲区。

  3. 配置DMA控制寄存器:DMA控制器通常有一组寄存器用于配置传输参数。具体的配置步骤将取决于你使用的DMA控制器型号和厂商。一般来说,你需要配置以下参数:

    • DMA通道号:选择要使用的DMA通道。
    • 传输方向:指定数据传输的方向,如从外设到内存(读)或从内存到外设(写)。
    • 数据宽度:设置每个传输的数据宽度,如8位、16位或32位。
    • 传输模式:选择传输模式,如单次传输、循环传输或块传输等。
    • DMA缓冲区地址:设置DMA缓冲区的物理地址。
    • 传输长度:指定要传输的数据长度。
  4. 配置外设接口:如果你想要使用DMA与外设进行通信,则需要在外设接口上配置相应的寄存器,以使其与DMA控制器进行协同工作。具体配置方式也会因外设类型而异。

  5. 启动DMA传输:在完成配置后,将启动DMA传输。根据DMA控制器的不同,可能需要写入特定的寄存器或触发特定的信号来启动传输。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值