STM32

STM32是STMicroelectronics(意法半导体)推出的一系列基于ARM Cortex-M内核的32位微控制器(MCU)产品。这些微控制器提供了广泛的产品系列,覆盖了多种不同的性能和功能需求,适用于各种应用领域,包括工业控制、汽车电子、消费类电子、医疗设备等。

STM32系列微控制器以其高性能、低功耗、丰富的外设接口和灵活的开发工具而闻名。它们通常具有丰富的存储器、多种通信接口(如UART、SPI、I2C、CAN等)、模拟数字转换器(ADC)、定时器、PWM输出等功能,以满足不同应用场景下的需求。

STM32微控制器通常使用标准的ARM Cortex-M内核,包括Cortex-M0、M0+、M3、M4和M7等,这些内核具有不同的性能和功耗特性,可根据具体应用的需求进行选择。此外,STM32系列还提供了多种封装和引脚配置,以满足不同尺寸和集成度的要求。

STMicroelectronics为STM32系列提供了丰富的开发工具和支持资源,包括基于ARM开发环境的集成开发环境(IDE)、调试器、评估板和参考设计等。这些工具和资源有助于开发人员快速开发和部署他们的应用,并提供了全面的技术支持和文档资料,帮助用户充分发挥STM32微控制器的性能和功能优势。

  •  业界首款免费的功能安全设计套件,可降低基于STM32的安全关键应用的设计复杂性和IEC 61508安全认证成本

  •  意法半导体原创安全文档和经过第三方认证的X-CUBE-STL软件自检库(STL),提供在STM32上设计并认证达到IEC 61508安全完整性等级(SIL3)的系统所需的全部功能

  •  适用于STM32F0微控制器的初版套件将在2018/2019期间扩充到STM32的其它产品系列

意法半导体针对其已取得巨大成功的STM32*微控制器发布了新的开发软件套件,助力科技公司以更快捷、更经济的方式设计更安全的应用。

工业控制、机器人、传感器、医疗或运输设备必须取得业界认可的安全标准IEC 61508的安全完整性等级(SIL)2级或3级证书。针对这些领域基于STM32的设备设计人员,意法半导体发布了一款能够简化系统开发和认证的STM32 SIL 功能性安全设计套件。

意法半导体微控制器产品市场总监Daniel Colonna表示:“为了帮助客户将经过安全认证的新产品快速、高效地推向市场,我们正在开发这种高附加值的意法半导体原创的多功能软件套件,其中包括经过认证的免费软件,这是业界首创。此外,通过在STM32微控制器产品组合中提供SIL功能安全设计包,意法半导体将为客户提供更高的设计灵活度,帮助他们优化物料成本。”

SIL功能安全设计包的组件包括技术文档和通过IEC 61508 SIL3认证的X-CUBE-STL软件自检库。SIL功能安全设计套件率先配备于STM32F0系列,之后意法半导体将在2018至2019年间陆续推出支持STM32全系产品的SIL功能安全设计包。目前STM32产品家族有800余款产品,为开发人员在价格优化、性能和功能集成度等方面提供独一无二的灵活性。

世界领先的国际标准功能性安全认证机构TÜVRheinland按照功能安全标准IEC 61508:2010给予X-CUBE-STL-F0软件正面评价,该证书的详细信息不久后将发布在www.fs-products.com网站上。

瑞士传感器制造商Contrinex是首个使用意法半导体功能性安全设计套件来认证采用STM32F0微控制器的安全产品的企业。Contrinex嵌入式软件开发项目负责人Nicolas Jouanne表示:“意法半导体微控制器的稳健性久经市场考验,再加上强大的SIL功能安全设计套件,已成为我们开发安全产品的放心之选。”

STM32F0微控制器的功能性安全设计套件可从www.st.com免费下载,用户须与意法半导体签署保密协议(NDA)。适用于STM32其它产品系列的软件包将在2018年和2019年陆续推出。

编者按

意法半导体的STM32 SIL功能性安全设计包含有开发STM32的符合IEC 61508功能安全要求的嵌入式系统所需的完整版技术文档。本文档包含详细介绍所有适用安全要求或使用条件的安全手册,以及说明开发人员根据IEC 61508验证其产品是否达到SIL 2或SIL 3安全等级的实现指南。此外,本文档还含有故障模式影响分析(Failure-Modes Effects Analysis ,简称FMEA )和故障模式影响和诊断分析(Failure-Mode Effects and Diagnostics Analysis ,简称FMEDA)。其中,FMEA 包含详细的微控制器故障模式和相关解决措施;而FMEDA则给出了在微控制器和基本功能层面上计算出的IEC 61508故障率报告静态截图。

X-CUBE-STL软件自检库是一款软件诊断套件,用于检测CPU、SRAM、闪存等STM32安全关键核心元件的随机性硬件故障。诊断覆盖率验证采用意法半导体独有的最先进的故障注入方法(fault injection methodology)。X-CUBE-STL整合在开发者熟悉且经过市场检验的STM32Cube工作流程内,与具体应用无关,从而允许与任何用户应用配合使用,以及提供与编译器中立的对象代码形式。

根据IEC 61508:2010功能安全标准,TÜVRheinland给予X-CUBE-STL-F0正面评测,证明其满足软件系统功能SC3的要求。此外,该机构还验证了诊断覆盖率(DC),使X-CUBE-STL-F0适合集成到SIL2HFT = 0和SIL3 HFT = 1的应用。

围观 461

一、stm32的中断和异常

Cortex拥有强大的异常响应系统,它能够打断当前代码执行流程事件分为异常和中断,它们用一个表管理起来,编号为0~15为内核异常,16以上的为外部中断,这个表就是中断向量表。而stm32对这个表重新进行了编排,把编号从-3~6定义为系统异常,编号为负的内核异常不能设置优先级,从编号为7为外部中断,这些中断的优先级可自行进行设置。我们一般在starup_stm32f10x_hd.s中查找中断向量,而且在编写中断函数时也要在这个文件里查找中断服务函数的函数名。如下图所示:

stm32之中断配置

二、NVIC中断控制器

1、stm32提供了强大的中断控制器NVIC,NVIC属于Cortex内核器件,不可屏蔽中断(NMI)和外部中断都由它来管理,而SYSTICK不由它管理。

在misc.h文件中我们对NVIC进行了结构体定义,我们找到NVIC_InitTypeDef结构体就可进行定义,结构体中包含四个成员,分别是:

  NVIC_IRQChannel :需要配置的中断向量,比如EXTI0_IRQn,不同的中断向量我们在stm32f10x.h这个文件中可以找到。

  NVIC_IRQChannelPreemptionPriority :配置相应中断向量抢占优先级。

  NVIC_IRQChannelSubPriority :配置相应中断响应优先级。

  NVIC_IRQChannelCmd :使能或关闭响应中断向量中断。

2、对于中端配置主要的内容是配置中断优先级,stm32有两种中断优先级,我们该怎么配置呢?

中断向量有两个属性,抢占式优先级和响应式优先级,编号越小,优先级越高。当两个中断抢占式优先级相同,则响应式中断优先级高的先执行。

3、NVIC中断优先级组

NVIC只可以配置16种中断优先级,也就是说抢占式优先级和响应式优先级由四位数字来决定,总共可以有5种配置方式,在misc.h文件中我们可以看:

stm32之中断配置

stm32的所有GPIO口都可以配置为EXTI外部中断模式,来捕捉信号,可以上升沿检测,下降沿,上升沿下降沿检测。PA0~PG0连接到EXTI0,PA1~PG1连接到EXTI1,PA2~PG2连接到EXTI2等

三、中断程序编写

我们需要自己建一个.c和.h文件来写中断配置这一块的代码。配置NVIC和中断函数如下所示:

static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;            //NVIC_InitTypeDef这个结构体我们在misc.h文件中可以找到
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);        //配置为第2种中端配置方式,即1bits配置抢占式,3bits配置响应式,这个函数在misc.c文件中,组别在misc.h文件中
  /* 配置中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;       //外部中断0用这种表示方法,中断0~4表示方法都类似,中断5~9表示方式统一为EXTI9_5IRQn,中断10~15统一为EXTI15_10IRQn
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式优先级0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;     //响应式优先级0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //使能中断
  NVIC_Init(&NVIC_InitStructure);
}
void EXTI_PA0_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;          //这个结构体在stm32f10x_exti.h中有定义
    /* config the extiline clock and AFIO clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);                                 
    /* config the NVIC */
    NVIC_Configuration();
    /* EXTI line gpio config*/ 
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;      
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          // 上拉输入
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* EXTI line mode config */
      GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
      EXTI_InitStructure.EXTI_Line = EXTI_Line0;          //外部中断0,其他的以此类推
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //配置为中断模式
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
} 

中断配置完了以后就要真正写代码了,我们的中断处理函数都写在stm32f10x_it.c文件中,示例代码如下:

void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) != RESET) //确保是否产生了EXTI Line中断
    {
        // LED1 取反     
        LED1_TOGGLE;
        EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位
    } 
}

本文转载自: xtusir

围观 507

一、DMA功能简介

首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量。在硬件系统中,主要由CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常要在内存和外设之间,外设和外设之间转移。例如:CPU需要处理从外设采集回来的数据,CPU需要先将数据从ADC外设的寄存器读取到内存中(变量)去,然后进行运算处理,这是一般的解决方法。CPU的资源是非常宝贵的,我们可以设法把转移的工作交给其他部件来完成,CPU把更多的资源用于数据运算和中断响应上,如此DMA便登场了。DMA正是为CPU分担数据转移工作,因为DMA的存在,CPU才被解放出来,它可以在数据转移的同时进行数据运算,相应中断,大大提高了效率。

二、DMA的主要特性
stm32之串口通信DMA传输完成中断

三、DMA中断特性

stm32之串口通信DMA传输完成中断

四、DMA之串口通信

