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);//清除中断状态