Finder自学stm32笔记之电源时钟

Finder自学stm32笔记之电源时钟
Finder自学stm32笔记之电源时钟

电源

STM32的工作电压(VDD)为2.0~3.6V。通过内置的电压调节器提供所需的1.8V电源。当主电源VDD掉电后,通过VBA T脚为实时时钟(RTC)和备份寄存器提供电源。

由上图可知VDDA.VSSA分别是独立给ADC的电源盒电源地。ADC需要准确的精度因此需要独立的电源供电。

使用电池或其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。以便于RTC、后备区域、一些寄存器工作当然也需要外部振荡器提供时钟,所以也为LSE振荡器供电。

stm32中有上电复位掉电复位电路,可以设置通过设置PVDE位设置PVD阀值,当VDD 电压异常的时候就会复位,可以设置中断。

低功耗模式

三种低功耗模式

睡眠模式(Cortex?-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)

停止模式(所有的时钟都已停止而电压还在供给) :是深睡眠模式基础上结合了外设的时钟控制机制,在停止模式下电压调节器可运行在正常或低功耗模式。此时在1.8V供电区域的的所有时钟都被停止,PLL、HSI和HSE RC振荡器的功能被禁止,SRAM和寄存器内

容被保留下来。在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。

待机模式(1.8V电源关闭):待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。

前面是三者的详细介绍,初一看看不出有什么区别,我当时都看的晕呼呼地,做笔记时候才发现他们真正的不同。现在讲解一下。

睡眠模式只是关掉了CM3的内核,外设都在运行包过内部外部时钟、IO口、中断NVIC 等等。停止模式是进一步的睡眠模式它是关掉了所有的外设时钟,但是仍旧在供电。待机模式是最低功耗的模式,它连时钟供电全部禁止除了备份的寄存器和待机电路维持供电。(有待进一步的深入研究并修正)

Stm32降低功耗的三种方法:

1.低功耗模式

2.降低系统时钟

3.关掉外设

如题降低系统时钟通过对预分频寄存器进行编程,可以降低任意一个系统时钟(SYSCLK、HCLK、PCLK1、PCLK2)的速度。从而降低功耗。

但是我有疑问就是:如何在系统运行的情况下切换系统时钟的时钟源?是否可以随时改变预分频系数?

RCC_SYSCLKConfig 设置系统时钟(SYSCLK)

RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);/* Wait till HSI is used as system clock source */

while(RCC_GetSYSCLKSource() != 0x00)

这个函数只是配置好系统时钟不是随时改变系统时钟的函数。所以有待做实验研究此处

关闭外设:在运行模式下,任何时候都可以通过停止为外设和内存提供时钟(HCLK和PCLKx)来减少功耗。通过设置AHB外设时钟使能寄存器(RCC_AHBENR)、APB2外设时钟使能寄存器

(RCC_APB2ENR)和APB1外设时钟使能寄存器(RCC_APB1ENR)来开关各个外设模块的时钟。

以下介绍怎么进入这三种模式:

进入睡眠模式:

void PWR_EnterSLEEPMode(u32 SysCtrl_Set, u8 PWR_SLEEPEntry)

{

//if (SysCtrl_Set)

// *(vu32 *) SCB_SysCtrl |= SysCtrl_SLEEPONEXIT_Set; // Set SLEEPONEXIT //else

// *(vu32 *) SCB_SysCtrl &= ~SysCtrl_SLEEPONEXIT_Set; // Reset SLEEPONEXIT

*(vu32 *) SCB_SysCtrl &= ~SysCtrl_SLEEPDEEP_Set; // Clear SLEEPDEEP bit

if(PWR_SLEEPEntry == PWR_SLEEPEntry_WFI) // Select SLEEP mode entry __WFI(); // Request Wait For Interrupt else

__WFE(); // Request Wait For Event

}

可惜库函数种没有睡眠模式这个函数。

进入待机模式:

看stm32手册进入停止模式方法附表:

void PWR_EnterSTANDBYMode(void)

{

PWR->CR |= CR_CWUF_Set; // 清除Wake-up 标志

PWR->CR |= CR_PDDS_Set; // 选择进入STANDBY 模式

// 置位SLEEPDEEP位

*(vu32 *) SCB_SysCtrl |= SysCtrl_SLEEPDEEP_Set;

__WFI(); // 等待中断请求

}

库函数就非常简单,直接调用PWR_EnterSTANDBYMode();

进入停止模式

看stm32手册进入停止模式方法附表:

与进入待机模式对比可以发现不同的是停止模式电压调节器还是在继续工作的,待机模式是笔停止模式更近一步的低功耗模式。(程序下一次再做出来)

库函数非常简单直接调用

PWR_EnterSTOPMode(u32 PWR_Regulator, u8 PWR_STOPEntry);

另外还有不得不提的就是上电复位(POR)和掉电复位(PDR):