我们实现一个简单的功能,在DMA中处理串口通信,把数据转移的工作交给DMA,DMA把数据从内存(数组)到外设(串口)的转移,在main函数中不断进行闪灯操作,这样我们可以看到DMA在工作的时候CPU也在工作。非常有必要复习一下DMA的对应关系,我们知道stm32总共有2个DMA控制器(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自一个或多个外设对存储器访问的请求,还有一个仲裁器来协调DMA请求的优先级(优先级分:很高、高、中等、低),这可不是随便对应的。
stm32之串口通信DMA传输完成中断
1、LED初始化程序如下:
stm32之串口通信DMA传输完成中断
这个地方地方没什么要注意的,唯一要注意的就是输入输出模式,我们按需求这样配就好了。

2、串口初始化
stm32之串口通信DMA传输完成中断

3、DMA初始化
stm32之串口通信DMA传输完成中断
在这里我们要注意以下几点:

(1)DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;这里对应USART数据寄存器地址,这个地址我们是这样定义的:#define USART3_DR_Base 0x40004804,这个值是怎么算出来的呢?我们可以查看stm32存储器映射表:
stm32之串口通信DMA传输完成中断
USART3的起始地址是0x40004800,我们查看stm32串口数据寄存器偏移地址为0x04
stm32之串口通信DMA传输完成中断
因此我们可以计算到USART3数据寄存器地址为0x40004804

(2)我们数据传输方向内存(变量)到外设(串口),所以DMA方向为内存到外设

(3)DMA传输模式有两种:DMA_Mode_Normal(普通模式),DMA只传输一次;DMA_Mode_Circular(循环模式),DMA循环传输,比如在AD采集时要配置成循环模式。

4、主函数
stm32之串口通信DMA传输完成中断
这个函数很简单,我们很容易就可以实现,达到效果,这里就不贴图片了。

五、串口通信DMA传输完成中断

我们知道DMA可以在传输过半,传输完成,传输错误时产生中断。我们实现的功能是,DMA工作在普通模式下即只传输一次,LED灯初始化是关闭的,DMA传输完成后产生一个中断,在中断中我们做点灯操作。这个程序调了一天才调了出来,并不是因为它很难,而是有一些要注意的地方没有注意到,从而到时耽误了好长时间才调出来。不过有错误就会有进步嘛。

我先贴出正确的代码,然后在讨论我犯的错误,由于和上一个程序好多都是一样的,这里我们只贴出不同的地方。

(1)DMA初始化程序:
stm32之串口通信DMA传输完成中断
注意我们在这里打开了DMA传输完成中断。

(2)NVIC初始化
stm32之串口通信DMA传输完成中断
(3)中断处理程序

我们在stm32f10x_it.c中编写我们的中断处理程序:
stm32之串口通信DMA传输完成中断
我们也可以这样写中断处理程序:
stm32之串口通信DMA传输完成中断
这两种写法都行,我们在库开发文档可以查看。都代表DMA的通道2传输完成中断。  

(4)主函数
stm32之串口通信DMA传输完成中断
这样我们实验便可以看到,LED灯初始化是关闭的,当串口发送完40000字节的‘A’后,LED等亮。

(5)补充

原意是测试DMA发送完成中断指的是每次指定字节发送完成后便产生一个中断还是最终都传输完成触发一次中断,刚开始中断处理函数写的程序如下:
stm32之串口通信DMA传输完成中断
通过测试,我发现LED灯并没有像试想的那样每次发送完成后便触发一次中断,然后灯会间隔闪烁,而实际是第一次传输完成后灯点亮,之后就一直保持亮的状态。刚开始我还以为DMA只会触发第一次中断,后来仔细分析后才发现了问题。正确的代码应该如下。
stm32之串口通信DMA传输完成中断
在这里n是一个局部变量,如果不定义成静态变量,每次出中断时后n所占的内存(栈)便会释放,这样再次进入后n还是会初始化为0.与我们要达到的效果不符。因此,在这里我们把它指定为静态变量,那么内存就不会释放,它会保持上一次的的值,修改之后达到了效果,每次传输完成3000个字节后灯的状态就会改变一次。  

在这里我们整理一下变量:

全局动态变量:作用范围为整个工程,不释放内存,会保持上一次的值。

全局静态变量:作用范围为当前文件,不释放内存,会保持上一次的值。

局部动态变量:作用范围为当前函数,每次函数执行结束释放内存,不会保持上一次的值。

局部静态变量:作用范围为当前函数,不释放内存,会保持上一次的值。

本文转载自: xtusir

围观 817

一、CMSIS标准

ST公司的stm32采用的是cortex-m3内核,内核是整个微处理器的CPU。该内核是ARM公司设计的一种处理器体系架构。内核与外设的关系就像PC上的CPU与硬盘、主板、内存等的关系一样。

基于cortex系列的处理器内核都是一样的,区别在于除内核以外的外设的差异,由于这些差异,导致不同处理器移植起来比较麻烦,所以ARM与芯片厂商建立了CMSIS标准,CMSIS架构如下所示:

stm32之CMSIS标准、库目录、GPIO

CMSIS标准中最主要的是CMSIS核心层;内核函数层中的内核函数寄存器以及地址主要由ARM公司提供;设备外设访问层核外外设和中断寄存器地址由芯片生产厂商定义。

二、库目录和文件简介

1、core_cm3.c文件

在CoreSupport文件夹中有core_cm3.c和头文件core_cm3.h,它的作用是采用Cortex-M3内核设计的SoC芯片厂商设计的芯片提供了一个进入CM3内核的接口。core_cm3.c中还有一些与编译器(MDK、IAR等)有关的代码。较重要的是core_cm3.c中包含stdio.h头文件,这是一个ANSI C文件,主要作用是提供一些新类型的定义。

2、system_stm32f10x.c文件

DeviceSupport文件夹下是启动文件、外设寄存器定义、中断向量定义层的一些文件,这些文件由ST公司提供。system_stm32f10x.c的主要作用是设置系统时钟和总线时钟。

3、stm32f10x.h文件

这个文件非常重要,是非常底层的文件,包含了寄存器地址和结构体类型的定义,在使用到stm32固件库的地方都要包含它。

3、stm32f10x_it.c和stm32f10x_conf.h文件

stm32f10x_it.c这个文件主要是编写中断程序的,stm32f10x_conf.h被包含在stm32f10x.h文件中主要是配置外设的头文件,我们需要什么在这里打开。

4、startup_stm32f10x_hd.s文件

在这个文件中有一段启动文件,启动文件中先初始化系统时钟,然后才执行主函数,因此我们要注意配置时钟在这个文件里配置。

三、引脚端口的一些概念

1、一些寄存器

1)配置寄存器:选择是输入还是输出。

2)数据寄存器:保存了GPIO的输入电平或者将要输出的电平。

3)为空值寄存器:设置引脚电平为1或0,控制输出电平。

4)锁定寄存器:设置锁定引脚后,就不能修改其配置。

2、管脚时钟

stm32拥有丰富的时钟系统,我们在配置管教时钟时,如果该管脚要用到其复用功能,我们必须也要初始化复用功能时钟。例如要使用PC1口的AD功能:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

3、GPIO8种工作模式

1)四种输入模式:上拉输入模式、下拉输入模式、浮空输入模式、模拟输入模式

上拉输入模式(GPIO_Mode_IPU):与VDD相连的为上拉电阻,若引脚配置为上拉输入模式,默认情况下该引脚是高电平。

下拉输入模式(GPIO_Mode_IPD):与VSS相连的为下拉电阻,若引脚配置为下拉输入模式,默认情况下该引脚是低电平。

浮空输入模式(GPIO_Mode_IN_FLOATING):没有上拉电阻也没有下拉电阻,一般这种模式用于标准的通信协议:IIC、USART等的接收端。

