STM32入门基础知识点

一、什么是32单片机

在学习STM32之前,首先应该学习一下51单片机。51单片机作为一款入门级的经典单片机,是目前应用最广泛的8位单片机之一。但随着市场产品竞争的加剧,51单片机现有的资源就显得力不从心了。

ARM公司首先推出了基于ARMv7架构对的32位Cortex-M3微型控内核,紧随其后ST公司推出了基于Cortex-M3内核的STM32单片机。因此,STM32的芯片由两部分组成:Cortex-M3微型控内核+ST公司开发的片上外设。

STM32入门基础知识点_第1张图片

Cortex-M3内核相当于CPU,CPU和片上外设是通过4条总线来完成的:

1、ICode总线中的I表示Instruction,即指令。我们写好的程序编译后就变成一条条指令,都存储在Flash中,ICode总线就是内核读取指令的专用通道。

2、Dcode总线中的D表示Data,即数据。数据分为常量和变量,常量存储在内部Flash中,变量存储在内部SRAM中。因为DMA也可以访问数据,为了便面访问冲突,在取数的时候需要经过一个总线矩阵仲裁。

3、System总线主要用来访问外设的寄存器。

4、DMA总线即可以传输内部Flash中的数据、也可以传输SRAM和外设的寄存器中的数据。因为DCode也可以访问数据,为了便面访问冲突,在取数的时候需要经过一个总线矩阵仲裁。

5、片上外设(如GPIO、USART、IIC、SPI等)是挂在由AHB总线延伸出来的APB1和APB2总线上

二、存储器映射和寄存器映射

存储器映射

存储器本身不具有地址信息,它的地址是由厂家或者用户分配的,给存储器分配地址的过程叫做存储器映射,如果给存储器再分配一个地址就叫存储器重映射。

STM32的内部Flash、SRAM、AHB桥和APB桥,片上外设等共同排列在一个4GB的地址空间内。这个4GB空间被分为个块,分别为:Block0、Block1、Block2、Block3、Block4、Block5、Block6、Block7,其中Block0被设计成内部Flash、Block1位SRAM、Block2被设计成片上外设。

序号 用途 地址范围
Block0 Code 0x0000 0000~0x1FFF FFFF
Block1 SRAM 0x2000 0000~0x3FFF FFFF
Block2 片上外设 0x4000 0000~0x5FFF FFFF
Block3 FSMC的bank1~bank2 0x6000 0000~0x7FFF FFFF
Block4 FSMC的bank3~bank4 0x8000 0000~0x9FFF FFFF
Block5 FSMC寄存器 0xA000 0000~0xBFFF FFFF
Block6 没有使用 0xC000 0000~0xDFFF FFFF
Block7 Cortex-M3内部外设 0xE000 0000~0xFFFF FFFF

寄存器映射

Block2中设计的是片上外设,其中每4个字节(32位)为一个单元,每一个单元对应不同的功能,控制这些单元就可以驱动片上外设工作。我们可以利用指针来访问这些单元,但是STM32中有很多单元,利用这种方式来访问,不好记忆且容易出错。根据每一个单元功能的不同,以功能为名给这个内存单元去一个别名,这个别名就是寄存器

给已经分配好地址的、有特定功能的内存单元取别名的过程就叫寄存器映射

寄存器的封装示例
#define FLASH_BASE            ((uint32_t)0x08000000) //FLASH
#define SRAM_BASE             ((uint32_t)0x20000000) //SRAM
#define PERIPH_BASE           ((uint32_t)0x40000000) //片上外设基地址



#define APB1PERIPH_BASE       PERIPH_BASE            //APB1总线基地址
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)//APB2总线基地址
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)//AHB总线基地址

