stm32笔记

1. 什么是嵌入式系统?

   ---- 以应用为中心,以计算机技术为基础,软硬件可裁减,以适应应用系统对功能、可靠性、成本、
   ---- 体积和功耗等有严格要求的专用计算机系统。
   
   ---- 嵌入的意义:嵌入到目标系统中的计算机系统
   
   
2. 最小系统由哪些部分组成?

   ---- MCU/MPU,电源系统,时钟系统,复位系统,下载调试系统,FLASH,RAM
   
   
3. 什么是 ARM?

   ---- 高级精简指令集机器,体系结构
   ---- 英国的一家芯片公司,使用 chipless 模式销售。
   
   
4. Cortex-A 系列用于什么产品?

   ---- 应用型:手机,平板
   
   
5. Cortex-R 系列用于什么产品?

   ---- 实时场景:汽车制动系统、汽车安全气囊,打印机,网络设备
   
   
6. Cortex-M 系列用于什么产品?

   ---- 价廉物美,价格低、性能高:无人机,智能手表
   
   
7. Cortex-M3 的体系结构是什么?

   ---- ARMv7M
   
   
8. STM32F103RC 的内核是什么?

   ---- Cortex-M3
   
   
9. 每个芯片一般包含哪几个层次的型号/版本号?

   ---- 芯片型号,如 STM32F103RCT6
   ---- 内核版本号,如 Cortex-M3
   ---- 体系结构版本号,如 ARMv7M
   
   
10. mcuisp 工具烧录需要什么文件?

    ---- .hex 文件
    
11. J-Link 烧录需要什么文件?

    ---- .bin 或 .axf
    
12. Keil 可以烧录程序到开发板吗?

    ---- 可以,通过 ST-Link 或 J-Link,等等

    
13. 由 .axf 文件生成 .bin 文件的命令?

    ---- Keil安装路径\ARM\ARMCC\bin\fromelf.exe --bin -o 输出文件路径\文件名.bin 输出文件路径\文件名.axf
    ---- C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin -o .\Objects\demo.bin .\Objects\demo.axf
    ---- Keil 默认生成 .axf 文件,如果需要生成 .hex 文件,必须勾选 Output 选项卡下的 Create HEX file 选项
    ---- 如果要生成 .bin 就必须执行 fromelf 命令
    
    
====================================================================================

1. 交叉开发

   在办公系统中进行软件开发(编辑、编译),下载程序到目标系统中运行、调试,如果发现 BUG,
   回到办公系统中再次编辑、编译,然后再次下载,这样重复在两个系统中进行的开发称为交叉开发。

   交叉开发工具:
   
     软件:Keil,usb 烧录器 mcuisp.exe,
     硬件:USB 线,ST-Link 烧录调试设备,J-Link 烧录调试设备
   
2. 软件开发前的准备工作

   环境搭建:开发软件 Keil、IAR 等。安装板级支持包。
   烧录工具:软件 keil/mcuisp,硬件 ST-Link、J-Link、USB 线
   硬件:产品(开发板、传感器)
   需求:完成的功能、功耗等
   资料:原理图,MCU 芯片用户手册、数据手册、编程手册,其他外设、传感器手册。
         获取渠道:官网、百度、谷歌、供应商

3. GPIO 通用 IO

   GPIO 是 MCU 中的一种设备,通过它可以直接控制 MCU 的 IO 口(引脚)

   STM32F103RCT6 有 GPIOA, GPIOB, GPIOC, GPIOD 共 4 个 GPIO 接口。
   每个 GPIO 接口最多可以管理 16 个 IO 口。
   
   对 GPIO 接口的控制,可以通过 7 个寄存器来实现:
   
   . 两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)
   . 两个16位数据寄存器(GPIOx_IDR,GPIOx_ODR)
   . 一个32位置位/复位寄存器(GPIOx_BSRR),
   . 一个16位复位寄存器(GPIOx_BRR)
   . 一个32位锁定寄存器(GPIOx_LCKR)

   复用功能:一脚多用(通用功能,外设功能)。比如:
   14 号引脚,通用 IO 是 PA0,外设功能有:
     WKUP
     USART2_CTS
     ADC123_IN0
     TIM2_CH1_ETR
     TIM5_CH1
     TIM8_ETR

   4 种输入模式:
   
   ─ 输入浮空(既不上拉也不下拉,状态未定,由外部电路决定输入状态)
   ─ 输入上拉(内部接上拉电阻)
   ─ 输入下拉(内部接下拉电阻)
   ─ 模拟输入
   
   4 种输出模式:
   
   ─ 开漏输出(用于 GPIO 通用功能)
   ─ 推挽式输出(用于 GPIO 通用功能)
   ─ 推挽式复用功能(用于外设)
   ─ 开漏复用功能(用于外设)

   开漏可以实现:线与功能,电流型驱动。
   一般输出数字信号时配置为推挽,需要“线与”功能时配置为开漏。

   一个 IO 口需要 4 个位来配置模式,16 个 IO 口需要 64 个位,因此共需要两个 32 位寄存器,
   CRL 寄存器配置 IO0 ~ IO7,CRH 寄存器配置 IO8 ~ IO15。
   
   对输出数据寄存器 ODR 写的值,可以通过 ODR 读取。
   
   为什么要通过 BSRR 寄存器和 BRR 寄存器来操作 ODR? 
   
   确保对 ODR 的写入是原子的,中途不会被中断,因此软件不需要因为对 ODR 的写入而禁止中断。
   
   当对GPIOx_ODR的个别位编程时,软件不需要禁止中断:在单次APB2写操作里,可以只更改一个或多个位。
   这是通过对“置位/复位寄存器”(GPIOx_BSRR,复位是 GPIOx_BRR)中想要更改的位写’1’来实现的。
   没被选择的位将不被更改。

   标准库中将对寄存器的操作封装在函数中,因此调用标准库函数也就操作了寄存器。