stm32中有上电复位掉电复位电路,可以设置通过设置P VDE位设置PVD阀值,当VDD电压异常的时候就会复位,可以设置中断。

电源这一块应该记下的寄存器

LPDS:停止模式下电压调节器的工作模式0:开启1:关闭

PDDS:睡眠模式下进入停止模式还是待机模式。0:待机模式1:停止模式。

CWUF:清除唤醒位

CSBF:清除待机位SBF

PVDE:电源监视器是否使能

PLS:选择电源电压监测器的电压阀值

DBP:后备区域的写保护?

EWUF:使能wkup这个IO口0:不能唤醒1:唤醒。在系统复位时软件清0。

SBF:用于查询是否处于待机状态。

WUF:唤醒标志。是否被唤醒标志位。发生唤醒事件或者RTC闹钟事件

备份寄存器

学stm32这么久了一直知道备份寄存器这个东西但是却一直没有过深入研究,只是知道他是是一个在低功耗模式下仍然可以工作的一个寄存器。下面我将好好学习这个寄存器把他搞明白。

备份寄存器:VDD被切断,VBA T为其提供电源,它们不会应为系统复位而复位。备份域复位来复位或(如果侵入检测引脚TAMPER功能被开启时)由侵入引脚事件复位。

BKP中三个位是必须知道。

TPAL:TAMPER高电平会清除备份区域寄存器。

TPE:TAMPER这个引脚作为通用IO口还是作为侵入检测用。

TPIE:检测到侵入事件时是否产生一个中断。

为方便测量,RTC时钟可以经64分频输出到侵入检测引脚TAMPER上。通过设置RTC 校验寄存器(BKP_RTCCR)的CCO位来开启这一功能。

问题是怎么校准?RTC的时钟被输出到TAMPER上。(去网上找线索)。。。。

主要是一些标志位,以及设置中断,清除一些标志位。

时钟

时钟这一块真的不知道看了多少遍,啥也不说了直接上图。没错就是时钟树的图

先来几个容易忽略的小知识点。

1、时钟源被直接或通过PLL间接作为系统时钟时,它将不能被停止。只有当某个时钟源准备就绪之后时钟源切换才会发生。并且那一个准备好就选定那个位系统的时钟源。(这个事真的吗?不行我得亲身试试看,先研究控制和状态寄存器,再做实验)

2、PLL倍频系数。只有在PLL关闭的情况下才可被写入

3、PLL输入时钟源。只能在关闭PLL时才能写入此位。

由此看来时钟切换容易实现。先开好要的时钟源然后等待期准备好在设置SW位来设置系统时钟源。但是倍频怎么在运行的时候切换呢?

想法1:先进入待机或者停止模式(时钟将会被关闭)从停止模式返回的话会默认为HSI 作为系统时钟。之后重新配置时钟源的输入,和PLL的配平系数。

RTCCLK时钟源可以由HSE/128、LSE或LSI时钟提供。除非备份域复位,此选择不能被改变。为什么会这样呢除非备份域和RTC有很大的关系(关系是什么呢?我现在是不懂)

备份域复位的两种方法:

软件复位,备份区域复位可由设置备份域控制寄存器(RCC_BDCR)(见6.3.9节)中的

BDRST位产生。

在VDD和VBAT两者掉电的前提下,VDD或VBAT上电将引发备份区域复位

我有很多疑惑在这里还没有搞清楚。。。哎,,,不能操之过急。。只有慢慢来搞了。。。

但是学习方法已经总结出来就是寄存器操作和库函数一起看。应为库函数的操作都是寄存器里面提到过得,分开二者完全不行。边做笔记懂原理记寄存器懂库函数。

复位

有三种复位:系统复位、电源复位和后备域复位。

系统复位:复位除时钟控制寄存器CSR中的复位标志和备份区域中的寄存器以外的所有

寄存器。

当以下事件中的一件发生时,产生一个系统复位:

1. NRST引脚上的低电平(外部复位)

2. 窗口看门狗计数终止(WWDG复位)

3. 独立看门狗计数终止(IWDG复位)

4. 软件复位(SW复位)

5. 低功耗管理复位

可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源。

电源复位

当以下事件中之一发生时,产生电源复位:电源复位将复位除了备份区域外的所有寄存器

1. 上电/掉电复位(POR/PDR复位)

2. 从待机模式中返回

以下介绍寄存器这些都是必须记住的结合库函数看

STM32学习笔记