#define TIM2_BASE             (APB1PERIPH_BASE + 0x0000) //定时器TIM2基地址
#define TIM3_BASE             (APB1PERIPH_BASE + 0x0400)
#define TIM4_BASE             (APB1PERIPH_BASE + 0x0800)
#define TIM5_BASE             (APB1PERIPH_BASE + 0x0C00)
#define TIM6_BASE             (APB1PERIPH_BASE + 0x1000)
#define TIM7_BASE             (APB1PERIPH_BASE + 0x1400)
#define TIM12_BASE            (APB1PERIPH_BASE + 0x1800)
#define TIM13_BASE            (APB1PERIPH_BASE + 0x1C00)
#define TIM14_BASE            (APB1PERIPH_BASE + 0x2000)
#define RTC_BASE              (APB1PERIPH_BASE + 0x2800)  
#define WWDG_BASE             (APB1PERIPH_BASE + 0x2C00)
#define IWDG_BASE             (APB1PERIPH_BASE + 0x3000)
#define SPI2_BASE             (APB1PERIPH_BASE + 0x3800)
#define SPI3_BASE             (APB1PERIPH_BASE + 0x3C00)
#define USART2_BASE           (APB1PERIPH_BASE + 0x4400)
#define USART3_BASE           (APB1PERIPH_BASE + 0x4800)
#define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)
#define UART5_BASE            (APB1PERIPH_BASE + 0x5000)
#define I2C1_BASE             (APB1PERIPH_BASE + 0x5400)
#define I2C2_BASE             (APB1PERIPH_BASE + 0x5800)
#define CAN1_BASE             (APB1PERIPH_BASE + 0x6400)
#define CAN2_BASE             (APB1PERIPH_BASE + 0x6800)
#define BKP_BASE              (APB1PERIPH_BASE + 0x6C00)
#define PWR_BASE              (APB1PERIPH_BASE + 0x7000)
#define DAC_BASE              (APB1PERIPH_BASE + 0x7400)
#define CEC_BASE              (APB1PERIPH_BASE + 0x7800)

#define AFIO_BASE             (APB2PERIPH_BASE + 0x0000)
#define EXTI_BASE             (APB2PERIPH_BASE + 0x0400)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800) //GPIOA基地址
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)
#define ADC1_BASE             (APB2PERIPH_BASE + 0x2400)
#define ADC2_BASE             (APB2PERIPH_BASE + 0x2800)
#define TIM1_BASE             (APB2PERIPH_BASE + 0x2C00)
#define SPI1_BASE             (APB2PERIPH_BASE + 0x3000)
#define TIM8_BASE             (APB2PERIPH_BASE + 0x3400)
#define USART1_BASE           (APB2PERIPH_BASE + 0x3800)
#define ADC3_BASE             (APB2PERIPH_BASE + 0x3C00)
#define TIM15_BASE            (APB2PERIPH_BASE + 0x4000)
#define TIM16_BASE            (APB2PERIPH_BASE + 0x4400)
#define TIM17_BASE            (APB2PERIPH_BASE + 0x4800)
#define TIM9_BASE             (APB2PERIPH_BASE + 0x4C00)
#define TIM10_BASE            (APB2PERIPH_BASE + 0x5000)
#define TIM11_BASE            (APB2PERIPH_BASE + 0x5400)

#define SDIO_BASE             (PERIPH_BASE + 0x18000)

#define DMA1_BASE             (AHBPERIPH_BASE + 0x0000)
#define DMA1_Channel1_BASE    (AHBPERIPH_BASE + 0x0008)
#define DMA1_Channel2_BASE    (AHBPERIPH_BASE + 0x001C)
#define DMA1_Channel3_BASE    (AHBPERIPH_BASE + 0x0030)
#define DMA1_Channel4_BASE    (AHBPERIPH_BASE + 0x0044)
#define DMA1_Channel5_BASE    (AHBPERIPH_BASE + 0x0058)
#define DMA1_Channel6_BASE    (AHBPERIPH_BASE + 0x006C)
#define DMA1_Channel7_BASE    (AHBPERIPH_BASE + 0x0080)
#define DMA2_BASE             (AHBPERIPH_BASE + 0x0400)
#define DMA2_Channel1_BASE    (AHBPERIPH_BASE + 0x0408)
#define DMA2_Channel2_BASE    (AHBPERIPH_BASE + 0x041C)
#define DMA2_Channel3_BASE    (AHBPERIPH_BASE + 0x0430)
#define DMA2_Channel4_BASE    (AHBPERIPH_BASE + 0x0444)
#define DMA2_Channel5_BASE    (AHBPERIPH_BASE + 0x0458)
#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
#define CRC_BASE              (AHBPERIPH_BASE + 0x3000)

