【菜鸟入门】stm32 之 DMA
2013-11-24 17:24
274 查看
DMA是个好东西,他可以帮助CPU分担好多工作,减轻CPU的工作压力,我们可以一边传输数据,一边干别的事情,很不错!
今天可谓是配置的好艰辛啊,看电视把我看蒙了,好多注意事项都木有看见,浪费了我好多时间。
好吧,开始进入主题!
时钟配置我就不用罗嗦了!大家自己去RCC里面的AHBENR找:
RCC->AHBENR |= 1<<0;//DAM1 Clock Enable
主要来看看DMAx的控制寄存器CCR
这个寄存器看着很容易理解,今天对控制寄存器有了新的认识,一般的寄存器可能要在控制寄存器的某一位关闭或者打开才能修改,而控制寄存器基本上可以在任意时刻进行修改,所以,在配置控制寄存器的时候我们没必要考虑那么多!
我今天准备把一个字符串通过DMA与USART1建立一个通道,把数据发送出去!
所以我们不从外设读数据,我们需要Read From Register,如果我们从ADC里面读数据我们就可以把这位置0
dma->CCR |= 1<<4;
//Read from register
我们可以采用循环发送,也可以不循环发送,如果是ADC的话,那就用循环发送
dma->CCR &= ~(1<<5);
//normal mode
因为USART1的地址不进行偏移或者改变
dma->CCR &= ~(1<<6);
//Device Address non-Rise
在一个字符串中我们要不断寻址去发送该为地址上的数据
dma->CCR |= 1<<7;
//Memary Address Rise
所有设备和存储都按8bit进行存储和读取
dma->CCR &= ~(3<<8);
//Device 8 Bit Data
dma->CCR &= ~(3<<10);
//Memary 8 Bit
在设置两位或两位以上的数据是一定要把其全部清空在进行设置,这样方便一点
dma->CCR &= ~(3<<12);
//clear 12:13
dma->CCR |= 1<<12;
//Set Priority level
14bit的配置我不用说了,大家看一下就肯定知道了
dma->CCR &= ~(1<<14);
//non M2M mode
DMA还有这么几个寄存器
DMA_CNDTR :要发送的数据个数
DM_CPAR:外设地址寄存器
DM_CMAR:存储器地址寄存器
这3个寄存器必须在DMA_CCRx的EN=0时才能进行修改!我今天就在这个地方沦陷了,后来看了李想老师的视频,他的感觉他的配置有问题,但是还是。。。
可能我们的板子不一样吧,反正我他那几个配置违背了EN=0时才能修改的原则
dma->CCR &= ~(1<<0);
dma->CPAR = cpar;
dma->CMAR = cmar;
dma->CNDTR = cndtr;
dma->CCR |= 1<<0;
还有其他规则,大家可以看看!DMA还是相对比较简单的,不过是建立在你细心的基础上!
另外我们要用到USART1的发送,所以我们也要去打开USART1里面的dma功能
在USART1的控制寄存器里面有这么两个配置:
我们要什么功能就选什么功能了!
这里我选USART1->CR3 |= 1<<7;
好了,那几天就这样,下面附上我的代码
效果图:
,
PS:最近在研究库,感觉库挺好用的,所以关于寄存器配置的进度比较慢!
今天可谓是配置的好艰辛啊,看电视把我看蒙了,好多注意事项都木有看见,浪费了我好多时间。
好吧,开始进入主题!
时钟配置我就不用罗嗦了!大家自己去RCC里面的AHBENR找:
RCC->AHBENR |= 1<<0;//DAM1 Clock Enable
主要来看看DMAx的控制寄存器CCR
这个寄存器看着很容易理解,今天对控制寄存器有了新的认识,一般的寄存器可能要在控制寄存器的某一位关闭或者打开才能修改,而控制寄存器基本上可以在任意时刻进行修改,所以,在配置控制寄存器的时候我们没必要考虑那么多!
我今天准备把一个字符串通过DMA与USART1建立一个通道,把数据发送出去!
所以我们不从外设读数据,我们需要Read From Register,如果我们从ADC里面读数据我们就可以把这位置0
dma->CCR |= 1<<4;
//Read from register
我们可以采用循环发送,也可以不循环发送,如果是ADC的话,那就用循环发送
dma->CCR &= ~(1<<5);
//normal mode
因为USART1的地址不进行偏移或者改变
dma->CCR &= ~(1<<6);
//Device Address non-Rise
在一个字符串中我们要不断寻址去发送该为地址上的数据
dma->CCR |= 1<<7;
//Memary Address Rise
所有设备和存储都按8bit进行存储和读取
dma->CCR &= ~(3<<8);
//Device 8 Bit Data
dma->CCR &= ~(3<<10);
//Memary 8 Bit
在设置两位或两位以上的数据是一定要把其全部清空在进行设置,这样方便一点
dma->CCR &= ~(3<<12);
//clear 12:13
dma->CCR |= 1<<12;
//Set Priority level
14bit的配置我不用说了,大家看一下就肯定知道了
dma->CCR &= ~(1<<14);
//non M2M mode
DMA还有这么几个寄存器
DMA_CNDTR :要发送的数据个数
DM_CPAR:外设地址寄存器
DM_CMAR:存储器地址寄存器
这3个寄存器必须在DMA_CCRx的EN=0时才能进行修改!我今天就在这个地方沦陷了,后来看了李想老师的视频,他的感觉他的配置有问题,但是还是。。。
可能我们的板子不一样吧,反正我他那几个配置违背了EN=0时才能修改的原则
dma->CCR &= ~(1<<0);
dma->CPAR = cpar;
dma->CMAR = cmar;
dma->CNDTR = cndtr;
dma->CCR |= 1<<0;
还有其他规则,大家可以看看!DMA还是相对比较简单的,不过是建立在你细心的基础上!
另外我们要用到USART1的发送,所以我们也要去打开USART1里面的dma功能
在USART1的控制寄存器里面有这么两个配置:
我们要什么功能就选什么功能了!
这里我选USART1->CR3 |= 1<<7;
好了,那几天就这样,下面附上我的代码
/* dma.c */ #include <stm32f10x.h> #include "stdio.h" #include "usart.h" #include "init.h" void dma1_init(DMA_Channel_TypeDef * dma) { RCC->AHBENR |= 1<<0;//DAM1 Clock Enable dma->CCR |= 1<<4; //Read from register dma->CCR &= ~(1<<5); //normal mode dma->CCR &= ~(1<<6); //Device Address non-Rise dma->CCR |= 1<<7; //Memary Address Rise dma->CCR &= ~(3<<8); //Device 8 Bit Data dma->CCR &= ~(3<<10); //Memary 8 Bit dma->CCR &= ~(3<<12); //clear 12:13 dma->CCR |= 1<<12; //Set Priority level dma->CCR &= ~(1<<14); //non M2M mode USART1->CR3 |= 1<<7; } void dma1_enable(DMA_Channel_TypeDef * dma,u32 cpar,u32 cmar,u32 cndtr) { #ifdef __DEBUG char buff[255]; #endif dma->CCR &= ~(1<<0); dma->CPAR = cpar; dma->CMAR = cmar; dma->CNDTR = cndtr; dma->CCR |= 1<<0; #ifdef __DEBUG sprintf(buff,"Initialize<start>.....\ndma:0x%08x\nCPAR:0x%08x\nCMAR:0x%08x\nCNDTR:0x%08x\n",\ (u32)dma,(u32)cpar,(u32)cmar,cndtr); rs232_send_str(buff,strlen(buff)); sprintf(buff,"Initialize.....\ndma:0x%08x\nCPAR:0x%08x\nCMAR:0x%08x\nCNDTR:0x%08x\n",\ (u32)dma,dma->CPAR,dma->CMAR,dma->CNDTR); rs232_send_str(buff,strlen(buff)); #endif }主函数:
#include <stm32f10x.h> #include "init.h" #include "usart.h" #include "dma.h" #include "stdio.h" int main() { char str[512]; rs232_init(CPU_72M,9600); RCC->APB2ENR |= 1<<4; GPIOC->CRH = 0x33333333; GPIOC->ODR |= 0xff00; sprintf(str,"This is a DMA1 Channel4 Test!\n"); dma1_init(DMA1_Channel4); while(1) { delay_ms(1000); dma1_enable(DMA1_Channel4,(u32)&USART1->DR,(u32)str,strlen(str)); while(1) { if(DMA1->ISR&(1<<13)) break; delay_ms(1000); } DMA1->IFCR |= 1<<13; } }
效果图:
,
PS:最近在研究库,感觉库挺好用的,所以关于寄存器配置的进度比较慢!
相关文章推荐
- 【菜鸟入门】stm32 之 pwm
- 【菜鸟入门】stm32 之 实时时钟
- STM32中DMA的使用入门
- STM32中DMA的使用入门
- STM32中DMA的使用入门
- 【菜鸟入门】stm32 之 iic
- 【菜鸟入门】stm32 之 eeprom
- STM32入门学习之DMA(STM32F030F4P6基于CooCox IDE)
- 【菜鸟入门】stm32 之 DAC
- 【菜鸟入门】stm32的第一个程序--LED
- 【菜鸟入门】stm32 之 USART
- 【菜鸟入门】stm32 之 ADC 模数转换
- STM32从菜鸟到牛人的学习方法
- 框架设计之菜鸟漫漫江湖路系列 一:菜鸟入门
- 菜鸟学习从入门到放弃(二)排序算法总结与应用(附代码)
- Linux 菜鸟入门级命令大全
- java程序员菜鸟入门之七java集合
- Stm32 DMA
- java程序员菜鸟入门之十一jQuery
- JAVA菜鸟入门(5) Hashmap vs Hashtable