输入模式初始化GPIOE2,3,4 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PORTA,PORTE时钟: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); ③PE.2.3.4端口配置:GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; ④设置成(上拉)输入:GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; ⑤GPIO_Init(GPIOE, &GPIO_InitStructure); 输出模式初始化 ①IO口初始化:GPIO_InitTypeDef GPIO_InitStructure; ②使能PB,PE端口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); ③3LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; ④设置(推挽)输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ⑤设置IO口速度为50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ⑥说明初始化哪个端口GPIO_Init(GPIOB, &GPIO_InitStructure); 在LED灯试验中初始为高电平灭GPIO_SetBits(GPIOB,GPIO_Pin_5); 再初始化相同发输出模式时③④⑤可省略例如(经实验初始化恰好为不同IO口相同IO序号③可省略,应该不规范吧) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数; 2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。 3,头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。 4,他并不是C自带的,可以不用。 5,调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h 这个头文件。

STM32学习笔记_STM32F103ZET6

STM32F103 系列芯片的系统架构: 系统结构: 在每一次复位以后,所有除SRAM 和FLITF 以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR 来打开该外设的时钟。

GPIO 输入输出,外部中断,定时器,串口。理解了这四个外设,基本就入门了一款MCU。 时钟控制RCC: -4~16M 的外部高速晶振 -内部8MHz 的高速RC 振荡器 -内部40KHz低速RC 振荡器,看门狗时钟 -内部锁相环(PLL,倍频),一般系统时钟都是外部或者内部高速时钟经过PLL 倍频后得到 - 外部低速32.768K 的晶振,主要做RTC 时钟源

ARM存储器映像: 数据字节以小端格式存放在存储器中。一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。

存储器映像与寄存器映射: ARM 存储器映像 4GB 0X0000 00000X1FFF FFFF 0X2000 00000X3FFF FFFF 0X4000 00000X5FFF FFFF

寄存器说明: 寄存器名称 相对外设基地址的偏移值 编号 位表 读写权限 寄存器位 功能说明 使用C语言封装寄存器: 1、总线和外设基地址封装利用地址偏移 (1)定义外设基地址(Block2 首地址) (2)定义APB2总线基地址(相对外设基地址偏移固定) (3)定义GPIOX外设基地址(相对APB2总线基地址偏移固定)(4)定义GPIOX寄存器地址(相对GPIOX外设基地址偏移固定)(5)使用 C 语言指针操作寄存器进行读/写 //定义外设基地址 #define PERIPH_BASE ((unsigned int)0x40000000) 1) //定义APB2 总线基地址 #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2) //定义GPIOC 外设基地址 #define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3) //定义寄存器基地址这里以GPIOC 为例 #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4) #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04) #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08) #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C) #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10) #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14) #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18) //控制GPIOC 第0 管脚输出一个低电平5) GPIOC_BSRR = (0x01<<(16+0)); //控制GPIOC 第0 管脚输出一个高电平 GPIOC_BSRR = (0x01<<0);

stm32学习 c语言笔记

这是前段时间做彩屏显示时候遇到的难题, *(__IO uint16_t *) (Bank1_LCD_C)这个就是将后面的数据转换为地址,然后对地址单元存放数据。可如下等效: __IO uint16_t *addr; addr = (__IO uint16_t *) Bank1_LCD_C; #ifdef和#elif连用,语法和if。。。else if语句一样 推挽输出增加驱动,可以驱动LED起来 static int count=0 count++ 这个语句中,count仅仅被初始化一次 以后加加一次期中的值就不会变化了 SysTick_CTRL(控制和状态寄存器) SysTick_LOAD(重装载寄存器) SysTick_VAL(当前值寄存器) SysTick_CALIB(校准值寄存器)

TFT经验:弄多大的相片,必须先把那个相片的尺寸改掉,再去取模,才可以,要不会有重影的嘿嘿嘿嘿 VBAT 是电池供电的引脚 VBAT和ADD同时都掉电时才能让备份区复位。 volatile一个变量的存储单元可以在定义该变量的程序之外的某处被引用。 volatile主要是程序员要告诉编译器不要对其定义的这个变量进行优化,防止其不能被引用,不能被改变。 VDDA>2.4V ADC才能工作 VDDA>2.7V USB才能工作 VDD(1.8-3.6v) VBAT=1.8-3.6v VSS VSSA VREF必须接到地线 没有外部电源供电时必须VBAT接上VDD 使用PLL时,VDDA必须供电

printf("abs(x)=%d\n",x<0?(-1)*x:x) 条件编译是问号前边为真则取冒号前边的值,为假的,则取后边的值。 所以说上边这条打印的语句是打印x的绝对值。 //stm32f10x_nvic.c stm32f10x_lib.c stm32f10x_gpio.c stm32f10x_flash.c stm32f10x_rcc.c TIM6 TIM7基本定时器 (只有这两个定时器不能产生PWM) TIM1 TIM8高级控制定时器 TIM2 TIM3 TIM4 TIM5为通用定时器 其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出! 修改和自己写代码时候

STM32F407学习资料