模拟输入模式(GPIO_Mode_AIN):使用ADC外设时,接口必须设置为,模拟输入模式。

2)四种输出模式:推挽输出模式、开漏输出模式、复用推挽输出模式、复用开漏输出模式

推挽输出模式(GPIO_Mode_Out_PP):一般用于0和3.3伏的场合。

开漏输出模式(GPIO_Mode_Out_OD):一般用于电平不平衡的场合。

任何一种开漏模式都要接上拉电阻。

复用推挽输出模式(GPIO_Mode_AF_PP)

复用开漏输出模式(GPIO_Mode_AF_OD)

4、中断

stm32有100个引脚,GPIO口总共80个,分为GPIOA~GPIOE 5组,每组16个。每个IO口都可以作为中断源的输入,可以配置为上升沿中断,下降沿中断,上升沿下降沿中断.

本文转载自:博客园 - xtusir

围观 464

一、基础概念

什么是IAP?IAP即在应用中编程(In-Application Programming IAP),简单的说就像是一个用户自定义的升级程序。实际上,STM32单片机的程序烧写有多种方法,可以用JTAG,也可用串口通过ISP软件烧写新程序。

JTAG的方式需要专用的烧写工具,在产品布置到现场后,更新产品程序比较麻烦,而通过串口的ISP软件升级方法可以直接使用常见的串口线升级程序,十分方便,这种方法用的是ISP。ISP可以说是单片机默认的bootloader,

正常情况下,单片机系统启动后,会直接从用户程序执行,而升级程序时,单片机会进入bootloader,在ISP中一直运行。ISP虽然方便了升级,但是还是没法解决用户自定义和远程升级的问题。对于用户来说,有时候可能需要在单片机

flash不同地址烧写多个应用程序,用于根据不同条件启动不同应用程序;有时候,产品分布到全国各地,去所有现场升级程序明显不理智,解决方法是将升级程序放到服务器上,发送远程升级指令,设备进入IAP升级程序,从远程

获取升级应用程序,实现在线升级。

二、IAP实现

1.硬件

STM32单片机的启动方式有三种,

关于STM32单片机的IAP实现

单片机根据boot0和boot1的引脚来确定启动方式。主闪存存储器即为用户程序空间,IAP启动将会从这里开始,系统存储器是ISP启动,内置SRAM不讨论。正常情况下,boot0管脚接入低电平,单片机从应用程序开始执行;当使用ISP升级时,boot0为1,boot1为0,系统进入ISP程序,等待串口升级,升级完成后,需要断电,改变boot电平,重新启动,让单片机从应用程序执行。(所以ISP升级时,还需要关注有关boot脚的电平开关问题。)

IAP升级不需要改变任何管脚电平,因为它实际上就是一个应用程序,只是让单片机启动时先执行它,执行完后,跳转到真正的应用程序执行。

注意:单片机第一次烧写时,是需要通过JTAG或ISP烧写IAP的,如果打算用ISP,那最好留一个boot脚的硬件拨码开关用于首次ISP升级hex文件。

2.软件

弄清楚硬件之后,就知道什么样的硬件boot对应什么样的启动方式。加入IAP之后,系统启动时会先执行IAP程序用于判断是否达到升级条件和执行什么样的升级配置,相应的逻辑类似于下图:

关于STM32单片机的IAP实现

用户可以根据自己的需求来设计IAP程序,详细设计可以参考ST官方资料:

《使用STM32F10xxx的USART 实现在应用中编程》,而且官方也给出了例程,资料比较全面,实现起来也很简单。

最后,提醒注意一点的是,在IAP后面的应用程序都要在系统启动时重新定义中断向量表。

转自:维克多的梦想

围观 462

STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的DAC。DAC 可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。DAC工作在 12 位模式时,数据可以设置成左对齐或右对齐。DAC 模块有 2 个输出通道,每个通道都有单独的转换器。在双DAC 模式下,2 个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2 个通道的输出。DAC 可以通过引脚输入参考电压 VREF+以获得更精确的转换结果。

STM32 的 DAC 模块主要特点有:

① 2 个 DAC 转换器:每个转换器对应 1 个输出通道

② 8 位或者 12 位单调输出

③ 12 位模式下数据左对齐或者右对齐

④ 同步更新功能

⑤ 噪声波形生成

⑥ 三角波形生成

⑦ 双 DAC 通道同时或者分别转换

⑧ 每个通道都有 DMA 功能

使用库函数的方法来设置 DAC 模块的通道 1 来输出模拟电压,其详细设置步骤如下:

1)开启 PA 口时钟,设置 PA4 为模拟输入。

STM32F103ZET6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设置 PA4 为模拟输入。DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但使能 DACx 通道之后,相应的 GPIO 引脚(PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。

使能 GPIOA 时钟:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能 PORTA 时钟

设置 PA1 为模拟输入只需要设置初始化参数即可:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入

2)使能 DAC1 时钟。

同其他外设一样,要想使用,必须先开启相应的时钟。 STM32 的 DAC 模块时钟是由 APB1提供的,所以我们调用函数 RCC_APB1PeriphClockCmd()设置 DAC 模块的时钟使能。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能 DAC 通道时钟

3)初始化 DAC,设置 DAC 的工作模式。

该部分设置全部通过 DAC_CR 设置实现,包括:DAC 通道 1 使能、DAC 通道 1 输出缓存关闭、不使用触发、不使用波形发生器等设置。这里 DMA 初始化是通过函数 DAC_Init 完成的:

void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)

参数设置结构体类型 DAC_InitTypeDef 的定义:

typedef struct

{

uint32_t DAC_Trigger; //设置是否使用触发功能

uint32_t DAC_WaveGeneration; //设置是否使用波形发生

uint32_t DAC_LFSRUnmask_TriangleAmplitude; //设置屏蔽/幅值选择器,这个变量只在使用波形发生器的时候才有用

uint32_t DAC_OutputBuffer; //设置输出缓存控制位

}DAC_InitTypeDef;

实例代码:

DAC_InitTypeDef DAC_InitType;

DAC_InitType.DAC_Trigger = DAC_Trigger_None; //不使用触发功能 TEN1=0

DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生

DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;

DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ; //DAC1 输出缓存关闭

DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化 DAC 通道 1

4)使能 DAC 转换通道

初始化 DAC 之后,理所当然要使能 DAC 转换通道,库函数方法是:

DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC1

5)设置 DAC 的输出值。

通过前面 4 个步骤的设置,DAC 就可以开始工作了,我们使用 12 位右对齐数据格式,所以我们通过设置 DHR12R1,就可以在 DAC 输出引脚(PA4)得到不同的电压值了。库函数的函数是:

DAC_SetChannel1Data(DAC_Align_12b_R, 0);

第一个参数设置对齐方式,可以为 12 位右对齐 DAC_Align_12b_R,12 位左对齐DAC_Align_12b_L 以及 8 位右对齐 DAC_Align_8b_R 方式。第二个参数就是 DAC 的输入值了,这个很好理解,初始化设置为 0。

这里,还可以读出 DAC 的数值,函数是:

DAC_GetDataOutputValue(DAC_Channel_1);

以下为代码:

//DAC通道1输出初始化
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 输出高

DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1

DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
}
//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
float temp=vol;
temp/=1000;
temp=temp*4096/3.3;
DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}
在使用的过程中,只需要调用 DAC_SetChannel1Data(DAC_Align_12b_R,temp);该函数就可以随意设定需要输出的电压值。

本文转自:http://blog.chinaunix.net/uid-24219701-id-4101802.html

围观 852

本文将就使用FSMC可能遇到的问题进行说明。希望能对大家的学习有所帮助。

一、端口配置

1、 由于FSMC写NOR时序与8080接口的时序十分相识,因此我们采用模拟8080时序,

STM32之FSMC的液晶使用

2、 STM32的引脚图如图所示。
STM32之FSMC的液晶使用

3、根据上图我们可以得出,FSMC的数据端口D[15:0]如下
STM32之FSMC的液晶使用

4、我们使用的是 FSMC 的信号线 NE1 作为控制 8080 的 CSX 片选信号,所以我们把本成配置为 FSMC_Bank1_NORSRAM1 (NE1 片选BANK1)。由上图得FSMC-NE1 ==PD7 ---------LCD-CS
STM32之FSMC的液晶使用

5、数据地址的选择,

本成员用于设置 FSMC 接口的数据宽度,可被设置为 8Bit 或 16bit。对于16 位宽度的外部存储器。在 STM32 地址映射到 FSMC 接口的结构中,HADDR信号线是需要转换到外部存储器的内部 AHB 地址线,是字节地址。

若存储器的数据线宽为 8Bit,FSMC 的 26 条地址信号线 FSMC_A[25:0]直接可以引入到与 AHB 相连HADDR[25:0],26 条字节地址信号线最大寻址空间为 64MB。见图 0-9。

STM32之FSMC的液晶使用

若存储器的数据线宽 16Bit,则存储器的地址信号线是半字地址(16Bit) 。为了使 HADDR 的字节地址信号线与存储器匹配,FSMC 的 25 条地址信号线FSMC_A[24:0]与 HADDR[25:1]相连,由于变成了半字地址(16Bit),仅需要 25条半字字地址信号线就达到最大寻址空间 64MB。正因地址线的不对称相连,16bit 数据线宽下,实际的访问地址为右移一位之后的地址。

如下,我的地址选择FSMC_A16, 只需在命令地址上左移(16+1)位。

STM32之FSMC的液晶使用

6、FSMC寄存器的配置
STM32之FSMC的液晶使用

7、如果我们需要改动端口,只需注意以下几个要点即可

(1)我们需要改动BANK1_SRAM[X],,如我改成BANK1_EN4,需改动

STM32之FSMC的液晶使用

STM32之FSMC的液晶使用

STM32之FSMC的液晶使用

因为EN4的地址是0X6C000000,
STM32之FSMC的液晶使用

(2)如需改动命令地址,FSMC_A[25:0],如我选择A16
STM32之FSMC的液晶使用

只需将命令地址改为0x6c000000+(16+1)
STM32之FSMC的液晶使用

来源:destiny的专栏

围观 1498

SPI (Serial Peripheral interface),顾名思义就是串行外围设备接口。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间

SPI内部简明结构图

stm32之SPI通信协议

关于SPI传输过程(下面由灵魂画家作图)

stm32之SPI通信协议

SPI包含四根线:

1、SS(Slave Select):片选信号线,当有多个SPI设备与MCU相连时,每个设备的这个片选信号线是与MCU单独的引脚相连的,而其他SCK,MOSI,MISO线则为多个设备并联到相同的SPI总线上,当SS信号线为低电平时,片选有效,开始SPI通信

2、SCK(Serial Clock):时钟信号线,由主通信设备产生,不同的设备支持的时钟频率不一样。

3、MOSI(Master Output,Slave Input):主设备输出、从设备输入引脚

4、MISO(Master Input,Slave Output):主设备输入、从设备输出引脚

关于SPI模式

根据SPI时钟极性(CPOL)和时钟相位(CPHA)配置的不同可分为4种模式

时钟极性是指SPI通信设备处于空闲状态时(或SPI通信开始时,即SS为低电平时),SCK的电平信号

CPOL=0时,SCK空闲状态为低电平,CPOL=1时则相反。

时钟相位是指数据采样的时刻,当CPHA=0时,MOSI或MISO数据线会在时钟线第一个边沿开始采样(奇数边沿)

当CPHA=1时,MOSI或MISO数据线会在时钟线第二个边沿开始采样(偶数边沿)

stm32之SPI通信协议

步骤分析:SS片选信号线拉低-->根据CPOL和CPHA进行数据采样

stm32 SPI接口框图

stm32之SPI通信协议

stm32 SPI配置过程

1、配置相关引脚的复用功能,使能SPIx时钟

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

