STM32入门(10)

STM32入门(10)

image-20260315183857611

项目一:DMA数据转运

#include "stm32f10x.h"                    // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyDMA.h"

uint8_t DataA[] = {0x01,0x02,0x03,0x04};  // 定义测试数组DataA,为数据源 
uint8_t DataB[] = {0,0,0,0};              // 定义测试数组DataB,为数据目的地

int main()
{
	
	// 模块初始化
	OLED_Init();                                    // OLED初始化
	
	MyDMA_Init((uint32_t)DataA,(uint32_t)DataB,4);  // DMA初始化,把源数组和目的地的数组的地址传入
	
	// 显示静态字符串
	OLED_ShowString(1,1,"DataA"); 
	OLED_ShowString(3,1,"DataB");
	
	// 显示数组的首地址
	OLED_ShowHexNum(1,8,(uint32_t)DataA,8);
	OLED_ShowHexNum(3,8,(uint32_t)DataB,8);	

	while(1)
	{
		DataA[0] ++;       // 变换测试数据
		DataA[1] ++;
		DataA[2] ++;
		DataA[3] ++;
		
		OLED_ShowHexNum(2, 1,DataA[0],2);     // 显示数组DataA
		OLED_ShowHexNum(2, 4,DataA[1],2);
		OLED_ShowHexNum(2, 7,DataA[2],2);
		OLED_ShowHexNum(2,10,DataA[3],2);
		OLED_ShowHexNum(4, 1,DataB[0],2);     // 显示数组DataB
		OLED_ShowHexNum(4, 4,DataB[1],2);
		OLED_ShowHexNum(4, 7,DataB[2],2);
		OLED_ShowHexNum(4,10,DataB[3],2);	
		
		Delay_ms(1000);         			  // 延时1s,观察转运前的现象
		
		MyDMA_Transfer();       			  // 使用DMA转运数组,从DataA转运到DataB
		
		OLED_ShowHexNum(2, 1,DataA[0],2);     // 显示数组DataA
		OLED_ShowHexNum(2, 4,DataA[1],2);
		OLED_ShowHexNum(2, 7,DataA[2],2);
		OLED_ShowHexNum(2,10,DataA[3],2);
		OLED_ShowHexNum(4, 1,DataB[0],2);     // 显示数组DataB
		OLED_ShowHexNum(4, 4,DataB[1],2);
		OLED_ShowHexNum(4, 7,DataB[2],2);
		OLED_ShowHexNum(4,10,DataB[3],2);	
		
		Delay_ms(1000);         			  // 延时1s,观察转运后的现象 
	}
}

#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;                    // 定义全局变量,用于记住Init函数的Size,供Transfer函数使用

/**
  * 函    数:DMA初始化
  * 参    数:AddrA 原数组的首地址
	* 参    数:AddrB 目前数组的首地址
	* 参    数:Size 转运的数据大小(转运次数)
  * 返 回 值:无
  */
void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)
{
	MyDMA_Size = Size;                                         // 将Size写入到全局变量,记住参数Size
	
	// 开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);          // 开启DMA的时钟
	
	// DMA初始化
	DMA_InitTypeDef DMA_InitStructure;                                      // 定义结构体变量
	DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;						// 外设基地址,给定形参AddrA
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度,选择字节
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;			// 外设地址自增,选择使能
	DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;							// 存储器基地址,给定形参AddrB
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;			// 存储器数据宽度,选择字节
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					// 存储器地址自增,选择使能
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;						// 数据传输方向,选择由外设到存储器
	DMA_InitStructure.DMA_BufferSize = Size;								// 转运的数据大小(转运次数)
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							// 模式,选择正常模式
	DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;								// 存储器到存储器,选择使能
	DMA_InitStructure.DMA_Priority = DMA_M2M_Enable;						// 优先级,选择中等
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);				// 将结构体变量交给DMA_Init,配置DMA1的通道1
	
	// DMA使能
	DMA_Cmd(DMA1_Channel1,DISABLE);         // 这里先不给使能,初始化后不会立刻工作,等后续调用Transfer后,再开始

}


/**
  * 函    数:启动DMA数据转运
  * 参    数:无
  * 返 回 值:无
  */
void MyDMA_Transfer(void)
{
	DMA_Cmd(DMA1_Channel1,DISABLE);                      // DMA失能,在写入传输计数器之前,需要DMA暂停工作
	DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size);    // 写入传输计数器,指定将要转运的次数
	DMA_Cmd(DMA1_Channel1,ENABLE);                       // DMA使能,开始工作
	
	while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);    // 等待DMA工作完成
	DMA_ClearFlag(DMA1_FLAG_TC1);                        // 清除工作完成标志位
}

#ifndef __MYDMA_H
#define __MYDMA_H

void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size);
void MyDMA_Transfer(void);

#endif

posted @ 2026-03-15 21:34  Q&25  阅读(2)  评论(0)    收藏  举报