使用心得: STM32F4与STM32F1在ADC方面的区别: 通常,在STM32F1中需要加自动校准的程序,如下: // 使能ADC1自动校准功能 ADC_ResetCalibration(ADC1); //检查ADC1自校准的状态位 while(ADC_GetResetCalibrationStatus(ADC1)); //启动ADC1自校准 ADC_StartCalibration(ADC1); //检查ADC1自校准是否结束 while(ADC_GetCalibrationStatus(ADC1)); // ADC自动校准结束--------------- 然而,STM32F4中无需此程序,给出STM32F407的ADC3和DMA方式的官方程序如下:/** ****************************************************************************** * @file ADC3_DMA/main.c * @author MCD Application Team * @version V1.0.0 * @date 19-September-2011 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS A T PROVIDING CUSTOMERS * WITH CODING INFORMA TION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SA VE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY

STM32学习笔记

STM32学习笔记——时钟频率 ******************************** 本学习笔记基于STM32固件库V3.0 使用芯片型号:STM32F103 开发环境:MDK ******************************** 第一课时钟频率 STM32F103内部8M的内部震荡,经过倍频后最高可以达到72M。目前TI的M3系列芯片最高频率可以达到80M。 在stm32固件库3.0中对时钟频率的选择进行了大大的简化,原先的一大堆操作都在后台进行。系统给出的函数为SystemInit()。但在调用前还需要进行一些宏定义的设置,具体的设置在system_stm32f10x.c文件中。 文件开头就有一个这样的定义: //#define SYSCLK_FREQ_HSE HSE_Value //#define SYSCLK_FREQ_20MHz 20000000 //#define SYSCLK_FREQ_36MHz 36000000 //#define SYSCLK_FREQ_48MHz 48000000 //#define SYSCLK_FREQ_56MHz 56000000 #define SYSCLK_FREQ_72MHz 72000000 ST 官方推荐的外接晶振是8M,所以库函数的设置都是假定你的硬件已经接了8M 晶振来运算的.以上东西就是默认晶振8M 的时候,推荐的CPU 频率选择.在这里选择了: #define SYSCLK_FREQ_72MHz 72000000 也就是103系列能跑到的最大值72M 然后这个C文件继续往下看 #elif defined SYSCLK_FREQ_72MHz const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_SysClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz; const uint32_t SystemFrequency_APB1Clk = (SYSCLK_FREQ_72MHz/2); const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz; 这就是在定义了CPU跑72M的时候,各个系统的速度了.他们分别是:硬件频率,系统时 钟,AHB总线频率,APB1总线频率,APB2总线频率.再往下看,看到这个了: #elif defined SYSCLK_FREQ_72MHz static void SetSysClockTo72(void); 这就是定义72M 的时候,设置时钟的函数.这个函数被SetSysClock ()函数调用,而SetSysClock ()函数则是被SystemInit()函数调用.最后SystemInit()函数,就是被你调用的了

STM32的学习速成

STM32入门系列教程如何提高STM32的学习效率 Revision0.01 (2010-04-08)

目录 第一章笔者的入门总结 (2) 1.1为什么要把时间花在“犹豫”上? (2) 1.2看资料需要计划、耐心和速度 (2) 1.3学STM32必备开发板 (3) 1.4熟悉开发板并试图写程序 (3) 第二章STM32入门方法谈 (4) 2.1拿到开发板我该做什么? (4) 2.2我的时间如何安排 (5) 2.3碰到问题怎么办? (5) 第三章STM32学习步骤 (6) 3.1关于STM32文档学习 (6) 3.230天上手STM32计划 (7) 3.2.1第1步:熟悉调试软件 (8) 3.2.2第2步:GPIO编程 (8) 3.2.3开始全新的STM32深入研究 (9) 福州芯达工作室简介 (9)

