求同时使用芯片自带的AD1和AD2的配置代码

2019-07-20 23:00发布


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
likunxue
1楼-- · 2019-07-21 01:47
本帖最后由 likunxue 于 2016-4-5 23:29 编辑

/********************************************************************************************
函 数 名: ADC1,ADC2,初始化同步规则转换
调    用: ADC_RegSimul_Init(void)
参    数: 无
返 回 值: 无
说    明: ADC1 模拟输入通道0,ADC2 模拟输入通道1
********************************************************************************************/
void ADC_RegSimul_Init(void)
     {     
     RCC->APB2ENR  |= 0x00000610;    //PCLK2/6 = 12MHZ(ADC转换器的时钟)        
     RCC->APB2ENR  |= 1<<2;          //使能PORTA口时钟
     GPIOA->CRL    &= 0XFFFFFF00;    //PA0,PA1  anolog输入
     RCC->APB2ENR  |= 1<<9;          //ADC1时钟使能         
     RCC->APB2ENR  |= 1<<10;         //ADC2时钟使能        
     RCC->APB2RSTR |= 1<<9;          //ADC1复位
     RCC->APB2RSTR &= ~(1<<9);       //ADC2复位结束        
     RCC->APB2RSTR |= 1<<10;         //ADC2复位
     RCC->APB2RSTR &= ~(1<<10);      //ADC2复位结束            
     //ADC1寄存器的配置方法
     ADC1->CR1   = 0x00060000;       //同步规则模式  
     ADC1->CR2   = 0x000E0002;
     ADC1->SQR1  = 0x00000000;     
     ADC1->SMPR2 = 0x00000007;       //转换时间(239.5周期)
     ADC1->SQR3  = 0x00000000;       //ADC1的0通道 PA0
     ADC1->CR2  |= 0x00000001;       //使能ADC1
     ADC1->CR2  |= 0x00000008;       //使能ADC1复位
     while(ADC1->CR2&1<<3);          //等待复位校准结束
     ADC1->CR2|=1<<2;                //开启AD校准,该位由软件设置以开始校准,
     //并在校准结束时由硬件清除            
     while(ADC1->CR2&1<<2);          //等待校准结束
     //ADC2寄存器配置的方法
     ADC2->CR1   = 0x00060000;       //同步规则模式
     ADC2->CR2   = 0x000E0002;       //禁止扫描模式,使能连续转换,   
     ADC2->SQR1  = 0x00000000;
     ADC2->SMPR2 = 0x00000038;       //转换时间(239.5周期)
     ADC2->SQR3  = 0x00000001;       //ADC2的第1通道 PA1
     ADC2->CR2   |= 0x00100000;      //使能ADC2外部触发转换
     ADC2->CR2   |= 0x00000001;      //使能ADC2
     ADC2->CR2   |= 1<<3;            //使能复位校准,该位由软件设置并由硬件清除,
     //在校准寄存器被初始化后该位将被清除。   
     while(ADC2->CR2 & 1<<3);        //等待ADC2复位校准结束                  
     ADC2->CR2 |= 1<<2;              //开启AD校准,该位由软件设置以开始校准
     //并在校准结束时由硬件清除            
     while(ADC2->CR2 & 1<<2);        //等待ADC2校准结束         
     ADC1->CR2 |= 0x00000100;        //使能ADC1 DMA传输
     }
模块名称: DMA 驱动低层头文件
#ifndef __ADC_H
#define __ADC_H        
#include "sys.h"
void ADC_RegSimul_Init(void); //ADC1,ADC2,初始化同步规则转换
void ADC1_Init(void);
u16 Get_Adc_Average(u8 ch,u16 times); //获取通道ch的转换值
u16 Adc_Qverage(u16 times); //基准电压值采集函数
#endif
         
模块名称: DMA 驱动低层C文件
文件名称: DMA.C
版    本: V1.0

#include "dma.h"
#include "delay.h"
#include <math.h>               //数学函数  

#define  ZENGLIANG      15u     //动态一阶滤波系数增量值
#define  JISHUZUIDAZHI  10u     //动态一阶滤波消抖动计数器最大值
#define  ZUIDACHAZHI    10u     //两次结果的差值

FILTER_BYTE adc1_byte;          //定义ADC1动态滤波数据
FILTER_BYTE adc2_byte;          //定义ADC2动态滤波数据
u32 ADC_Buf[ADC_SIZE];                //用于存放ADC数据
vu16 ADC_MSIN,ADC_MCON;
/********************************************************************************************
函 数 名: DMA1 配置函数
调    用: MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
参    数: *DMA   DMA 结构数据指针
          cpar:外设地址
          cmar:存储器地址
          cndtr:数据传输量   
返 回 值: 无
********************************************************************************************/         
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
     {     
     RCC->AHBENR    |= 1<<0;              //开启DMA1时钟,使能DMA传输
     DMA1->IFCR     =  0x0000000F;    //将DMA的通道1寄存器重设为缺省值
     DMA_CHx->CCR   |= 1<<5;          //使能连续模式
     DMA_CHx->CCR   |= 1<<7;          //使能存储器增量模式
     DMA_CHx->CCR   |= 2<<8;          //外设数据宽度为32位
     DMA_CHx->CCR   |= 2<<10;         //存储器数据宽度32位
     DMA_CHx->CCR   |= 2<<12;         //高等优先级
     DMA_CHx->CPAR  = cpar;                //DMA1 外设地址
     DMA_CHx->CMAR  = (u32)cmar;      //DMA1,存储器地址
     DMA_CHx->CNDTR = cndtr;          //DMA1,传输数据量
     DMA_CHx->CCR   |= 1<<0;          //使能ADC TX DMA1 所指示的通道
     delay_ms(5);                      //等待DMA时钟稳定
     adc1_byte.FangXiang = 0;         //方向
     adc1_byte.JiShuQi = 0;           //计数器
     adc1_byte.XiShu = 128;           //滤波系数
     adc2_byte.FangXiang = 0;         //方向
     adc2_byte.JiShuQi = 0;           //计数器
     adc2_byte.XiShu = 128;           //滤波系数   
     MY_NVIC_Init(3,2,DMA1_Channel1_IRQn,4);//配置DMA中断配置
     DMA_CHx->CCR |= 1<<1;            //使能传输完成中断  
     }
