您的位置 首页 电子

stm32之DMA完全研讨(2)

AD转换之DMA1、DMA的配置//DMA的配置voidDMA_Configuration(void){/*允许DMA1*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DM

AD转化之DMA

1、DMA的装备

//DMA的装备
void DMA_Configuration(void)
{

/* 答应 DMA1 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA通道1*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)( &(ADC1->DR)); //ADC1数据寄存器
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADCCov; //获取ADC的数组
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //片内外设作源头
DMA_InitStructure.DMA_BufferSize = 16; //每次DMA16个数据
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不添加
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址添加
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //半字
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //一般形式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //DMA通道1传输完结中止

/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}

要装备的内容有:

(1)DMA1的AHB时钟使能

(2)DMA的源端和意图端的装备以及传输方向的装备

(3)每次DMA的数据长度、地址是否添加、形式、优先级等等

(4)使能DMA中止

(5)使能DMA1的通道1(通道挑选)

本例程中DMA中止的操作如下:

/*******************************************************************************
* Function Name : DMAChannel1_IRQHandler
* Description : This function handles DMA Stream 1 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern volatile bool ADC_Ok;
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC1))
{
DMA_ClearITPendingBit(DMA1_IT_GL1); //铲除悉数中止标志
ADC_Ok=TRUE;
}
}

在DMA1的1通道的中止程序中,清楚中止标志,而且将AD标志方位位。

从头答应DMA

void DMAReConfig(void)
{
DMA_DeInit(DMA1_Channel1);
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
}

下面是主程序中,对AD和DMA的运用操作:

int main(void)
{
u16 adc;
u8 a,b,c,d;

ChipHalInit(); //片内硬件初始化
ChipOutHalInit(); //片外硬件初始化

for(;;)
{
if(ADC_Ok==TRUE)
{
ADC_Ok=FALSE;
adc=DigitFilter(ADCCov,16); //滤波

DMAReConfig();//从头启动DMA

adc=(1.42 – adc*3.3/4096)*1000/4.35 + 25;

//转化为温度值,实践使用中,可考虑用毫伏为单位,防止浮点运算

a = adc/1000;
b = (adc – a*1000)/100;
c = (adc – a*1000 – b*100)/10;
d = adc – a*1000 – b*100 – c*10;

USART1_Puts(“当时温度是:”);
USART1_Putc(a+0);
USART1_Putc(b+0);
USART1_Putc(c+0);
USART1_Putc(d+0);
USART1_Puts(“C \r\n”);
}
}
}

这段程序所完结的操作有:

(1)当一次DMA传输完结后,主程序依据标志量,核算转化出来的ad值。

(2)从头启动DMA

(3)将ad值核算成温度,然后将温度值经过串口发送出去。

(4)等候下一个DMA传输完结的到来,进行下一个周期的转化和核算。

还有一点比较重要的便是NVIC的装备,任何stm32的中止程序都需求装备NVIC,有的时分有一忽视掉。

//设置一切的中止答应

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

/* Enable DMA channel1 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

}

别的,在装备DMA中止的时分,也能够装备成传输一半发生中止的方法。

咱们能够做如下试验:

将DMA中止设置成传输一半发生中止,如下:

DMA_ITConfig(DMA1_Channel4, DMA_IT_HT, ENABLE);

当数据传送到一半的时分发现进入到中止:

void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_HT4))
{
DMA_ClearITPendingBit(DMA1_IT_HT4);

}
}

在此中止中设置断点,当发生中止后,发现DMA传送并没有完毕。

仅仅cpu“中止”了。

DMA依然将剩余的一半数据传送完。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/265283.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部