第一章笔者的入门总结 1.1为什么要把时间花在 犹豫””上? 为什么要把时间花在““犹豫 每当我们在入门之前(ARM是这样,DSP也一样),总会会有很多疑问,会有很多顾虑。我们渴望知道学习STM32前景如何?需要啥基础?难不难?适不适合我?但是什么时候能心潮澎湃地、相当着急地开始学STM32?日子在一天一天过去!你开始行动了吗?没有行动的思索,永远都不可能入门!把这些时间用来看书吧,效果能好一万倍。 大家一般都是从51单片机过来的,回想一下,我们之前学单片机时如何入门呢?实际上都是先看书(理论),再玩板子(实践)。严格地说,应该是模仿实验。熟悉之后才会自己写程序代码实现某个功能。因此,如果你正在咨询STM32;如果你正对STM32心潮澎湃;如果你想入门STM32;那么,从现在开始,不要犹豫了,不要想再详细地了解STM32的前景了。做一个可能影响你一生的决定吧!不用咨询,不用兴奋,开始看书籍(文档)吧!!每个人都是这么走过来的。 1.2看资料需要计划、耐心和速度 这里所谓的“资料”包括STM32书籍、文档。因为STM32有个特点,datasheet 很多都是中文的,有些同学就没有去买书籍,直接看STM32的用户手册,也是可以的。但是不管看书籍还是文档,我们是需要计划的。不是今天看3页,明天看5页。一本书看了两个月,还在磨蹭。请记住,你学的不是寂寞,是STM32!看书或文档不是用来消遣时间的。背水一战吧,给自己规定一个底线:两周内把一定粗略地过一遍!不要求都看懂,事实上,不可能都看懂。但我们必须理解基本知识,对难度高的知识有一个印象,至少以后碰到问题的时候,我们会似曾相识,感觉在哪里见到过,于是翻资料上网找答案——带着问题的时候,效率才是超高的。 两周过去了,STM32的知识你过一遍了吗?没看完?那么,你应该考虑这些天中,你是否尽力了?是否真的想学STM32?或者还是看到STM32人气很高,也想跟下时髦?是不是碰到问题没法解决就想放弃了?现在是你做第二个决定的时候了,请决定你是否继续攻读STM32。如果是一时冲动想跟时髦,请马上放弃——你已经浪费两周时间了,你还想再浪费14天吗?如果想吃得苦中苦,方为人上人,OK,请继续往下看:) 1.3学STM32必备开发板 稍微了解一些理论知识后,现在摆在你面前,有两条路: 第一,自己画PCB制板、焊接、调试。 第二,购买一套性价比高的开发板。 笔者之前做过几次PCB设计,而且当时在实验室可以报销所有费用,就自

STM32入门基本知识

STM32学前班教程之一:选择他的理由 经过几天的学习,基本掌握了STM32的调试环境和一些基本知识。想拿出来与大家共享,笨教程本着最大限度简化删减STM32入门的过程的思想,会把我的整个入门前的工作推荐给大家。就算是给网上的众多教程、笔记的一种补充吧,所以叫学前班教程。其中涉及产品一律隐去来源和品牌,以防广告之嫌。全部汉字内容为个人笔记。所有相关参考资料也全部列出。:lol 教程会分几篇,因为太长啦。今天先来说说为什么是它——我选择STM32的原因。 我对未来的规划是以功能性为主的,在功能和面积之间做以平衡是我的首要选择,而把运算放在第二位,这根我的专业有关系。里面的运算其实并不复杂,在入门阶段想尽量减少所接触的东西。 不过说实话,对DSP的外设并和开发环境不满意,这是为什么STM32一出就转向的原因。下面是我自己做过的两块DSP28的全功能最小系统板,在做这两块板子的过程中发现要想尽力缩小DSP的面积实在不容易(目前只能达到50mm×45mm,这还是没有其他器件的情况下),尤其是双电源的供电方式和的电源让人很头疼。 后来因为一个项目,接触了LPC2148并做了一块板子,发现小型的ARM7在外设够用的情况下其实很不错,于是开始搜集相关芯片资料,也同时对小面积的AVR和51都进行了大致的比较,这个时候发现了CortexM3的STM32,比2148拥有更丰富和灵活的外设,性能几乎是2148两倍(按照MIPS值计算)。正好2148我还没上手,就直接转了这款STM32F103。 与2811相比较(核心供电情况下),135MHz×1MIPS。现在用STM32F103,72MHz×,性能是DSP的66%,STM32F103R型(64管脚)芯片面积只有2811的51%,STM32F103C型(48管脚)面积是2811的25%,最大功耗是DSP的20%,单片价格是DSP的30%。且有更多的串口,CAP和PWM,这是有用的。高端型号有SDIO,理论上比SPI速度快。 由以上比较,准备将未来的拥有操作系统的高端应用交给DSP的新型浮点型单片机28335,而将所有紧凑型小型、微型应用交给STM32。 STM32学前班教程:怎么开发 sw笨笨的STM32学前班教程之二:怎么开发目前手头的入门阶段使用的开发器概述 该产品为简易STM32调试器和DEMO板一体化的调试学习设备,价格在一百多块。 2、硬件配置

STM32学习笔记(5)通用定时器PWM输出

STM32学习笔记(5):通用定时器PWM输出 2011年3月30日TIMER输出PWM 1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。 STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。 1.1PWM输出模式 STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下: 110:PWM模式1-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。 111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。 由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。 而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节,在此就不详细赘述了。 1.2PWM输出管脚 PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如

STM32入门C语言详解精编版