2、初始化SPIx,设置SPIx工作模式

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

3、使能SPIx

void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

4、SPI传输数据

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

5、查看SPI传输状态

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

转自:古墓派掌门 - 博客园

围观 315

一、位带操作

在学习51单片机的时候就使用过位操作,通过关键字sbit对单片机IO口进行位定义。但是stm32没有这样的关键字,而是通过访问位带别名区来实现,即将每个比特位膨胀成一个32位字,通过位带别名区指针指向位带区内容。

支持位带操作的两个内存区的范围是:

0x2000_0000‐0x200F_FFFF(SRAM 区中的最低 1MB)
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)

位带别名区地址=(A&0xF0000000)+0x2000000+(A&0xFFFFF)<<5+(n≤2)

其中A为位带区地址,n为该字节的第几位。

这里再不嫌啰嗦地举一个例子:

1. 在地址 0x20000000 处写入 0x3355AACC
2. 读取地址0x22000008。本次读访问将读取 0x20000000,并提取比特 2,值为 1。
3. 往地址 0x22000008 处写 0。本次操作将被映射成对地址 0x20000000 的“读-改-写”操作(原子的),把比特2 清 0。
4. 现在再读取 0x20000000,将返回 0x3355AAC8(bit[2]已清零)。

注:如果用到位带操作,可以把各个引脚进行位带宏定义,封装在一个头文件里,方便使用引脚。

二、中断

中断其实就是当CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中段子程序)。下面是中断的示意图。

stm32之内部功能

部分中断可屏蔽,部分中断不可屏蔽,每个中断通道都具备自己的中断优先级控制字,分别控制抢占优先级和响应优先级。只有当抢占优先级相同时,响应优先级高低决定哪个中断被处理(响应式优先级的高低没法中断正在执行的中断程序)。

stm32中的NVIC(嵌套向量中断控制器)属于内核的一个外设,控制着芯片的中断相关功能。

注:中断和事件的区别:

可以这样简单的认为,事件机制提供了一个完全有硬件自动完成的触发到产生结果的通道,不要软件的参与,降低了CPU的负荷,节省了中断资源,提高了响应速度(硬件总快于软件),是利用硬件来提升CPU芯片处理事件能力的一个有效方法。

三、printf重定向

我们知道C语言中printf函数默认输出设备是显示器,如果要实现在串口或者LCD上显示,必须重定义标准库函数里调用与输出设备相关的函数。一般是在fputc函数里把输出对象改为指向串口或者LCD,这一过程叫做重定向。

四、随机数发生器RNG

STM32F4芯片内部含有一个硬件随机数发生器(RNG),RNG处理器是一个以连续模拟噪声为基础的随机数发生器,提供了一个32位的随机数。使能后,需要检查标志位,判断其是否稳定,稳定后才能使用。RNG结构图如下图所示:

stm32之内部功能

五、AD/DA

STM32的ADC模块,请允许我用如此通俗的语言:普通话 来介绍STM32ADC模块的特色

1、1MHz转换速率、12位转换结果(12位、记住这个12位哈、因为2^12=4096 ,也请记住4096哈)

STM32F103系列:

在56MHz时转换时间为:1μs
在72MHz时转换时间为:1.17μs

2、转换范围:0~3.3V (3.3v---->当你需要将采集的数据用电压来显示的话:设你采集的数据为:x[0~4095],此时的计算公式就为:(x / 4096) * 3.3))

3、ADC供电要求:2.4V~3.6 V(可千万别接到 5V 的石榴裙子底下呀)

4、ADC输入范围:VREF-≤ VIN ≤VREF+ (VREF+和VREF-只有LQFP100封装才有)

5、双重模式(带2个ADC的设备): 8种转换模式

6、最多有18个通道:16个外部通道,2个内部通道:连接到温度传感器和内部参考电压(VREFINT = 1.2V)。通道可以分为规则通道和注入通道,其中规则通道组最多有16路,是一种规规矩矩的通道,具有DMA功能,而注入通道组最多有4路,转换过程中可以中断,还可以在规则通道转换过程中插队。

其转换步骤如下:

• 使能端口时钟和ADC时钟
• 设置ADC通道控制器CCR(ADC模式(独立、双重、三重)、输入时钟分频等)
• 初始化ADC(分辨率、转换模式(单次、连续)、数据对齐方式等)
• 开启ADC
• 读取ADC转换值

测交流电信号要把交流电分压到5V 以内,再把负半周提升到零点以上,用运放做一个加法器(有专用交流电检测用的高精度运放,好像是MCP的),把零点抬高到2.5V,这样最低点也大于零,最高点不超过5V ,再用单片机在交流电一周期内采40个点,存入内存,计算出各离散值的均方根就是交流电的有效值。

或者把交流信号经(电压跟随器 + 全波整流 ),将负半周期信号反转到正半轴,得到半波交流信号,再用ADC进行测量。

我们来看看STM32之DAC的Resume(简历简介):

stm32之内部功能

● 2个DAC转换器:每个转换器对应1个输出通道

● 8位或者12位单调输出

● 12位模式下数据左对齐或者右对齐

● 同步更新功能

● 噪声波形生成

● 三角波形生成

● 双DAC通道同时或者分别转换

● 每个通道都有DMA功能

● 外部触发转换

● 输入参考电压VREF+

注:PWM+RC滤波可以模拟DAC的输出方式。

  在对DAC的输出频率要求不是太高的情况下,我们一般可以采用PWM+二阶RC滤波来模拟DAC,进行输出。PWM的占

空比来模拟幅值,二阶RC低通滤波电路用来截止谐波(一般只考虑基波即可),通过直流,具体详情如下:

在8位分辨条件下,我们一般要求1次谐波对输出电压的影响不要超过1个位的精度,也就是3.3/256=0.01289V。假设VH为3.3V,VL为0V,那么一次谐波的最大值是2*3.3/π=2.1V,这就要求我们的RC滤波电路提供至少-20lg(2.1/0.01289)=-44dB的衰减。STM32的定时器最快的计数频率是168Mhz,部分定时器只有84MHz,以84M为例,8为分辨率的时候,PWM频率为84M/256=328.125Khz。如果是1阶RC滤波,则要求截止频率为2.07Khz,如果为2阶RC滤波,则要求截止频率为26.14Khz。

1、PWM频率为328.125Khz,那么一次谐波频率就是328.125Khz;

2、1阶RC滤波,幅频特性为:-10lg[1+(f/fp)^2];fp为截止频率。

所以对一阶滤波来说,要达到-44dB的衰减,必须-10lg[1+(f/fp)^2]=-44; 得到f/fp=158.486,即fp=328.125/158.486=2.07Khz。

3、2阶RC滤波,幅频特性为:-20lg[1+(f/fp)^2];fp为截止频率。

所以对二阶滤波来说,要达到-44dB的衰减,必须-20lg[1+(f/fp)^2]=-44; 得到f/fp=12.549,即fp=328.125/12.549=26.14Khz。

得到截止频率以后,我们可以紧接着求出R、C的值。如下图所示,R35*C68=R36*C69,fp=1/2πRC。

stm32之内部功能

六、DMA 

DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM 与I/O设备开辟一条直接传送数据的通路,能使CPU 的效率大为提高。

STM32F4中 有两个DMA,每个DMA控制器对应8个数据流,每个数据流又对应8个通道,其映射图如下图所示。DMA挂载的时钟为AHB总线,其时钟为72Mhz,所以可以实现高速数据搬运。

stm32之内部功能

DMA的结构框图如下图所示,可以看出DMA各数据流需要仲裁优先级,且拥有FIFO先进先出缓存区(解决目标地址和原地址数据宽度不一致的情况)。
stm32之内部功能

七、高性能计算能力

如下图所示,stm32F4自带DSP处理器,我们可以采用DSP库函数进行浮点运算等计算问题。

stm32之内部功能

我们平常所使用的CPU为定点CPU,意思是进行整点数值运算的CPU。当遇到形如1.1+1.1的浮点数运算时,定点CPU就遇到大难题了。对于32位单片机,利用Q化处理能发挥他本身的性能,但是精度和速度仍然不会提高很多。

现在设计出了一个新的CPU,叫做FPU,这个芯片专门处理浮点数的运算,这样处理器就将整点数和浮点数分开来处理,整点数交由定点CPU处理而浮点数交由FPU处理。我们见到过TI的DSP,还有STM32F4系列的带有DSP功能的微控制器。前者笔者没有用过,不作评论,而后者如果需要用到FPU的浮点运算功能,必须要进行一些必要的设置。

八、加密

采用加密处理器CRYP,下面是CRYP的结构框图。

stm32之内部功能

加密算法有AES加解密算法、DES/TDES加解密算法等

九、ART加速

由于生产工艺的限制,当CPU主频显著提高时,Flash的存取速度却只能处于一个较低的水平。

STM32F4有存储器加速器(ART),可以使 CPU 频率高达 168 MHz 时在闪存中以 0 个等待周期执行程序。其秘密在于,STM32内部的Flash我记得是128bit的。这样每次读取时ART会把后面3条指令放到队列里。而Flash等待为5WS的话,每执行4条指令则必须停一次,再继续执行后4条指令。反正是性能跟同频的X86差不多顶个70%的样子(指Dothan处理器,纯逻辑运算)。超频我最高测过250MHz,还算比较稳定,结果没出错。再高结果就不对了。

转自: steed灬

围观 441

说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置、芯片ID、自举程序等等。当然, FLASH还可以用来装数据。

自己收集了一些资料,现将这些资料总结了一下,不想看的可以直接调到后面看怎么操作就可以了。

FLASH分类

根据用途,STM32片内的FLASH分成两部分:主存储块、信息块。 主存储块用于存储程序,我们写的程序一般存储在这里。 信息块又分成两部分:系统存储器、选项字节。 系统存储器存储用于存放在系统存储器自举模式下的启动程序(BootLoader),当使用ISP方式加载程序时,就是由这个程序执行。这个区域由芯片厂写入BootLoader,然后锁死,用户是无法改变这个区域的。 选项字节存储芯片的配置信息及对主存储块的保护信息。

FLASH的页面

STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。

STM32产品的分类

STM32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。

小容量产品主存储块1-32KB, 每页1KB。系统存储器2KB。
中容量产品主存储块64-128KB, 每页1KB。系统存储器2KB。
大容量产品主存储块256KB以上, 每页2KB。系统存储器2KB。
互联型产品主存储块256KB以上, 每页2KB。系统存储器18KB。

对于具体一个产品属于哪类,可以查数据手册,或根据以下简单的规则进行区分:
STM32F101xx、STM32F102xx 、STM32F103xx产品,根据其主存储块容量,一定是小容量、中容量、大容量产品中的一种,STM32F105xx、STM32F107xx是互联型产品。

互联型产品与其它三类的不同之处就是BootLoader的不同,小中大容量产品的BootLoader只有2KB,只能通过USART1进行ISP,而互联型产品的BootLoader有18KB,能通过USAT1、4、CAN等多种方式进行ISP。小空量产品、中容量产品的BootLoader与大容量产品相同。

关于ISP与IAP

ISP(In System Programming)在系统编程,是指直接在目标电路板上对芯片进行编程,一般需要一个自举程序(BootLoader)来执行。ISP也有叫ICP(In Circuit Programming)、在电路编程、在线编程。 IAP(In Application Programming)在应用中编程,是指最终产品出厂后,由最终用户在使用中对用户程序部分进行编程,实现在线升级。IAP要求将程序分成两部分:引导程序、用户程序。引导程序总是不变的。IAP也有叫在程序中编程。 ISP与IAP的区别在于,ISP一般是对芯片整片重新编程,用的是芯片厂的自举程序。而IAP只是更新程序的一部分,用的是电器厂开发的IAP引导程序。综合来看,ISP受到的限制更多,而IAP由于是自己开发的程序,更换程序的时候更容易操作。