4. volatile 的作用

   编译器可能对变量有以下优化:
   
   . 对同一变量的连续多次赋值时,可能只保留最后一次赋值,而优化掉前面几步的赋值。如:
     a = 1; // 优化删除
     a = 2; // 优化删除
     a = 3; // 优化删除
     a = 4; // 只保留这一次赋值
     
   . 重新排列对变量操作的语句
   
   . 对变量的访问,为了加快速度,将变量保存到高速缓存中,之后从高速缓存中访问这个变量
   
   使用 volatile 修饰的变量,编译器就不会进行以上优化。
   
5. 复用功能重映射

   一个功能可以由多个引脚去完成,称为复用功能重映射。
   
   复用功能重映射需要使用 AFIO 寄存器,因此需要使能 AFIO 时钟。
   
   调用 void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState) 函数进行重映射:
   
   GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);
   
6. KEIL 自带的模拟器是使用软件来模拟芯片的通用 IO,无法模拟外设。

1. 位带/位段

   位带区域:可以直接操作某个位,但不能直接操作需要通过它的别名区域进行操作
   有两个位带区域:
        位带区域                   位带别名区域
   0x20000000-0x200FFFFF(1M)  0x22000000-0x23FFFFFF(32M)  SRAM地址
   0x40000000-0x400FFFFF(1M)  0x42000000-0x43FFFFFF(32M)  外设寄存器地址

   通过位带别名区域的一个字(32位)来操作位带区域的一个位(32:1)
   
   字节:8 位
   半字:16 位,2 个字节
   字:  32 位,4 个字节
   
   位带区域映射到别名区域的公式:
   
   别名区域位映射字偏移量 bit_word_offset = (byte_offset x 32) + (bit_number x 4)
   别名区域位映射字地址   bit_word_addr = bit_band_base + bit_word_offset
   
   其中 bit_band_base 分别是 0x22000000 和 0x42000000
   byte_offset 是字节偏移量,即字节相对于起始地址的偏移量,如:0x40013800 中的 0x13800 即是。
   bit_number 位编号
   
2. 启动模式

   三种启动模式:用户闪存存储器,系统存储器,SRAM
   无论哪一种启动模式,最终都是映射到 0x00000000 地址执行。
   
   用户闪存存储器保存我们录到 MCU 的程序。
   系统存储器保存芯片生产线上烧录的启动程序。
   SRAM 是将程序复制到其内运行。
   
   选择启动模式:
   
   boot1 boot0 启动位置       存储地址
     x     0   用户闪存存储器 0x08000000
     0     1   系统存储器     0x1FFFFFFF
     1     1   SRAM           0x20000000
   
3. 启动流程

   0x00000000 地址读取栈顶指针(加载到 SP 寄存器)
   0x00000004 地址读取复位处理函数 Reset_Handler(),并跳转执行(加载到 PC 寄存器)
   Reset_Handler() 函数中先调用 SystemInit() 函数,结束后返回;再调用 main() 函数,永不返回。
   SystemInit() 函数中主要做三件初始化工作:设置系统时钟,配置 FLASH,配置外部 SRAM。