阅读flash:芯片内部存储器flash操作函数我的理解——对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据。 基础应用1,FLASH时序延迟几个周期,等待总线同步操作。推荐按照单片机系统运行频率,0—24MHz时,取Latency=0;24—48MHz时,取Latency=1;48~72MHz时,取Latency=2。 所有程序中必须的 用法:FLASH_SetLatency(FLASH_Latency_2); 位置:RCC初始化子函数里面,时钟起振之后。 基础应用2,开启FLASH预读缓冲功能,加速FLASH的读取。 所有程序中必须的 用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 位置:RCC初始化子函数里面,时钟起振之后。 3、阅读lib:调试所有外设初始化的函数。 我的理解——不理解,也不需要理解。只要知道所有外设在调试的时候,EWRAM需要从这个函数里面获得调试所需信息的地址或者指针之类的信息。 基础应用1,只有一个函数debug。所有程序中必须的。 用法:#ifdef DEBUG debug(); #endif 位置:main函数开头,声明变量之后。 4、阅读nvic:系统中断管理。 我的理解——管理系统内部的中断,负责打开和关闭中断。 基础应用1,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。 所有程序中必须的。 用法:void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; //中断管理恢复默认参数 #ifdef VECT_TAB_RAM //如果C/C++ Compiler\Preprocessor\Defined symbols中的定义了 VECT_TAB_RAM(见程序库更改内容的表格) NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //则在RAM调试 #else //如果没有定义VECT_TAB_RAM NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//则在Flash里调试 #endif //结束判断语句 //以下为中断的开启过程,不是所有程序必须的。 //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC优先级分组,方式。 //注:一共16个优先级,分为抢占式和响应式。两种优先级所占的数量由此代码确定, NVIC_PriorityGroup_x可以是0、1、2、3、4,分别代表抢占优先级有1、2、4、8、16个和响应优先级有16、8、4、2、1个。规定两种优先级的数量后,所有的中断级别必须在其中选择,抢占级别高的会打断其他中断优先执行,而响应级别高的会在其他中断执行完优先执行。 //NVIC_InitStructure.NVIC_IRQChannel = 中断通道名; //开中断,中断名称见函数库 //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级

STM32学习笔记

1、GPIO函数: 输出: HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);//此例以PA12口为例 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); //此例以PA12口为例 HAL_GPIO_ TogglePin(GPIOA,GPIO_PIN_12); //此例以PA12口为例 2、串口函数: 1、串口发送/接收函数 HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制 HAL_UART_Receive();串口轮询模式接收,使用超时管理机制 HAL_UART_Transmit_IT();串口中断模式发送 HAL_UART_Receive_IT();串口中断模式接收 HAL_UART_Transmit_DMA();串口DMA模式发送 HAL_UART_Transmit_DMA();串口DMA模式接收 2、串口中断函数 HAL_UART_TxHalfCpltCallback();一半数据发送完成时调用 HAL_UART_TxCpltCallback();数据完全发送完成后调用 HAL_UART_RxHalfCpltCallback();一半数据接收完成时调用 HAL_UART_RxCpltCallback();数据完全接受完成后调用 HAL_UART_ErrorCallback();传输出现错误时调用 例程:串口接收中断 uint8_t aTxStartMessages[] = "\r\n******UART commucition using IT******\r\nPlease enter 10 characters:\r\n"; uint8_t aRxBuffer[20]; 2、在main函数中添加两个语句通过串口中断发送aTxStartMessage数组的数据和接收数据10个字符,保存在数组aRxBuffer中 HAL_UART_Transmit_IT(&huart1 ,(uint8_t*)aTxStartMessages,sizeof(aTxStartMessages)); //sizeof()可读取目标长度 HAL_UART_Receive_IT(&huart1,(uint8_t*)aRxBuffer,10); 3、在main.c文件后面添加中断接收完成函数,将接收到的数据又通过串口发送回去。 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { UNUSED(huart); HAL_UART_Transmit(&huart1,(uint8_t*)aRxBuffer,10,0xFFFF);//(uint8_t*)aRxBuffer为字符串地址,10为字符串长度,0xFFFF为超时时可以在中间加任何可执行代码。 }

STM32自学笔记

一、原子位操作: 原子位操作定义在文件中。令人感到奇怪的是位操作函数是对普通的内存地址进行操作的。原子位操作在多数情况下是对一个字长的内存访问,因而位号该位于0-31之间(在64位机器上是0-63之间),但是对位号的范围没有限制。 原子操作中的位操作部分函数如下: void set_bit(int nr, void *addr)原子设置addr所指的第nr位 void clear_bit(int nr, void *addr)原子的清空所指对象的第nr位 void change_bit(nr, void *addr)原子的翻转addr所指的第nr位int test_bit(nr, void *addr)原子的返回addr位所指对象nr位int test_and_set_bit(nr, void *addr)原子设置addr所指对象的第nr位,并返回原先的值 int test_and_clear_bit(nr, void *addr)原子清空addr所指对象的第nr位,并返回原先的值 int test_and_change_bit(nr, void *addr)原子翻转addr所指对象的第nr位,并返回原先的值 unsigned long word = 0; set_bit(0, &word); /*第0位被设置*/ set_bit(1, &word); /*第1位被设置*/ clear_bit(1, &word); /*第1位被清空*/ change_bit(0, &word); /*翻转第0位*/ 二、STM32的GPIO锁定: 三、中断挂起: 因为某种原因,中断不能马上执行,所以“挂起”等待。比如有高、低级别的中断同时发生,就挂起低级别中断,等高级别中断程序执行完,在执行低级别中断。四、固文件: 固件(Firmware)就是写入EROM(可擦写只读存储器)或EEPROM(电可擦可编程只读存储器)中的程序。 五、固件库:包含各个外设或者内核的驱动头文件和C文件。 六、TIx的输入捕获滤波器(消抖): 采样频率fSAMPLING,采样次数N,如果以采样频率对一脉冲进行采样时,如果在N个采样方波里该脉宽不变,则视为一次有效的脉冲,否则视为无效的脉冲。 七、高级定时器的PWM互补输出: 常用于X相电机驱动,其中的互补输出则防止电机的死区出现。

