2019-07-20 23:00发布
likunxue 发表于 2016-4-5 21:37 /******************************************************************************************** 函 数 ...
likunxue 发表于 2016-4-7 12:02 这是F103系列的, 地
小杰 发表于 2016-4-7 12:29 有407的吗?大神
最多设置5个标签!
/********************************************************************************************
函 数 名: 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;
这个代码好像不是F407的吧?
有407的吗?大神
还没有空完它呢!
一周热门 更多>