#define FLASH_R_BASE          (AHBPERIPH_BASE + 0x2000) /*!< Flash registers base address */
#define OB_BASE               ((uint32_t)0x1FFFF800)    /*!< Flash Option Bytes base address */

#define ETH_BASE              (AHBPERIPH_BASE + 0x8000)
#define ETH_MAC_BASE          (ETH_BASE)
#define ETH_MMC_BASE          (ETH_BASE + 0x0100)
#define ETH_PTP_BASE          (ETH_BASE + 0x0700)
#define ETH_DMA_BASE          (ETH_BASE + 0x1000)

#define FSMC_Bank1_R_BASE     (FSMC_R_BASE + 0x0000) /*!< FSMC Bank1 registers base address */
#define FSMC_Bank1E_R_BASE    (FSMC_R_BASE + 0x0104) /*!< FSMC Bank1E registers base address */
#define FSMC_Bank2_R_BASE     (FSMC_R_BASE + 0x0060) /*!< FSMC Bank2 registers base address */
#define FSMC_Bank3_R_BASE     (FSMC_R_BASE + 0x0080) /*!< FSMC Bank3 registers base address */
#define FSMC_Bank4_R_BASE     (FSMC_R_BASE + 0x00A0) /*!< FSMC Bank4 registers base address */

#define DBGMCU_BASE          ((uint32_t)0xE0042000) /*!< Debug MCU registers base address */

三、学习方法

了解了存储器和寄存器映射的相关知识,我们就可以进一步了解其编程方法。

51单片机编程是经典的位操作,例如通过关键字sbit实现位定义,通过对一个比特位进行读和写,来控制I/O点的电平或者完成其他操作(定时、串口通信等)。其编程实质就是利用位操作,控制51单片机上的片上寄存器。

例如,点亮一个LED。

/*--------------------------------------------------------------------------
点亮一个LED
--------------------------------------------------------------------------*/
#include   //51单片机头文件
#define uchar unsigned char
#define uint  unsigned int
sbit LED1=P2^0; //P2^0即为51单片机的寄存器,其封装定义可在reg52.h中查看
void main(void)
{
 LED1=0;
 while(1);
}


/*--------------------------------------------------------------------------
头文件 REG52.H ,内部有对51单片机的寄存器的封装
--------------------------------------------------------------------------*/

#ifndef __REG52_H__
#define __REG52_H__

/*  BYTE Registers  */
sfr P0    = 0x80;
sfr P1    = 0x90;
sfr P2    = 0xA0;
sfr P3    = 0xB0;
sfr PSW   = 0xD0;
sfr ACC   = 0xE0;
sfr B     = 0xF0;
sfr SP    = 0x81;
sfr DPL   = 0x82;
sfr DPH   = 0x83;
sfr PCON  = 0x87;
sfr TCON  = 0x88;
sfr TMOD  = 0x89;
sfr TL0   = 0x8A;
sfr TL1   = 0x8B;
sfr TH0   = 0x8C;
sfr TH1   = 0x8D;
sfr IE    = 0xA8;
sfr IP    = 0xB8;
sfr SCON  = 0x98;
sfr SBUF  = 0x99;

/*  8052 Extensions  */
sfr T2CON  = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2    = 0xCC;
sfr TH2    = 0xCD;


/*  BIT Registers  */
/*  PSW  */
sbit CY    = PSW^7;
sbit AC    = PSW^6;
sbit F0    = PSW^5;
sbit RS1   = PSW^4;
sbit RS0   = PSW^3;
sbit OV    = PSW^2;
sbit P     = PSW^0; //8052 only