稀里糊涂学习STM32全本

J^dt ? ? ? ?? ???? ? ????? ? q?670 ? ?8 ?Yū ?Yū ? ū a ?q? 1 /? ? ? % - ? $ L ? ) 670 &RUWH[ 0 #&RUWH[ 0 ? $50Y 0 8 ? )??? ?) b?0 ) #0 0 ? $50? 0 # 0 ?? $50 2 (? #) 8? ?? 3 δ . (?)?- ? δ 8?b q? ? - /? ??? ? ? ? ?-? -? ? -?670 ?? " $ ? -? / ) ? -?670 q ? ǎ ? ? 670 0) Ρ? ? ???p ? - ? ?? ?- # ? ) ?μ-670 )-1 ? -? - ? ? ?+ ??? ? ?? ?) ??(? C ? - ?

J^dt %- (0? ) ? (??/ ?W ? μ - d /??q670 e $% $% " - ? ?p ?" ? ?? 8 '0$ ? c? q? G>1" 3 ? $+% ?- ??? ? ? ? ? $+%"? ? $3% $3% ?P ?? ? ?? ? ! 8? $ $3% ?ǎ2-? #$3% ?ǎ?-? .1" (-? v 670 " ? 8 ?)? ?v b? 50 670 ) [[[?#μ?? 9

J^dt ? ) 670 ? ?? " ?? . 5HJ K # - 0$7 ; K - ? ? 670 ? ? %3 ? ? ? d K e d670 ) [B6WG3HULSKB/LEB9 e? LQF ?-/ / ?? 0) 670 ? ?< ? - ?) - % ? +- ?) ?> ? / -? ?? ??? ??670 t " ?J ? )- >- .? )8 t)?? ? ? - ? ? */ - -? -% + ) ? ?? % - ? ? 2 ??9 ?a- ǎ ǎ? a

STM32学习心得笔记

STM32学习心得笔记 时钟篇 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍, 但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外, 实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。 STM32中有一个全速功能的USB 模块,其串行接口引擎需要一个频率为48MHz的时

钟源。该时钟源只能 从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL 必须使能, 并且时钟频率配置为48MHz或72MHz。 另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。 系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL 输出、HSI或者HSE。系统时钟最 大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分 频。其中AHB分频器输出的时钟送给5大模块使用: ①、送给AHB 总线、内核、内存和DMA使用的HCLK时钟。 ②、通过8分频后送给Cortex的系统定时器时钟。 ③、直接送给Cortex的空闲运行时钟FCLK。 ④、送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz), 另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

STM32经典学习资料——SPI

SPI总线 与IIC类似,SPI也是一种通信协议。今天我们就以WX25X16芯片为例来介绍SPI.首先我们来看下硬件连接。 、从原理图可以看到该芯片需要单片机控制的管脚有4个,非别是CS,DO,DIO,CLK.其中CS 是片选信号,只有将该位拉低才能选中该芯片。DO,DIO分别是输出和输入。CLK是时钟信号。SPI通信的步骤如下所示: 1)获取地址1 2)获取地址2 3)擦除扇区 4)写入数据 好的,下面我们对每个步骤进行分析 (1)在对芯片操作前先要对端口及SPI外设进行相应的设置: /* 函数名:SPI_FLASH_Init(void) 功能:对端口和SPI初始化 输入:无 输出:无 调用:被主函数调用 */ void SPI_FLASH_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE); /*!< SPI_FLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); /*将PA5(CLK)配置成复用推挽输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /*将PA6(DO)设置成浮空输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOA, &GPIO_InitStructure); /将PA7(DIO)设为浮空输入/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure); /将PA4(CS)设为推挽输出/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /拉高CS,失能芯片,该语句是宏定义,就是置高PA4/ SPI_FLASH_CS_HIGH(); /* SPI配置/ // W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK. /*将SPI设为全双工模式*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; /*将SPI设为主模式*/ SPI_InitStructure.SPI_Mode = SPI_Mode_Master; /*将SPI通信的数据大小设为8位*/ SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; /*将CLK的高电平设为空闲*/ SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /*设置在第二个时钟沿捕获数据*/ SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; /*指定NSS信号由软件管理*/ SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /SPI_BaudRatePrescaler用来定义波特率预分频的值,这个值用以设置发送和接收的SCK时钟/ SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; /SPI_FirstBit指定了数据传输从高位还是低位开始/ SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /SPI_CRCPolynomial定义了用于CRC值计算的多项式/ SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE); } (2)获取器件地址1

