1、嵌入式系统
嵌入式系统是嵌入到对象体系中的专用计算机系统。
嵌入式系统是以应用为中心,以计算机技术为基础,硬件和软件可裁剪,适应应用系统对功能、可靠性、成本、体积和功耗等严格要求的专用计算机系统。
嵌入式系统和通用计算机系统类似,由处理器、存储器、输入输出接口和输入输出设备以及软件等部分组成。
但作为专用计算机系统的嵌入式系统和通用计算机系统相比,具有以下几个重要特征:系统简练、专用性强、实时操作系统支持和专门开发工具支持。
嵌入式系统最初的应用是单片机系统。
最早的单片机是Intel公司的8048(1976)和8051(1980)。
近几年流行的是ARM公司的Cortex-M系列: Cortex-M0(基本型)、Cortex-M3、Cortex-M4(DSP)
物联网(IoT)= 互联网 + 智能硬件(嵌入式系统)。
智能硬件是以平台性底层软硬件为基础,以智能传感互联、人机交互、新型显示及大数据处理等新一代信息技术为特征,以新设计、新材料、新工艺硬件为载体的新型智能终端产品及服务。
2、嵌入式系统设计
硬件设计:需求分析;功能确定;方框图;电路图;PCB制作;硬件调试,如图所示:
image.png
软件设计:需求分析;算法确定;流程图;源程序调试运行,如图所示:
image.png
嵌入式系统的C语言程序设计与一般的C语言程序设计基本相同,主要差别是:
嵌入式系统C语言程序设计常用到位操作,包括“位反~”、“左移<<”、“右移>>”、“位与&”、“位或|”和“位异或^”等。
注意“位与&”和“位或|”与“逻辑与&&”和“逻辑或||”的区别),
使用位操作的主要目的是只对控制和状态寄存器的指定位进行操作,对其他位的值不产生影响。

3、STM32 MCU简介
image.png
STM32 MCU结构:由控制单元、从属单元和总线矩阵三大部分组成,控制单元和从属单元通过总线矩阵相连接;
控制单元包括 Cortex-M3内核和两个DMA控制器(DMA1和DMA2);
总线矩阵: ICode、DCode、System、AHB、APB1、APB2,如下图所示:

image.png
从属单元包括存储器(Flash和SRAM等)和设备(连接片外设备的接口和片内设备);AHB、APB1、APB2:APB1(36MHz);APB2(72MHz)
连接片外设备的接口有并行接口和串行接口,并行接口即通用IO接口GPIO,串行接口有USART、SPI、I2C、USB和CAN等;片内设备有定时器TIM、模数转换器ADC和数模转换器DAC等。

STM32 MCU存储器映像:

程序存储器、数据存储器和输入输出端口寄存器被组织在同一个4GB的线性地址空间内,如下图所示:
image.png
STM32 MCU系统时钟树:
系统时钟树由系统时钟源、系统时钟和设备时钟等部分组成。系统时钟源有4个:高速外部时钟HSE、低速外部时钟LSE、高速内部时钟HSI和低速内部时钟LSI。外部时钟用OSC实现,内部时钟用RC实现。 如下图所示:

image.png
系统时钟SYSCLK可以是HSE或HSI,也可以是HSE或HSI通过锁相环倍频后的锁相环时钟PLLCLK。
SYSCLK经AHB预分频器分频后得到AHB总线时钟HCLK,HCLK经APB1/APB2预分频器分频后得到APB1/APB2总线时钟PCLK1和PCLK2。

系统时钟树中的时钟选择、预分频值和外设时钟使能等都可以通过对复位和时钟控制(RCC)寄存器编程实现,如下图所示:
image.png
复位和时钟控制(RCC)寄存器结构体RCC_TypeDef在Drivers\CMSIS\Device\ST\STM32F1xx\ Include\stm32f103xb.h中定义。
RCC常用的HAL宏定义在stm32f1xx_hal_rcc.h中定义如下:
__HAL_RCC_AFIO_CLK_ENABLE()                /* 允许AFIO时钟 */
  ……………………………………………
复位和时钟控制(RCC)寄存器结构体RCC_TypeDef在Drivers\CMSIS\Device\ST\STM32F1xx\ Include\stm32f103xb.h中定义。
RCC常用的LL库函数在stm32f1xx_ll_bus.h中声明如下:
void LL_APB1_GRP1_EnableClock(uint32_t Periphs);
void LL_APB2_GRP1_EnableClock(uint32_t Periphs);
参数说明:
     ★ Periphs:设备名称,在stm32f1xx_ll_bus.h中声明定义如下:
   #define LL_APB1_GRP1_PERIPH_I2C1                RCC_APB1ENR_I2C1EN
   #define LL_APB2_GRP1_PERIPH_ADC1                RCC_APB2ENR_ADC1EN
   …………………………………………………………………………………