/*  TCON  */
sbit TF1   = TCON^7;
sbit TR1   = TCON^6;
sbit TF0   = TCON^5;
sbit TR0   = TCON^4;
sbit IE1   = TCON^3;
sbit IT1   = TCON^2;
sbit IE0   = TCON^1;
sbit IT0   = TCON^0;

/*  IE  */
sbit EA    = IE^7;
sbit ET2   = IE^5; //8052 only
sbit ES    = IE^4;
sbit ET1   = IE^3;
sbit EX1   = IE^2;
sbit ET0   = IE^1;
sbit EX0   = IE^0;

/*  IP  */
sbit PT2   = IP^5;
sbit PS    = IP^4;
sbit PT1   = IP^3;
sbit PX1   = IP^2;
sbit PT0   = IP^1;
sbit PX0   = IP^0;

/*  P3  */
sbit RD    = P3^7;
sbit WR    = P3^6;
sbit T1    = P3^5;
sbit T0    = P3^4;
sbit INT1  = P3^3;
sbit INT0  = P3^2;
sbit TXD   = P3^1;
sbit RXD   = P3^0;

/*  SCON  */
sbit SM0   = SCON^7;
sbit SM1   = SCON^6;
sbit SM2   = SCON^5;
sbit REN   = SCON^4;
sbit TB8   = SCON^3;
sbit RB8   = SCON^2;
sbit TI    = SCON^1;
sbit RI    = SCON^0;

/*  P1  */
sbit T2EX  = P1^1; // 8052 only
sbit T2    = P1^0; // 8052 only
             
/*  T2CON  */
sbit TF2    = T2CON^7;
sbit EXF2   = T2CON^6;
sbit RCLK   = T2CON^5;
sbit TCLK   = T2CON^4;
sbit EXEN2  = T2CON^3;
sbit TR2    = T2CON^2;
sbit C_T2   = T2CON^1;
sbit CP_RL2 = T2CON^0;

#endif

和51单片机一样,32也可以通过类似的方法(位带操作),控制片上外设的寄存器。STM32中没有sbit这样的关键字,其对片上外设寄存器的控制是通过访问位带别名区来实现的。

例如,点亮LED



//32对寄存器的封装头文件stm32f10x.h
#define PERIPH_BASE           ((unsigned int)0x40000000)


#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)


#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)


#define GPIOB_CRL			*(unsigned int*)(GPIOB_BASE+0x00)
#define GPIOB_CRH			*(unsigned int*)(GPIOB_BASE+0x04)
#define GPIOB_IDR			*(unsigned int*)(GPIOB_BASE+0x08)
#define GPIOB_ODR			*(unsigned int*)(GPIOB_BASE+0x0C)
#define GPIOB_BSRR	  *(unsigned int*)(GPIOB_BASE+0x10)
#define GPIOB_BRR			*(unsigned int*)(GPIOB_BASE+0x14)
#define GPIOB_LCKR		*(unsigned int*)(GPIOB_BASE+0x18)


#define RCC_BASE      (AHBPERIPH_BASE + 0x1000)

#define RCC_APB2ENR		 *(unsigned int*)(RCC_BASE+0x18)


//主函数 
#include "stm32f10x.h" 

int main(void)
{	

	RCC_APB2ENR |= (1<<3);

	GPIOB_CRL &= ~( 0x0F<< (4*0));	
	
	GPIOB_CRL |= (1<<4*0);

	GPIOB_ODR &= ~(1<<0);
	
	while(1);
}

void SystemInit(void)
{	
}

寄存器编程:51单片机的编程,就是经典的寄存器编程。51单片机在配置I/O口,定时器和中断等的时候,都要查阅寄存器表,看看需要配置哪些位,置零还是置一。STM32同一可以直接对寄存器进行编程,不过因为32的寄存器过于繁多复杂,一般不推荐这种方式。

库函数编程:了解库函数之前,需要先了解存储器映射和寄存器映射。

你可能感兴趣的:(STM32入门基础知识点)