FPEC

FPEC(FLASH Program/Erase controller 闪存编程/擦除控制器),STM32通过FPEC来擦除和编程FLASH。FPEC使用7个寄存器来操作闪存:

FPEC键寄存器(FLASH_KEYR) 写入键值解锁。
选项字节键寄存器(FLASH_OPTKEYR) 写入键值解锁选项字节操作。
闪存控制寄存器(FLASH_CR) 选择并启动闪存操作。
闪存状态寄存器(FLASH_SR) 查询闪存操作状态。
闪存地址寄存器(FLASH_AR) 存储闪存操作地址。
选项字节寄存器(FLASH_OBR) 选项字节中主要数据的映象。
写保护寄存器(FLASH_WRPR) 选项字节中写保护字节的映象。

键值

为了增强安全性,进行某项操作时,须要向某个位置写入特定的数值,来验证是否为安全的操作,这些数值称为键值。STM32的FLASH共有三个键值:

RDPRT键 = 0x000000A5 用于解除读保护
KEY1 = 0x45670123 用于解除闪存锁
KEY2 = 0xCDEF89AB 用于解除闪存锁

闪存锁

在FLASH_CR中,有一个LOCK位,该位为1时,不能写FLASH_CR寄存器,从而也就不能擦除和编程FLASH,这称为闪存锁。

当LOCK位为1时,闪存锁有效,只有向FLASH_KEYR依次写入KEY1、KEY2后,LOCK位才会被硬件清零,从而解除闪存锁。当LOCK位为1时,对FLASH_KEYR的任何错误写操作(第一次不是KEY1,或第二次不是KEY2),都将会导致闪存锁的彻底锁死,一旦闪存锁彻底锁死,在下一次复位前,都无法解锁,只有复位后,闪存锁才恢复为一般锁住状态。

复位后,LOCK位默认为1,闪存锁有效,此时,可以进行解锁。解锁后,可进行FLASH的擦除编程工作。任何时候,都可以通过对LOCK位置1来软件加锁,软件加锁与复位加锁是一样的,都可以解锁。

主存储块的擦除

主存储块可以按页擦除,也可以整片擦除。

页擦除

主存储块的任何一页都可以通过FPEC的页擦除功能擦除。 建议使用以下步骤进行页擦除:

1.检查FLASH_SR寄存器的BSY位。以确认没有其他正在进行的闪存操作。必须等待BSY位为0,才能继续操作。
2.设置FLASH_CR寄存器的PER位为1。选择页擦除操作。
3.设置FLASH_AR寄存器为要擦除页所在地址,选择要擦除的页。FLASH_AR的值在哪一页范围内,就表示要擦除哪一页。
4.设置FLASH_CR寄存器的STRT位为1,启动擦除操作。
5.等待FLASH_SR寄存器的BSY位变为0,表示操作完成。
6.查询FLASH_SR寄存器的EOP位,EOP为1时,表示操作成功。
7.读出被擦除的页并做验证。擦完后所有数据位都为1。

整片擦除

整片擦除功能擦除整个主存储块,信息块不受此操作影响。 建议使用以下步骤进行整片擦除:

1.检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作。
2.设置FLASH_CR寄存器的MER位为1。选择整片擦除操作。
3.设置FLASH_CR寄存器的STRT位为1。启动整片擦除操作。
4.等待FLASH_SR寄存器的BSY位变为0,表示操作完成。
5.查询FLASH_SR寄存器的EOP位,EOP为1时,表示操作成功。
6.读出所有页并做验证。擦完后所有数据位都为1。

主存储块的编程

对主存储块编程每次可以写入16位。当FLASH_CR寄存器的PG位为1时,在一个闪存地址写入一个半字(16位)将启动一次编程;写入任何非半字的数据,FPEC都会产生总线错误。在编程过程中(BSY位为1时),任何读写闪存的操作都会使CPU暂停,直到此次闪存编程结束。

建议使用如下步骤对主存储块进行编:

1.检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的编程操作。
2.设置FLASH_CR寄存器的PG位为1。选择编程操作。
3.在指定的地址写入要编程的半字。直接用指针写。
4.等待FLASH_SR寄存器的BSY位变为0,表示操作完成。
5.查询FLASH_SR寄存器的EOP位,EOP为1时,表示操作成功。
6.读出写入的地址并验证数据。

关于主存储块擦除编程操作的一些疑问

1. 为什么每次都要检查BSY位是否为0?
因为BSY位为1时,不能对任何FPEC寄存器执行写操作,所以必须要等BSY位为0时,才能执行闪存操作。

2. 如果没有擦除就进行编程,会出现什么结果?
STM32在执行编程操作前,会先检查要编程的地址是否被擦除,如果没有,则不进行编程,并置FLASH_SR寄存器的PGERR位为1。唯一例外的是,当要编程的数据为0X0000时,即使未擦除,也会进行编程,因为0X0000即使擦除也可以正确编程。

3. 为什么操作后要读出数据并验证?
STM32在某些特殊情况下(例如FPEC被锁住),可能根本就没有执行所要的操作,仅通过寄存器无法判断操作是否成功。所以,保险起见,操作后都要读出所有数据检查。

4. 等待BSY位为1的时间以多少为合适?
请参考STM32固件库中的数据。

5. FLASH编程手册上说进行闪存操作(擦除或编程)时,必须打开内部的RC振荡器(HSI),是不是一定要用HIS进行闪存的擦除及编程操作?

对于这点,我的理解是,进行闪存操作时,必须要保证HIS没有被关闭,但是操作时的系统仍然可以是HSE时钟。STM32复位后,HIS默认是开的,只要你不为了低功耗去主动关闭它,则用什么时钟都可以进行闪存操作的。我所编的程序也验证了这一点。

来源:stm社区

围观 621

页面

订阅 RSS - STM32