stm32 DMA
2022-01-28 22:15 jym蒟蒻 阅读(298) 评论(0) 编辑 收藏 举报stm32 DMA
- 介绍的定义
- 存储器到存储器
- main.c
- 存储器到外设
- main.c
- usart_dma.c
- usart_dma.h
- 外设到存储器
- main.c
- usart_dma.c
- usart_dma.h
- 中断函数
- 对比理解
存储器:用来存储程序代码和数据。
易失性存储器:存储器断电后,它存储的数据内容丢失。易失性存储器存取速度快,如内存。
非易失性存储器:存储器断电后,它存储的数据内容不丢失。非易失性存储器可长期保存数据,如硬盘。
RAM(Random Access Memory):随机存储器。当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。也就是说,RAM 读取其内部任意地址的数据,时间都是相同的。根据RAM 的存储机制,分为动态随机存储器 DRAM;静态随机存储器 SRAM。
DRAM(Dynamic RAM):动态随机存储器。DRAM 的存储单元以电容的电荷来表示数据,有电荷代表 1,无电荷代表 0。由于代表 1 的电容会放电,代表 0 的电容会吸收电荷,因此需要定期刷新操作,刷新操作会对电容进行检查,若电量大于满电量的 1/2,则认为其代表 1,并把电容充满电;若电量小于 1/2, 则认为其代表 0,并把电容放电。 DRAM 的结构简单,所以生产相同容量的存储器,DRAM 的成本更低,集成度更高。外部扩展的内存一般使用 DRAM。
SRAM(Static RAM):静态随机存储器。 SRAM 的存储单元以锁存器来存储数据,这种电路结构不需要定时刷新充电,就能保持状态。SRAM 一般用于 CPU 内部的高速缓存(Cache)。
SDRAM(Synchronous DRAM):同步通讯方式的DRAM,使用时钟同步的通讯速度更快。SDRAM 只在上升沿表示有效数据,在 1 个时钟周期内,只能表示 1 个有数据。
DDR SDRAM(Double Data Rate SDRAM):在时钟的上升沿及下降沿各表示一个数据,也就是说在 1 个时钟周期内可以表示 2 位数据,在时钟频率同样的情况下, 提高了一倍的速度。
ROM(Read Only Memory):英文是只能读的存储器,后来人们设计出可以写入数据的 ROM。用于指代非易失性半导体存储器。
MASK ROM:存储在它内部的数据是在出厂时使用特殊工艺固化的,生产后就不可修改,用在生产量大,数据不需要修改的场合。
EEPROM(Electrically Erasable Programmable ROM):电可擦除存储器。可重复擦写,擦除和写入都是直接使用电路控制,不需要使用外部设备。而且可以以字节为单位修改数据,无需整个芯片擦除。现在主要使用的 ROM 芯片都是 EEPROM。
FLASH:闪存,有人称为flash ROM,也是可重复擦写的储器,容量一般比 EEPROM 大得多;在擦除时,一般以多个字节为单位。有的 FLASH 存储器以 4096 个字节为扇区,最小的擦除单位为一个扇区。FLASH 存储器又分为 NOR FLASH 和 NAND FLASH。NOR 与 NAND 的共性是在数据写入前都需要有擦除操作。FLASH 的擦除次数都是有限的(10 万次左右),当使用接近寿命的时候,可能会出现写操作失败。
NOR FLASH: NOR 的地址线和数据线分开,可以按“字节”读写数据;假如 NOR 上存储了代码指令,CPU 给 NOR 一个地址,NOR 就能向 CPU 返回一个数据让 CPU 执行,中间不需要额外的处理操作。功能上可以认为 NOR 是一种断电后数据不丢失的 RAM,但他的读写速度比 RAM 要慢得多。NOR FLASH 一般应用在代码存储的场合,如嵌入式控制器内部的程序存储空间。
NAND FLASH:NAND 的数据和地址线共用,只能按“块”来读写数据;若代码存储在 NAND 上,可以把它先加载到 RAM 存储器上,再由 CPU 执行。NAND FLASH 一般应用在大数据量存储的场合,包括 SD 卡、U 盘以及固态硬盘等。
DMA:直接存储器存取,是单片机的一个外设,主要功能是搬数据,但是不需要占用 CPU(传输数据的时候,CPU 可以干其他的事情)。数据传输支持从外设到存储器、存储器到外设、存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。DMA 控制器独立于内核,属于一个单独的外设。
先定义一个静态的源数据,存放在内部 FLASH,然后使用 DMA 传输把源数据拷贝到目标地址上(内部 SRAM),最后对比源数据和目标地址的数据,看看是否传输准确。RGB 彩色灯用于指示程序状态,如果 DMA 传输成功设置 RGB 彩色灯为蓝色,如果 DMA 传输出错设置 RGB 彩色灯为红色。
void DMA_Config(void)函数是根据DMA_InitTypeDef这个结构体来编写的,整体上,关于DMA的函数和结构体定义,都在stm32f10x_dma.c和stm32f10x_dma.h文件里面,利用库函数编程其实说白了就是结合外设对应的那两个文件来编程。
main整体流程:使能 DMA 时钟;配置 DMA 数据参数;使能 DMA,进行传输;等待传输完成,并对源数据和目标地址数据进行比较。
main里面DMA_GetFlagStatus函数是获取DMA事件标志位的当前状态,参数是DMA_FLAG_TC意味着获取DMA 数据传输完成这个标志位,DMA传输完成后,退出循环,运行之后程序。
main里面Buffercmp函数,aSRC_Const_Buffer是FLASH中存储的数据,aDST_Buffer是内部的SRAM中存储的数据,BUFFER_SIZE是数据大小。
TransferStatus=Buffercmp(aSRC_Const_Buffer, aDST_Buffer, BUFFER_SIZE);
#include "stm32f10x.h"
#include "./led/bsp_led.h"
// 当使用存储器到存储器模式时候,通道可以随便选,没有硬性的规定
#define DMA_CHANNEL DMA1_Channel6
#define DMA_CLOCK RCC_AHBPeriph_DMA1
// 传输完成标志
#define DMA_FLAG_TC DMA1_FLAG_TC6
// 要发送的数据大小
#define BUFFER_SIZE 32
/* 定义aSRC_Const_Buffer数组作为DMA传输数据源
* const关键字将aSRC_Const_Buffer数组变量定义为常量类型
* 表示数据存储在内部的FLASH中
*/
const uint32_t aSRC_Const_Buffer[BUFFER_SIZE]= {
0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};
/* 定义DMA传输目标存储器
* 存储在内部的SRAM中
*/
uint32_t aDST_Buffer[BUFFER_SIZE];
#define SOFT_DELAY Delay(0x0FFFFF);
void Delay(__IO u32 nCount);
uint8_t Buffercmp(const uint32_t* pBuffer, uint32_t* pBuffer1, uint16_t BufferLength);
void DMA_Config(void);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
/* 定义存放比较结果变量 */
uint8_t TransferStatus;
/* LED 端口初始化 */
LED_GPIO_Config();
/* 设置RGB彩色灯为紫色 */
LED_PURPLE;
/* 简单延时函数 */
Delay(0xFFFFFF);
/* DMA传输配置 */
DMA_Config();
/* 等待DMA传输完成 */
while(DMA_GetFlagStatus(DMA_FLAG_TC)==RESET)
{
}
/* 比较源数据与传输后数据 */
TransferStatus=Buffercmp(aSRC_Const_Buffer, aDST_Buffer, BUFFER_SIZE);
/* 判断源数据与传输后数据比较结果*/
if(TransferStatus==0)
{
/* 源数据与传输后数据不相等时RGB彩色灯显示红色 */
LED_RED;
}
else
{
/* 源数据与传输后数据相等时RGB彩色灯显示蓝色 */
LED_BLUE;
}
while (1)
{
}
}
void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 开启DMA时钟
RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);
// 外设
DMA_InitStructure.DMA_PeripheralBaseAddr = (