Cortex-M3简介:
Cortex-M3是采用哈佛结构的32位处理器内核,拥有独立的指令总线和数据总线,两者共享同一个4GB存储空间。
Cortex-M3内建一个嵌套向量中断控制器(NVIC:Nested Vectored Interrupt Controller),支持可嵌套中断、向量中断和动态优先级等。
Cortex-M3内部还包含一个系统滴答定时器SysTick。
SysTick的核心是1个24位递减计数器,使用时根据需要设置初值,启动后在系统时钟的作用下递减,减到0时置计数标志位并重装初值。
系统可以查询计数标志位,也可以在中断允许时产生SysTick中断,如下图所示:


image.png
SysTick通过4个32位寄存器进行操作,如下图所示:
image.png
控制状态寄存器有3个控制位和1个状态位,如下图所示:
image.png
SysTick常用的HAL库函数在stm32f1xx_hal.c中声明如下:
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
void HAL_Delay(uint32_t Delay);
1)SysTick初始化
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
参数说明:
  ★ TickPriority:SysTick中断优先级,在stm32f1xx_hal_conf.h中定义如下:
   #define  TICK_INT_PRIORITY                0U
返回值:HAL_StatusTypeDef-HAL状态,在stm32f1xx_hal_def.h中定义。
2)HAL延时
void HAL_Delay(uint32_t Delay);
参数说明:
  ★ Delay:延时值(ms)
SysTick常用的LL库函数在stm32f1xx_ll_utils.h中声明如下:
void LL_Init1msTick(uint32_t HCLKFrequency);
void LL_mDelay(uint32_t Delay);
1)SysTick初始化
void LL_Init1msTick(uint32_t HCLKFrequency);
参数说明:
  ★ HCLKFrequency:HCLK频率(72MHz)
注意:LL_Init1msTick()没有允许SysTick中断,需要用stm32f1xx_ll_cortex.h中的下列函数允许SysTick中断:
void LL_SYSTICK_EnableIT(void);
2)LL延时
void LL_mDelay(uint32_t Delay);
参数说明:
  ★ Delay:延时值(ms)

Keil的SysTick对话框:

image.png
注意:HAL和LL操作本质相同。HAL操作将底层操作进行封装,操作简单,移植性好;LL操作和直接操作寄存器类似,目标程序小,有利于对硬件的理解。
4、软件配置工具STM32CubeMX的使用
STM32CubeMX的使用包括下列步骤:
1)安装嵌入式软件包

image.png
2)从MCU新建工程
image.png
3)引脚配置
    GPIO、USART2、SPI2、 I2C1、ADC1、TIM1~3

image.png
4)时钟配置
  时钟配置的步骤如下:
(1)单击时钟配置标签,在HCLK中输入“72”,显示时钟向导对话框。
(2)在时钟向导对话框中单击“Ok”自动进行时钟配置。
5)工程管理
(1)单击工程管理标签,在Project Name下输入工程名“HAL”,在Project Location下输入“D:\CT117E-F1”,Toolchain / IDE选择“MDK-ARM”,Min Version选择“V4”,使用最新工具包,或取消“Use latest available version”,选择“STM32Cube FW_F1 V1.8.0”。
注意:Keil5不支持Colink下载调试器,所以MDK-ARM版本只能选“V4”。
(2)单击“Code Generator”,在“STM32Cube MCU packkages and embedded sofeware packs”中选择“Copy only the necessary library files”(只复制必要的库文件),在“Generated Files”中选中“Generate peripheral initialization as a pair of ‘.c/.h’files per peripheral”(每个设备分别生成一对初始化‘.c/.h’文件)。
(3)单击“Advanced Settings”,驱动程序默认使用“HAL”。
6)生成HAL/LL工程
(1)单击右上角的“GENERAE CODE”生成HAL工程和初始化代码,生成完成后显示代码生成对话框。
(2)单击“Open Folder”打开工程文件夹HAL,其中包含下列文件和文件夹:
HAL.ioc:STM32CubeMX工程文件;
MDK-ARM:Keil工程文件夹,包含Keil工程文件和启动代码汇编语言文件;
Drivers:驱动软件库,包括CMSIS和STM32F1xx_HAL_Driver两个文件夹;
Core:用户文件夹,包括Inc和Src两个文件夹,Inc包括用户头文件,Src包括用户源文件和1个系统初始化源文件;
注意:为了多个工程共用驱动软件库和用户文件,可以将“Src”文件夹中的“main.c”文件剪切粘帖到“MDK-ARM”文件夹,Keil工程中也要做相应的修改。
(3)在“Advanced Settings”中将驱动程序全部修改为“LL”。
(4)单击“File”下“Save Project As ..”菜单项,将工程另存到“D:\CT117E-F1\LL”文件夹。
(5)单击右上角的“GENERAE CODE”生成LL工程和初始化代码,生成完成后打开工程文件夹LL,其中包含下列文件和文件夹:
    LL.ioc:STM32CubeMX工程文件;
    MDK-ARM:Keil工程文件夹,包含Keil工程文件和启动代码汇编语言文件;
    Drivers:驱动软件库,包括CMSIS和STM32F1xx_HAL_Driver两个文件夹;
    Core:用户文件夹,包括Inc和Src两个文件夹,Inc包括用户头文件,Src包括用户源文件和1个系统初始化源文件。