F407双ADC模式DMA传输,DMA第一次启动后能传输完数据,再次启动后就不能传输数据了,AD还在采样,但触发不了DMA传输。
程序如下:
[mw_shl_code=c,true]ADC配置:
#include "adc.h"
#include "delay.h"
void Adc_Init(void)
{
//先初始化IO口
RCC->AHB1ENR|=1<<0; //使能PORTA口时钟
RCC->APB2ENR|=1<<8; //开启ADC1时钟
RCC->APB2ENR|=1<<9;//开启ADC2时钟
GPIO_Set(GPIOA,PIN1,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU);//PA1 anolog输入
GPIO_Set(GPIOA,PIN2,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU);//PA2 anolog输入
GPIO_Set(GPIOA,PIN3,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU);//PA3 anolog输入
RCC->APB2RSTR|=1<<8; //所有ADC复位
RCC->APB2RSTR&=~(1<<8);//复位结束
ADC->CCR=3<<16; //ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
ADC1->CR1=0;
ADC1->CR2=0;
ADC2->CR1=0;
ADC2->CR2=0;
ADC->CCR&=0XFFFFE0; //工作模式清零
ADC->CCR|=0X06<<0; //规则同步
ADC1->CR1|=0<<24; //12位模式,分辨率
ADC2->CR1|=0<<24; //12位模式
ADC->CCR&=~(3<<14);
ADC->CCR|=2<<14;//多重ADC模式使用DMA
// - - - - - - - - - - - - - - - - - - - - - - - - - --- - - - - -ADC1 - - - - - -//
ADC1->CR1&=~(1<<8);//ADC1非扫描模式
//ADC1->CR1|=(1<<8);//ADC1扫描模式
ADC1->CR2&=~(1<<1);//单次转换
// - - - - - - - -- -- - - - - - -- - - - - - - - - - - -- - - -- ADC2 - - - - - - //
ADC2->CR1&=~(1<<8);//ADC2非扫描模式
//ADC2->CR1|=(1<<8);//ADC2扫描模式
ADC2->CR2&=~(1<<1);//单次转换、、、、、、、、、、、
//- - - - - 规则通道组 - - - - -//
ADC1->CR2&=~(15<<24);
ADC1->CR2|=9<<24;//主ADC外部T4_CC4事件触发,即ADC1。。。
ADC2->CR2&=~(3<<28);//规则通道组从ADC软件触发,即ADC2。。。
ADC1->CR2&=~(3<<28);
ADC1->CR2|=1<<28;//ADC1外部上升沿触发启动转换
ADC1->CR2&=~(1<<11);//右对齐
ADC1->SQR1&=~(0XF<<20);//ADC1规则通道序列长度
ADC1->SQR1|=0<<20;//1个转换(L[3:0])
ADC2->SQR1&=~(0XF<<20);//ADC2规则通道序列长度
ADC2->SQR1|=0<<20;//1个转换(L[3:0])
ADC1->SMPR2&=~(7<<6);
ADC1->SMPR2|=7<<6;//2通道,采样480周期
ADC2->SMPR2&=~(7<<9);
ADC2->SMPR2|=7<<9;//3通道,采样480周期
//- - - - - 注入通道组 - - - - -//
ADC1->CR2&=~(3<<20);//注入通道组主ADC外部软件触发,采集内部温度
ADC2->CR2&=~(3<<20);//注入通道组从ADC软件触发,即ADC2。。。采集外部温度
ADC->CCR|=1<<23;//使能内部温度传感器
ADC2->CR2&=~(1<<11);//右对齐
ADC1->JSQR&=~(3<<20);//ADC1注入通道序列长度
ADC1->JSQR|=0<<20;//1个转换(L[3:0])
ADC2->JSQR&=~(3<<20);//ADC2注入通道序列长度
ADC2->JSQR|=0<<20;//1个转换(L[3:0])
ADC1->SMPR1&=~(7<<18);
ADC1->SMPR1|=7<<18;//16通道,采样480周期
ADC2->SMPR2&=~(7<<3);
ADC2->SMPR2|=7<<3;//1通道,采样480周期
//开启AD1转换
ADC1->CR2|=1<<0;
////开启AD2转换
ADC2->CR2|=1<<0;
//- - - - - 设置规则通道组转换序列 - - - - -//
ADC1->SQR3&=0XFFFFFFE0;
ADC1->SQR3|=2;
ADC2->SQR3&=0XFFFFFFE0;
ADC2->SQR3|=3;//3通道
//- - - - - 设置注入通道组转换序列 - - - - -//
ADC1->JSQR&=0XFFF07FFF;
ADC1->JSQR|=(16<<15);//16通道,采集内部温度
ADC2->JSQR&=0XFFF07FFF;
ADC2->JSQR|=(1<<15);//1通道,PA1
}
DMA配置:
#include "dma.h"
#include "delay.h"
//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_Streamx
MA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chx
MA通道选择,范围:0~7
//par:外设地址
//mar:存储器地址
//ndtr:数据传输量
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr)
{
DMA_TypeDef *DMAx;
u8 streamx;
if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
{
DMAx=DMA2;
RCC->AHB1ENR|=1<<22;//DMA2时钟使能
}else
{
DMAx=DMA1;
RCC->AHB1ENR|=1<<21;//DMA1时钟使能
}
while(DMA_Streamx->CR&0X01);//等待DMA可配置
streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18; //得到stream通道号
if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16); //清空之前该stream上的所有中断标志
else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4); //清空之前该stream上的所有中断标志
else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16);//清空之前该stream上的所有中断标志
else DMAx->LIFCR|=0X3D<<6*streamx; //清空之前该stream上的所有中断标志
DMA_Streamx->
AR=par; //DMA外设地址
DMA_Streamx->M0AR=mar; //DMA 存储器0地址
DMA_Streamx->NDTR=ndtr; //DMA 传输数据量
DMA_Streamx->CR=0; //先全部复位CR寄存器值
DMA_Streamx->CR&=0<<6; //外设到存储器模式
DMA_Streamx->CR|=0<<8; //非循环模式(即使用普通模式)
DMA_Streamx->CR|=0<<9; //外设非增量模式
DMA_Streamx->CR|=1<<10; //存储器增量模式
DMA_Streamx->CR|=2<<11; //外设数据长度:32位
DMA_Streamx->CR|=2<<13; //存储器数据长度:32位
DMA_Streamx->CR|=1<<16; //中等优先级
DMA_Streamx->CR|=0<<21; //外设突发单次传输
DMA_Streamx->CR|=0<<23; //存储器突发单次传输
DMA_Streamx->CR|=(u32)chx<<25;//通道选择
//DMA_Streamx->FCR=0X21; //FIFO控制寄存器
//DMA_Streamx->CR|=1<<0; //开启DMA传输////////////////////
}
//开启一次DMA传输
//DMA_Streamx
MA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:数据传输量
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{
DMA_Streamx->CR&=~(1<<0); //关闭DMA传输
while(DMA_Streamx->CR&0X1); //确保DMA可以被设置
DMA_Streamx->NDTR=ndtr; //DMA 存储器0地址
DMA_Streamx->CR|=1<<0; //开启DMA传输
}
timer配置:
#include "timer.h"
void TIM4_PWM_Init(u32 arr,u32 psc)
{
RCC->APB1ENR|=1<<2;//TIM4时钟时能
RCC->AHB1ENR|=1<<3;//使能PORTD时钟
GPIO_Set(GPIOD,PIN15,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//复用功能,上拉输出
GPIO_AF_Set(GPIOD,15,15);
TIM4->ARR=arr;//设置计数器自动重装载值
TIM4->
SC=psc;//分频
//TIM4->CCMR2|=0<<8;//配置CH2为输出,开启TIM2的通道2为输出
TIM4->CCMR2|=7<<12;//CH4 PWM2模式,7代表PWM2模式
TIM4->CCMR2|=1<<11;//CH4预装载使能
TIM4->CCER|=1<<12;//OC4输出使能
TIM4->CCER|=1<<13;//OC4高电平有效
TIM4->CCR4=0x2710;////////////////////////设置占空比,计数值21000/2
//TIM1->BDTR|=1<<15;
TIM4->CR1|=1<<7;//ARPE使能,即TIM4_ARR寄存器被装入缓冲器
TIM4->CR1|=1<<0;
}
主程序:
include "sys.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
#include "dma.h"
#include "timer.h"
#include "adc.h"
//ALIENTEK 探索者STM32F407开发板 实验1
//跑马灯实验
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
u32 ADCData[4000];
int main(void)
{
u32 m=0;
u32 num1=0;
u32 num2=0;
u16 t=0;
// u16 i=0;
// u32 temp=0;
u8 PSD[12];
Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
delay_init(168); //初始化延时函数
LED_Init(); //初始化LED时钟
Adc_Init();
uart_init(84,115200);
TIM4_PWM_Init(20999,0);//定时器频率为APB1的2倍,即84MHZ。(Stm32_Clock_Init函数里对APB14分频,即为42MHZ。分频系数为4,不为1
//故TIM4时钟为APB1的2倍)不分频。PWM频率=84000/(20999+1)=4KHZ
MYDMA_Config(DMA2_Stream0,0,(u32)&ADC->CDR,(u32)ADCData,4000);
MYDMA_Enable(DMA2_Stream0,4000);
while(1)
{
if(DMA2->LISR&(1<<5))
{
m++;
LED0=!LED0;
DMA2->LIFCR|=1<<5;
while(DMA2->LISR&(1<<5));
num1=0;
num2=0;
//temp=0;
for(t=0;t<4000;t++)
{
num2=(ADCData[t]&0xFFFF0000)>>16;
num1=ADCData[t]&0xFFFF;
sprintf((char*)PSD,"%04d %04d %04d
",num1,num2,t);
printf(PSD);
}////////////////////////////////////////4000个数据全部传输
printf("
");
printf("
");
printf(" over
");
printf("
");
printf("
");
MYDMA_Enable(DMA2_Stream0,4000);
}
}
}
求大神帮忙解惑!!![/mw_shl_code]
一周热门 更多>