STM32学习笔记(18)-数据的保存和毁灭

数据的保存和毁灭(2) 和以前学到的有关数据保存不同,这里的数据保存还有“保密”之意,即一旦受到意外的侵入,STM32将毁灭数据。这是通过Tamper机制来实现的。 以下是数据手册中的有关说明: 5.3.1 侵入检测 当TAMPER引脚上的信号从0变成1或者从1变成0(取决于备份控制寄存器BKP_CR的TPAL 位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除。然而为了避免丢失侵入事件,侵入检测信号是边沿检测的信号与侵入检测允许位的逻辑与,从而在侵入检测引脚被允许前发生的侵入事件也可以被检测到。 ●当 TPAL=0 时:如果在启动侵入检测TAMPER引脚前(通过设置TPE位)该引脚已经为高电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现上升沿)。 ●当 TPAL=1 时:如果在启动侵入检测引脚TAMPER前(通过设置TPE位)该引脚已经为低电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现下降沿)。 设置BKP_CSR寄存器的TPIE位为’1’,当检测到侵入事件时就会产生一个中断。 在一个侵入事件被检测到并被清除后,侵入检测引脚TAMPER应该被禁止。然后,在再次写入备份数据寄存器前重新用TPE位启动侵入检测功能。这样,可以阻止软件在侵入检测引脚上仍然有侵入事件时对备份数据寄存器进行写操作。这相当于对侵入引脚TAMPER进行电平检测。 注:当V DD电源断开时,侵入检测功能仍然有效。为了避免不必要的复位数据备份寄存器,TAMPER引脚应该在片外连接到正确的电平。 显然,Tamper需要硬件与之配合。以上数据手册描述了硬件配置时的一些注意事项。 (1)可以是把引脚由低电平到高电平认为是一次侵入,也可以把引脚从高电平变到低电平认为是一次侵入,这通过TPAL来设置。

STM32学习心得(新手必看)

STM32学习心得(新手必看) (作者:logokfu 邮箱:g535343589@https://www.360docs.net/doc/27306313.html, ) 在这里说下我的学习心得体会(照顾下新手,老鸟都表笑哦,呵呵)。 说下关于开发环境的建立,都说万事开头难,每种芯片都有它的开发环 境,首先得熟悉STM32的开发环境。用的最多就是MDK 和IAR 了,关于MDK ,这个用过51单片机的筒子肯定都知道keil uvision 。这个MDK 其实就是专门开发ARM 芯片的工具。开发51单片机的那个叫C51 。这个C51和MDK 共同使用keil uvsion 这个UI 界面。也是说C51和MDK 共同使用keil uvsion 这个外壳。好了,关于开发软件的介绍就介绍这么多,有什么还不清楚的,筒子们可以邮箱联系我。当然支持STM32的集成开发环境(IDE )还不止MDK 和IAR ,只不过这两个使用的人相对其他工具来说用的人比较多吧。另外 RIDE, HiTOP , TrueSTUDIO 这个三个开发工具也支持STM32的开发(可能还有其他的工具,不过我不知道)。有兴趣的盆友可以使用下尝尝鲜。 说下关于ST 官方为我们提供的固件库的使用问题。不要觉得固件库是 这个什么可怕的东西,固件库是ST 为用户提供的函数库,这些函数帮 我们一次性解决多个寄存器的设置问题。如果没有固件库的话,那么我们就需要像使用51单片机那样直接设置要使用的寄存器,在51单片机上为寄存器直接赋值可能没什么的,但是由于STM32的寄存器太多,如果一个个设置的话会很麻烦,有时候还会忘掉某些寄存器的设置,ST 提供的固件库正是为我们提供了这些方便。我们只需要为相关函数指定参数就可以完成寄存器的设置了。为产品的快速开发提供了保障。当然新固件库是好,但是却会对新手理解硬件结构造成一定的影响。有的人喜欢直接为STM32的寄存器直接赋值,说这样子比较直观,有的人喜欢使用固件库。当然这个是个人喜好,大家可以根据自己的喜好进行选择。我的建议是可以直接用固件库,虽然我对硬件结构还没了解很多,用固件库的话可能会觉得有点学习的不是很踏实,因此我们可以借助开发工具的go to definition 功能,顺藤摸瓜。在最终的函数中,我们就能发现这些函数到底为哪些寄存器设置了什么值。这样看多了,时间久了各个寄存器也就了解的差不多了。当然进行下随着产品的不断推出,固件库版本可能会不断的更新。之前的固件库版 首先 其次

相关文档
最新文档