/********************************************************************************************
函 数 名: 一阶滤波函数(动态调整滤波系数)
调    用: Filter_lst(u16 NEW_DATA,u16 OLD_DATA ,char k)
参    数: NEW_DATA 新采样值
          OLD_DATA 上次滤波的结果
          k 滤波系数
返 回 值: 本次滤波的结果
公式原型: 本次滤波的结果 = 上次滤波的结果*(256-滤波系数)/256+新采样值*滤波系数/256
全局变量: P->FangXiang;   方向
          P->JiShuQi;     计数器
          P->XiShu;       滤波系数  
宏定义:   ZENGLIANG       15u  动态一阶滤波系数增量值,10到25
          JISHUZUIDAZHI   10u  动态一阶滤波消抖动计数器最大值根据情况调整
          ZUIDACHAZHI     10u  两次结果的差值
********************************************************************************************/         
u16 Filter_lst( FILTER_BYTE *P,u16 NEW_DATA,u16 OLD_DATA )
    {
    int ChaZhi;
    char FX;   //方向  
    if(NEW_DATA == OLD_DATA)return OLD_DATA; //直接退出不需处理   
    if(NEW_DATA < OLD_DATA)
      {
      FX = 0; //记录数据变化方向            
      ChaZhi = OLD_DATA -NEW_DATA; //得到两次数据变化的差值
      OLD_DATA -= (ChaZhi * P->XiShu + 128)/256; //加128为了四舍五入                    
      }
    else{ //新采样值大于上次滤波结果时
        FX = 1; //记录数据变化方向                     
        ChaZhi = NEW_DATA - OLD_DATA;
        OLD_DATA += (ChaZhi * P->XiShu + 128)/256;//加128为了四舍五入            
        }
    //动态调节滤波系数
    if(FX != P->FangXiang){P->JiShuQi = 0->XiShu = 0;}//两次变化的方向不同,清零计数器及滤波系数
    else{
        if(ChaZhi > ZUIDACHAZHI)P->JiShuQi += 3;  //差值1大于阈值,计数器加3
        else P->JiShuQi++;  //计数器加1   
        if(P->JiShuQi >JISHUZUIDAZHI) //计数器已达最大值
          {         
          P->XiShu += ZENGLIANG; //调整一阶滤波系数
          if(P->XiShu > 255)P->XiShu = 255; //如果已达最大值,则取最大值
          P->JiShuQi = 0; //消抖计数器清零                          
          }  
        }
    P->FangXiang = FX; //保存当前次的变化方向      
    return OLD_DATA;   
    }   
/********************************************************************************************
函 数 名: DMA1 通道1 中断服务函数
调    用: 无
参    数: 无
返 回 值: 无
说    明: 两路ADC采样值在这里做算术平均滤波后付给全局变量 ADC_MSIN, ADC_MCON  
********************************************************************************************/         
void DMA1_Channel1_IRQHandler(void)
     {
     u32 adcx1,adcx2;     
     u8  k;              
     if((DMA1->ISR)&(1<<1))             //DMA1通道1中断完成
       {
       DMA1->IFCR |= 1<<1;              //清除中断完成标志        
       ADC1->CR2  &= 0xFFFFFEFF;        //禁止ADC,DMA传输,ADC1->CR2 &= ~(1<<8);                              
       adcx1 = 0;adcx2 = 0;             //清零累加器               
       for(k = 0; k < ADC_SIZE ; k ++)
          {
          adcx1 += (ADC_Buf[k]&0xffff); //低16位, /1
          adcx2 += (ADC_Buf[k]>>16);    //高16位  /2
          }
       ADC1->CR2 |= 0x00500000;  //软件触发ADC1转换
       ADC1->CR2 |= 0x00000100;  //使能ADC1,DMA传输,ADC1->CR2 |= 1<<8;   
       ADC_MSIN = Filter_lst(&adc1_byte,adcx1/ADC_SIZE,ADC_MSIN);//sin采样值一阶滤波
       ADC_MCON = Filter_lst(&adc2_byte,adcx2/ADC_SIZE,ADC_MCON);//con采样值一阶滤波
       }
     }
主函数里的调用
ADC_RegSimul_Init();        //重新ADC1,ADC2,初始化同步规则转换           
  MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)ADC_Buf,ADC_SIZE);//DMA1通道设置
  ADC1->CR2 |= 0x00500000;    //软件触发ADC1转换,ADC1->CR2|=1<<8;


小杰
2楼-- · 2019-07-21 06:14
自顶
小杰
3楼-- · 2019-07-21 07:33
likunxue 发表于 2016-4-5 21:37
/********************************************************************************************
函 数 ...

这个代码好像不是F407的吧?
likunxue
4楼-- · 2019-07-21 10:04
 精彩回答 2  元偷偷看……
小杰
5楼-- · 2019-07-21 10:55
likunxue 发表于 2016-4-7 12:02
这是F103系列的, 地

有407的吗?大神
likunxue
6楼-- · 2019-07-21 15:41
小杰 发表于 2016-4-7 12:29
有407的吗?大神

还没有空完它呢!

一周热门 更多>