热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ADC循环采集六路电压(转)

二)ADC循环采集六路电压,使用DMA.这次实验真的很郁闷,对DMA的不了解让我深陷误区,明白之后,让我更加佩服DMA的强大。误区就是:从实验的目标我们知道
二)ADC循环采集六路电压,使用DMA.
     这次实验真的很郁闷,对DMA的不了解让我深陷误区,明白之后,让我更加佩服DMA的强大。
     误区就是:从实验的目标我们知道这次是用DMA把ADC转换的数据传送到内存中的一个数组里存起来,因为是采集6个通道,这里使能了ADC的扫描模式。一旦启动ADC,就会按顺序转换SQRX里选中的通道,问题就是我一开始以为ADC与DMA并不会协调工做,也就是ADC自己转自己的,DMA自己传自己的,这样的话内存里的数组就不是我想要的了,后来着实的研究了很长时间,在群里的一位兄弟的提醒下,我才知道,可能我想的复杂了,也许就可以在ADC转一次,然后DMA把数据传一次,Ok,经过实验得知,这个想法是正确的。
    好了,说了这么多废话,开始进入正题。
    这里使用了ADC1的六个规则通道分别是:CH0、CH1、CH2、CH3、CH14、CH15,
                    分别对应的引脚为PA0、PA1、PA2、PA3、PC4、PC5。
    关于ADC的配置:
    启动了ADC1的扫描模式,还有连续转换模式,独立工作模式(只用1个ADC),因为用的了DMA,所以也要使能DMA位,使用外部触发(SWSTART),数据为右对齐。还有SQRX等等就不说了,这里不需要ADC中断的。中断在DMA里。
    关于DMA的配置:
    因为ADC请求规定在DMA1的第一个通道,所以这里使用DMA_CH1,外设地址为ADC唯一的数据寄存器(u32)&ADC1->DR,存储器地址为(u32)SendBuff数组,这个数组可以存放6个元素。这里还有使能传输完中断(TCIF),选择从外设读取,循环模式,外设地址非增量模式,存储器地址增量模式,外设数据宽度16位,存储器地址16位,非存储器到存储器模式。
    关于DMA中断函数:
   当DMA传输完6次数据时,TCIF位自动置位,程序进入中断服务函数,首先先关闭ADC的连续转换,我们把数组的处理都放在了这里,处理完发送到串口,通过电脑的超级终端可以看到不停变化的6个引脚电压的数据。别忘了一定要清楚中断标志位并置位ADC的连续转换,然后再次启动转换。
    主程序中只要初始化系统函数,还有串口,然后配置好DMA,启动规则转换通道,并启动DMA,然后等在死循环即可。
    下面附上部分代码
