STM32入门(10)

项目一: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