STM32时隔几个月的初学——DMA数据转运

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

const uint8_t aa = 0x66;

int main(void)
{
	OLED_Init();
	
	OLED_ShowHexNum(1, 1, aa, 2);
	OLED_ShowHexNum(2, 1, (uint32_t)&aa, 8);
	
	while(1)
	{	
		
	}
}

小实验——来验证存储器的地址映像

  • tips:C语言知识——const是关键字,在代码中使临时变量aa成为常量,这时的aa从原来的在运行内存SRAM中的地址映像——》现在的程序存储器Flash的地址映像。(存在尾部地址偏移)
  • flash——存储C语言编译后的程序代码和常量数据

定义常量和变量

  • 常量何时定义???
  • 当程序中出现一大批数据,且不需要更改时。——advantage——节省SRAM的空间
  • eg、查找表,字库数据等

  • 对于变量与常量,其地址由编译器所决定,程序不同,地址不同,不固定。 
  • 对于外设寄存器,其地址固定,可由手册查得

 

OLED_ShowHexNum(2, 1, (uint32_t)&ADC1->DR, 8);
//以结构体方式访问寄存器

 OLED显示:4001244C

寄存器实际地址:起始地址 + 偏移地址

如何以结构体方式访问寄存器——ADC1->DR???

 40000000 + 10000 + 2400 = 40012400

有点俄罗斯套娃的意思

STM32使用结构体访问外设寄存器

现在得到基地址BASE,起始地址 + 偏移地址——STM32通过结构体来实现

 

  •  结构体依次定义了各种寄存器,其结构体成员顺序与手册中寄存器实际存放地址一一对应。
  • 即使结构体内存与外设寄存器内存完美重合。——所以——访问结构体的某个成员也就相当于访问这个外设的某个寄存器。

解析:ADC1->DR

  • ADC1——结构体指针——指向ADC1外设的基地址BASE
  • ->的妙用:结构体指针要使用   ->   来取成员
  • DR——寄存器成员——对应于结构体成员
  • 访问结构体成员,即加上其对应的地址偏移
  • 所以:基地址BASE(起始地址) + 地址偏移 = 指定寄存器
  • 以上是库函数访问寄存器的原理,较为麻烦和复杂

我们也可通过指针来访问某个物理地址——较为easy

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

#define ADC1_DR    (uint32_t *)0X4001244C  //定义指针

int main(void)
{
	OLED_Init();
	//  *ADC1_DR        //利用*取指针内容
	
	OLED_ShowHexNum(2, 1, (uint32_t)&ADC1->DR, 8);
	OLED_ShowHexNum(3, 1, *ADC1_DR, 8);   //error
	
	
	
	while(1)
	{	
		
	}
}

给DMA建立模块——有些不同

  • 平时我们建立模块涉及外围电路,所以建立在
  •  DMA建立模块——不涉及外围电路,所以建立在

 SRAM的地址由编译器分配,不固定,所以我们不会写绝对地址,而是通过数组名来获得地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
工程是基于STM32F207的ADC_DMA的整体程序 #define ADC1_DR_Address ((u32)0x4001204C) //ADC1数据寄存器地址=ADC1基准地址(0x40012000)+数据寄存器偏移地址(0x4c) GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);// 使能 GPIO 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);// 开启ADC时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // 开启DMA时钟 DMA_DeInit(DMA2_Stream0); DMA_InitStructure.DMA_Channel=DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;// 外设基址为:ADC 数据寄存器地址 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ad;_start;// 存储器地址,实际上就是一个内部SRAM的变量 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;// 数据传输方向为外设到存储器 DMA_InitStructure.DMA_BufferSize = 1;// 缓冲区大小为,指一次传输的数据DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设寄存器只有一个,地址不用递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 存储器地址 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;// 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 存储器数据大小也为半字,跟外设数据大小相同 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 循环传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // 禁止DMA FIFO ,使用直连模式 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值