-------------------------------------------------------------------------------------------
 void  Adc_Init(void)
{   
 //先初始化IO口
  RCC->APB2ENR|=1<<2;     //使能PORTA口时钟
  RCC->APB2ENR|=1<<4;     //使能PORTC口时钟
 GPIOA->CRL&=0XFFFF0000; //PA0 1 2 3 anolog输入
 GPIOC->CRL&=0XFF00FFFF; //PC4,5 anolog输入
 //通道10/11设置   
 RCC->APB2ENR|=1<<9;     //ADC1时钟使能  
 RCC->APB2RSTR|=1<<9;    //ADC1复位
 RCC->APB2RSTR&=~(1<<9); //复位结束    
 RCC->CFGR&=~(3<<14);    //分频因子清零 
 //SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
 //否则将导致ADC准确度下降!
 RCC->CFGR|=2<<14;       
 ADC1->CR1&=0XF0FFFF;    //工作模式清零
 ADC1->CR1|=0<<16;       //独立工作模式 
 ADC1->CR1|=1<<8;     //扫描模式
 ADC1->CR2|=1<<1;        //启用连续转换           
 ADC1->CR2|=1<<8;        //启用DMA      
// ADC1->CR2&=~(1<<1);     //单次转换模式
 ADC1->CR2&=~(7<<17);   
 ADC1->CR2|=7<<17;     //软件控制转换 
 ADC1->CR2|=1<<20;       //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发
 ADC1->CR2&=~(1<<11);    //右对齐
 ADC1->SQR1&=~(0XF<<20);
 ADC1->SQR1|=5<<20;      //6个转换在规则序列
 ADC1->SQR3 = 0X00000000;
 ADC1->SQR3|= 0X1EE18820;      
 //设置通道0~3,14,15的采样时间
 ADC1->SMPR1&=0XFFFC0FFF;//通道14,15采样时间清空
 ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采样时间清空  
 ADC1->SMPR1|=7<<15;     //通道15  239.5周期,提高采样时间可以提高精确度 
 ADC1->SMPR1|=7<<12;     //通道14  239.5周期,提高采样时间可以提高精确度  
 ADC1->SMPR2|=7<<9;      //通道3  239.5周期,提高采样时间可以提高精确度 
 ADC1->SMPR2|=7<<6;      //通道2  239.5周期,提高采样时间可以提高精确度 
 ADC1->SMPR2|=7<<3;      //通道1  239.5周期,提高采样时间可以提高精确度 
 ADC1->SMPR2|=7<<0;      //通道0  239.5周期,提高采样时间可以提高精确度 
 ADC1->CR2|=1<<0;     //开启AD转换器 
 ADC1->CR2|=1<<3;        //使能复位校准 
 while(ADC1->CR2&1<<3);  //等待校准结束    
    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。   
 ADC1->CR2|=1<<2;        //开启AD校准   
 while(ADC1->CR2&1<<2);  //等待校准结束
 //该位由软件设置以开始校准,并在校准结束时由硬件清除 
}     
 void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
 u32 DR_Base;      //做缓冲用,不知道为什么.非要不可
 RCC->AHBENR|=1<<0;   //开启DMA1时钟
 DR_Base=cpar;
 DMA_CHx->CPAR=DR_Base;    //DMA1 外设地址
 DMA_CHx->CMAR=(u32)cmar;  //DMA1,存储器地址
 DMA1_MEM_LEN=cndtr;       //保存DMA传输数据量
 DMA_CHx->CNDTR=cndtr;     //DMA1,传输数据量
 DMA_CHx->CCR=0X00000000; //复位
 DMA_CHx->CCR|=1<<1;    //允许传输完中断
 DMA_CHx->CCR|=0<<4;    //从外设读
 DMA_CHx->CCR|=1<<5;    //循环模式
 DMA_CHx->CCR|=0<<6;    //外设地址非增量模式
 DMA_CHx->CCR|=1<<7;    //存储器增量模式
 DMA_CHx->CCR|=1<<8;    //外设数据宽度为16位
 DMA_CHx->CCR|=1<<10;   //存储器数据宽度16位
 DMA_CHx->CCR|=1<<12;   //中等优先级
 DMA_CHx->CCR|=0<<14;   //非存储器到存储器模式
 MY_NVIC_Init(1,3,DMA1_Channel1_IRQChannel ,2);     
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
 DMA_CHx->CCR&=~(1<<0);       //关闭DMA传输
 DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
 DMA_CHx->CCR|=1<<0;          //开启DMA传输
}
u16 ADC1_DR, adcx;
void DMAChannel1_IRQHandler(void)
{      
 u16 i;
 u32 sum[6]={0},val=0; 
 LED0 =!LED0;
 ADC1->CR2&=~(1<<1);        //关闭连续转换           
 for( i = 0; i<768 ;i+= 6)
 {
  sum[0] += SendBuff[i];
  sum[1] += SendBuff[i+1];
  sum[2] += SendBuff[i+2];
  sum[3] += SendBuff[i+3];
  sum[4] += SendBuff[i+4];
  sum[5] += SendBuff[i+5];
 }
 for(i = 0;i <6 ;i++)
 {
  val = sum[i]/DMA_COUNT;
  ADC1_DR = sum[i]/DMA_COUNT;
  TEMP=(float)ADC1_DR*(3.3/4096);
  adcx=TEMP;
  LCD_ShowNum(149,70+i*20,adcx,1,16);//显示电压值
  TEMP-=adcx;
  TEMP*=1000;
  LCD_ShowNum(165,70+i*20,TEMP,3,16);
 }
 delay_ms(200); 
   DMA1->IFCR |= 1<<1;        //清零通道完成中断标志位
 ADC1->CR2|=1<<1;           //启用连续转换           
 ADC1->CR2|=1<<22;          //启动规则转换通道         
}

推荐阅读
  • 本文介绍了[从头学数学]中第101节关于比例的相关问题的研究和修炼过程。主要内容包括[机器小伟]和[工程师阿伟]一起研究比例的相关问题,并给出了一个求比例的函数scale的实现。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • 本文介绍了多因子选股模型在实际中的构建步骤,包括风险源分析、因子筛选和体系构建,并进行了模拟实证回测。在风险源分析中,从宏观、行业、公司和特殊因素四个角度分析了影响资产价格的因素。具体包括宏观经济运行和宏经济政策对证券市场的影响,以及行业类型、行业生命周期和行业政策对股票价格的影响。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文介绍了如何清除Eclipse中SVN用户的设置。首先需要查看使用的SVN接口,然后根据接口类型找到相应的目录并删除相关文件。最后使用SVN更新或提交来应用更改。 ... [详细]
author-avatar
33
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有