4. 复位

   三种复位方式:系统复位、电源复位、备份域复位。
   
   系统复位将复位除时钟控制寄存器CSR中的复位标志和备份区域中的寄存器以外的所有寄存器
   
   当以下事件中的一件发生时,产生一个系统复位:
   
   1. NRST管脚上的低电平(外部复位) 
   2. 窗口看门狗计数终止(WWDG复位) 
   3. 独立看门狗计数终止(IWDG复位) 
   4. 软件复位(SW复位) 
   5. 低功耗管理复位
   可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源。
   
   其中软件复位:
   
   通过将Cortex™-M3中断应用和复位控制寄存器(SCB_AIRCR)中的SYSRESETREQ位置’1’,可实现软件复位。
   
   其中低功耗管理复位:
   
   在以下两种情况下可产生低功耗管理复位:
   1. 在进入待机模式时产生低功耗管理复位:
      通过将用户选择字节中的nRST_STDBY位置’1’将使能该复位。这时,即使执行了进入待机
      模式的过程,系统将被复位而不是进入待机模式。
   2. 在进入停止模式时产生低功耗管理复位:
      通过将用户选择字节中的nRST_STOP位置’1’将使能该复位。这时,即使执行了进入停机模
      式的过程,系统将被复位而不是进入停机模式。

   电源复位:
   当以下事件中之一发生时,产生电源复位:
   1. 上电/掉电复位(POR/PDR复位) 
   2. 从待机模式中返回
   电源复位将复位除了备份区域外的所有寄存器。

   备份域复位:
   当以下事件中之一发生时,产生备份区域复位。备份域复位只影响备份区域。
   1. 软件复位,备份区域复位可由设置备份区域控制寄存器RCC_BDCR中的BDRST位产生。
   2. 在VDD和VBAT两者掉电的前提下,VDD或VBAT上电将引发备份区域复位。

   core_cm3.h 中定义了以下软件复位函数:
   
#define SCB_AIRCR_VECTKEY_Pos     16
#define SCB_AIRCR_PRIGROUP_Pos    8
#define SCB_AIRCR_PRIGROUP_Msk    (7ul << SCB_AIRCR_PRIGROUP_Pos)
#define SCB_AIRCR_SYSRESETREQ_Pos 2
#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) 
static __INLINE void NVIC_SystemReset(void)
{
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      | /* 对 VECTKEY 域写 0x5FA 关键字 */
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | /* 保持优先级分阻不变 */
                 SCB_AIRCR_SYSRESETREQ_Msk);             /* 将 SYSRESETREQ 位置 1 */
  __DSB();  /* 设置内存屏障,确保之前的变量访问完成 */
  while(1); /* 等待复位 */
}

   对 SCB->AIRCR 寄存器写操作时,必须对高 16 位(VECTKEY域)写 0x5FA 关键字。

5. 时钟

   三种不同的时钟源可被用来驱动系统时钟(SYSCLK):
   
   ● HSI振荡器时钟(内部高速 RC 时钟,如 8MHz)
   ● HSE振荡器时钟(外部高速晶振时钟,如 8MHz)
   ● PLL(锁相环)时钟(引入时钟源进行倍频产生系统所需的高速时钟)
   
   这些设备有以下2种二级时钟源:
   
   ● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。RTC用于从停机/
     待机模式下自动唤醒系统。(LSI 内部低速 RC 时钟源)
   ● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。(LSE 外部低速晶振时钟源)
   
   当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。

   SystemInit() 函数内调用 SetSysClock() 函数设置系统时钟。

static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif
 /* 如果以上宏都没定义,则使用 HSI 作为系统时钟源 */
 /* If none of the define above is enabled, the HSI is used as System clock
    source (default after reset) */ 
}

/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
#define SYSCLK_FREQ_72MHz  72000000

以上宏只使能了 SYSCLK_FREQ_72MHz,说明系统使用 72MHz 时钟。

   SetSysClockTo72() 函数中实现以下功能:
   
   1. 使能 HSE
   2. 等待外部高速时钟 HSE 稳定
   3. 配置 FLASH
   4. 配置总线时钟:HCLK = SYSCLK / 1,PCLK2 = HCLK / 1,PCLK1 = HCLK / 2。
      其中 HCLK 是 AHB 总线时钟,PCLK2 是 APB2 总线时钟,PCLK1 是 APB1 总线时钟
   5. 配置 PLL 为 HSE 的 9 倍频:PLLCLK = HSE * 9 = 72 MHz
   6. 使能 PLL
   7. 等待 PLL 就绪
   8. 选择 PLL 为系统时钟源 SYSCLK
   9. 等待 PLL 成为系统时钟源
   
   各总线频率:
     SYSCLK = 72MHz
     HCLK = SYSCLK / 1 = 72MHz
     PCLK2 = HCLK / 1 = 72MHz
     PCLK1 = HCLK / 2 = 72 / 2 = 36MHz

6. 系统嘀嗒定时器

   是一个 24 位递减计数的定时器。
   
   CTRL 寄存器可:
     使能/关闭定时器         (第 0 位)
     使能/禁用中断           (第 1 位)
     配置时钟源(AHB, AHB/8)(第 2 位)
     获取/清除到期标志       (第 16 位)
   
   LOAD 寄存器保存计数值,开始计数时将其值加载到 VAL 寄存器中。
   假如计数值为 N,如果连续计数就设置为 "N - 1",如果是单次计数就设置为 "N"。
   注意这是一个 24 位的寄存器,因此可设置的最大值为 0x00FFFFFF。
   
   VAL 寄存器用于递减计数,它的初始值从 LOAD 寄存器加载。当计数到 0 时,会自动设置 CTRL 的 16 位。
   注意这是一个 24 位的寄存器,因此最大加载值为 0x00FFFFFF。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值