1.接线图/实物图如下:
2.代码部分如下:
主函数(main.c)代码部分:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyDMA.h"
uint8_t DataA[] = {0x01, 0x02, 0x03, 0x04};
uint8_t DataB[] = {0, 0, 0, 0};
int main(void)
{
OLED_Init();
MyDMA_Init((uint32_t)DataA, (uint32_t)DataB, 4);
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);
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);
OLED_ShowHexNum(4, 4, DataB[1], 2);
OLED_ShowHexNum(4, 7, DataB[2], 2);
OLED_ShowHexNum(4, 10, DataB[3], 2);
Delay_ms(1000);
MyDMA_Transfer();
OLED_ShowHexNum(2, 1, DataA[0], 2);
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);
OLED_ShowHexNum(4, 4, DataB[1], 2);
OLED_ShowHexNum(4, 7, DataB[2], 2);
OLED_ShowHexNum(4, 10, DataB[3], 2);
Delay_ms(1000);
}
}
//补充:
//在寄存器里,OLED_ShowHexNum(2, 1, (uint32_t)&ADC1->DR,8);//&ADC1->DR,取结构体指针成员的地址。
//&ADC1->HexNum表示ADC结构指针指向ADC1外设的起始地址,访问结构体成员,就相当于加一个地址偏移.起始地址+偏移=寄存器
//我们可以自己定义:
//#define ADC_DR (uint32_t*)0x4001244C
//*ADC1_DR
直接存储器(DMA.c)代码部分:
MyDMA_Size=Size;
//1.RCC开启DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//2.初始化DMA_Init结构体
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_MemoryBaseAddr=AddrB;//存储器站点的起始地址(32位),参数代替固定的地址。
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器站点的数据宽度(字节形式)
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器站点的是否自增
DMA_InitStructure.DMA_PeripheralBaseAddr=AddrA;//外设站点的起始地址
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设站点的数据宽度
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Enable;//外设站点的是否自增
DMA_InitStructure.DMA_BufferSize=Size;//缓冲区大小,(传输计数器,指定传输几次)
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//数据传输方向(DST:存储器-->外设站点,SRC:外设站点-->存储器)
DMA_InitStructure.DMA_M2M=DMA_M2M_Enable;//选择硬件触发还是软件触发(M2M_Enable存储器到存储器就是软件触发,Disable是硬件触发)
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//传输模式(指定是否自动重装)DMA_Mode_Normal:正常模式,转运之后停止
DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;//优先级(多个通道需要设置优先级,此处无所谓)
DMA_Init(DMA1_Channel1,&DMA_InitStructure);//把结构体配置的参数给DMA1里的通道1.
//第一个参数:既选择了是哪个DMA,又选择了是哪个通道。
//3.开关控制DMA_Cmd
DMA_Cmd(DMA1_Channel1,DISABLE);
}//转运一次,传输寄存器自减一次。传输寄存器为0时,转运结束。
//调用该函数,就在进行一次转运(给传输计数器重新赋值)
void MyDMA_Transfer(void)
{
DMA_Cmd(DMA1_Channel1,DISABLE);//关闭
DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size);//给传输计数器赋值
DMA_Cmd(DMA1_Channel1,ENABLE);//开启
while(DMA_GetFlagStatus(DMA1_FLAG_TC1)==RESET);//检查DMA1的通道1转运完成标志位,转运完成,标志位置1
DMA_ClearFlag(DMA1_FLAG_TC1);//清除标志位状态
}
直接存储器(DMA.h)代码部分:
#ifndef __MyDMA_H
#define __MyDMA_H
void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size);
#endif
3.//补充的DMA(数据传输部分)库函数:
//void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);//中断输出使能
//void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); //给传输计数器赋值
//uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);//获取数据寄存器的数据
//FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);//获取标志位状态函数
//void DMA_ClearFlag(uint32_t DMAy_FLAG);清除标志位状态
//ITStatus DMA_GetITStatus(uint32_t DMAy_IT);//获取中断状态
//void DMA_ClearITPendingBit(uint32_t DMAy_IT);//清除中断状态