当前位置:文档之家› 单片机STM32学习笔记

单片机STM32学习笔记

单片机STM32学习笔记
单片机STM32学习笔记

推挽输出与开漏输出的区别

推挽输出:可以输出高,低电平,连接数字器件;

开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内).

推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止.

要实现“线与”需要用OC(open collector)门电路.是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小,效率高。输出既可以向负载灌电流,也可以从负载抽取电流。

问题:

很多芯片的供电电压不一样,有3.3v和5.0v,需要把几种IC的不同口连接在一起,是不是直接连接就可以了?实际上系统是应用在I2C上面。

简答:

1、部分3.3V器件有5V兼容性,可以利用这种容性直接连接

2、应用电压转换器件,如TPS76733就是5V输入,转换成3.3V、1A输出。

开漏电路特点及应用

在电路设计时我们常常遇到开漏(open drain)和开集(open collector)的概念。所谓开漏电路概念中提到的“漏”就是指MOSFET的漏极。同理,开集电路中的“集”就是指三极管的集电极。开漏电路就是指以MOSFET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上拉电阻组成。如图1所示:

组成开漏形式的电路有以下几个特点:

1. 利用外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up ,MOSFET到GND。IC内部仅需很下的栅极驱动电流。如图1。

2. 可以将多个开漏输出的Pin,连接到一条线上。形成“与逻辑” 关系。如图1,当PIN_A、PIN_B、PIN_C任意一个变低后,开漏线上的逻辑就为0了。这也是I2C,SMBus等总线判断总线占用状态的原理。

3. 可以利用改变上拉电源的电压,改变传输电平。如图2, IC的逻辑电平由电源Vcc1决定,而输出高电平则由Vcc2决定。这样我们就可以用低电平逻辑控制输出高电平逻辑了。

4. 开漏Pin不连接外部的上拉电阻,则只能输出低电平(因此对于经典的51单片机的P0口而言,要想做输入输出功能必须加外部上拉电阻,否则无法输出高电平逻辑)。

5. 标准的开漏脚一般只有输出的能力。添加其它的判断电路,才能具备双向输入、输出的能力。

应用中需注意:

1. 开漏和开集的原理类似,在许多应用中我们利用开集电路代替开漏电路。例如,某输入Pin要求由开漏电路驱动。则我们常见的驱动方式是利用一个三极管组成开集电路来驱动它,即方便又节省成本。如图3。

2. 上拉电阻R pull-up的阻值决定了逻辑电平转换的沿的速度。阻值越大,速度越低功耗越小。反之亦然。

Push-Pull输出就是一般所说的推挽输出,在CMOS电路里面应该较CMOS输出更合适,应为在CMOS里面的push-pull输出能力不可能做得双极那么大。输出能力看IC内部输出极N 管P管的面积。和开漏输出相比,push-pull的高低电平由IC的电源低定,不能简单的做逻辑操作等。push-pull是现在CMOS电路里面用得最多的输出级设计方式。

at91rm9200 GPIO 模拟I2C接口时注意!!

判断上拉输入和下拉输入

当一个按键按下的时候,对应的引脚输入数据是0或1是不确定的,还要看外部电路的

组成是上拉还是下拉,当外部电路时上拉的时候,即外部接正的时候,读入的数据是1;当外部电路是下拉的时候,读入的数据是0.

上拉例子:无键按下的时候是1 ,有

键按下是0

下拉例子:无键按下的时候是0,有键按下时是1

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使用。

⑤、送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC

分频器可选择为2、4、6、8分频。

在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。

需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。

连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意USB模块虽然需要一个单独的48MHz时钟信号,但它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时

钟应该是由APB1提供的。

连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口。

下图为STM32芯片的时钟结构图。从图中可以直观的看出STM32的时钟封装。

STM32资料一

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; //响应优先级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //启动此通道的中断

NVIC_Init(&NVIC_InitStructure); //中断初始化

}

5、 rcc:单片机时钟管理。

我的理解——管理外部、内部和外设的时钟,设置、打开和关闭这些时钟。

基础应用1:时钟的初始化函数过程

用法:void RCC_Configuration(void) //时钟初始化函数

ErrorStatus HSEStartUpStatus; //等待时钟的稳定

RCC_DeInit(); //时钟管理重置

RCC_HSEConfig(RCC_HSE_ON); //打开外部晶振

HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部晶振就绪

if (HSEStartUpStatus == SUCCESS)

{

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//flash读取缓冲,加速FLASH_SetLatency(FLASH_Latency_2); //flash操作的延时

RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB使用系统时钟

RCC_PCLK2Config(RCC_HCLK_Div2); //APB2(高速)为HCLK的一半RCC_PCLK1Config(RCC_HCLK_Div2); //APB1(低速)为HCLK的一半

//注:AHB主要负责外部存储器时钟。APB2负责AD,I/O,高级TIM,串口1。APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM。

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHz

RCC_PLLCmd(ENABLE); //启动PLL

while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){} //等待PLL启动

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //将PLL设置为系统时钟源

while (RCC_GetSYSCLKSource() != 0x08){} //等待系统时钟源的启动

}

RCC_AHBPeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE); //启动AHP设备

RCC_APB2PeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE);//启动ABP2设备

RCC_APB1PeriphClockCmd(ABP2设备1 | ABP2设备2 |, ENABLE); //启动ABP1设备}

6、 exti:外部设备中断函数

我的理解——外部设备通过引脚给出的硬件中断,也可以产生软件中断,19个上升、下降或都触发。EXTI0~EXTI15连接到管脚,EXTI线16连接到PVD(VDD监视),EXTI线17连接到RTC(闹钟),EXTI线18连接到USB(唤醒)。

基础应用1,设定外部中断初始化函数。按需求,不是必须代码。

用法: void EXTI_Configuration(void)

{

EXTI_InitTypeDef EXTI_InitStructure; //外部设备中断恢复默认参数

EXTI_InitStructure.EXTI_Line = 通道1|通道2; //设定所需产生外部中断的通道,一共19个。

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //产生中断

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //上升下降沿都触发

EXTI_InitStructure.EXTI_LineCmd = ENABLE; //启动中断的接收

EXTI_Init(&EXTI_InitStructure); //外部设备中断启动

}

7、 dma:通过总线而越过CPU读取外设数据

我的理解——通过DMA应用可以加速单片机外设、存储器之间的数据传输,并在传输期间不影响CPU进行其他事情。这对于入门开发基本功能来说没有太大必要,这个内容先行跳过。

8、 systic:系统定时器

我的理解——可以输出和利用系统时钟的计数、状态。

基础应用1,精确计时的延时子函数。推荐使用的代码。

用法:

static vu32 TimingDelay; //全局变量声明

void SysTick_Config(void) //systick初始化函数

{

SysTick_ITConfig(DISABLE); //停止systick中断

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //systick使用HCLK作为时钟源,频率值除以8。

SysTick_SetReload(9000); //重置时间1毫秒(以72MHz为基础计算)

SysTick_ITConfig(ENABLE); //开启systic中断

}

void Delay (u32 nTime) //延迟一毫秒的函数

{

SysTick_CounterCmd(SysTick_Counter_Enable); //systic开始计时

TimingDelay = nTime; //计时长度赋值给递减变量

while(TimingDelay != 0){}; //检测是否计时完成

SysTick_CounterCmd(SysTick_Counter_Disable); //关闭计数器

SysTick_CounterCmd(SysTick_Counter_Clear); //清除计数值

}

void TimingDelay_Decrement(void) //递减变量函数,函数名由“stm32f10x_it.c”中的中断响应函数定义好了。

{

if (TimingDelay != 0x00) //检测计数变量是否达到0

{ TimingDelay--; //计数变量递减

}

}

注:建议熟练后使用,所涉及知识和设备太多,新手出错的可能性比较大。新手可用简化的延时函数代替:

void Delay(vu32 nCount) //简单延时函数

{

for(; nCount != 0; nCount--); //循环变量递减计数

}

当延时较长,又不需要精确计时的时候可以使用嵌套循环:

void Delay(vu32 nCount) //简单的长时间延时函数

{int i; //声明内部递减变量

for(; nCount != 0; nCount--) //递减变量计数

{for (i=0; i<0xffff; i++)} //内部循环递减变量计数

}

9、 gpio:I/O设置函数

我的理解——所有输入输出管脚模式设置,可以是上下拉、浮空、开漏、模拟、推挽模式,频率特性为2M,10M,50M。也可以向该管脚直接写入数据和读取数据。

基础应用1,gpio初始化函数。所有程序必须。

用法:void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure; //GPIO状态恢复默认参数

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_标号 | GPIO_Pin_标号 ; //管脚位置定义,标号可以是NONE、ALL、0至15。

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//输出速度2MHz

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

GPIO_Init(GPIOC, &GPIO_InitStructure); //C组GPIO初始化

//注:以上四行代码为一组,每组GPIO属性必须相同,默认的GPIO参数为:ALL,2MHz,FLATING。如果其中任意一行与前一组相应设置相同,那么那一行可以省略,由此推论如果前面已经将此行参数设定为默认参数(包括使用GPIO_InitTypeDef GPIO_InitStructure代码),本组应用也是默认参数的话,那么也可以省略。以下重复这个过程直到所有应用的管脚全部被定义完毕。

……

}

基础应用2,向管脚写入0或1

用法:GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01); //写入1

基础应用3,从管脚读入0或1

用法:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)

sw笨笨的STM32笔记之七:让它跑起来,基本硬件功能的建立

0、实验之前的准备

a) 接通串口转接器

b) 下载IO与串口的原厂程序,编译通过保证调试所需硬件正常

1、 flash,lib,nvic,rcc和GPIO,基础程序库编写

a) 这几个库函数中有一些函数是关于芯片的初始化的,每个程序中必用。为保障程序品质,初学阶段要求严格遵守官方习惯。注意,官方程序库例程中有个platform_config.h文件,是专门用来指定同类外设中第几号外设被使用,就是说在main.c里面所有外设序号用x代替,比如USARTx,程序会到这个头文件中去查找到底是用那些外设,初学的时候参考例程别被这个所迷惑住。

b) 全部必用代码取自库函数所带例程,并增加逐句注释。

c) 习惯顺序——Lib(debug),RCC(包括Flash优化),NVIC,GPIO

d) 必用模块初始化函数的定义:

void RCC_Configuration(void); //定义时钟初始化函数

void GPIO_Configuration(void); //定义管脚初始化函数

void NVIC_Configuration(void); //定义中断管理初始化函数

void Delay(vu32 nCount); //定义延迟函数

e) Main中的初始化函数调用:

RCC_Configuration(); //时钟初始化函数调用

NVIC_Configuration(); //中断初始化函数调用

GPIO_Configuration(); //管脚初始化函数调用

f) Lib注意事项:

属于Lib的Debug函数的调用,应该放在main函数最开始,不要改变其位置。

g) RCC注意事项:

Flash优化处理可以不做,但是两句也不难也不用改参数……

根据需要开启设备时钟可以节省电能

时钟频率需要根据实际情况设置参数

h) NVIC注意事项

注意理解占先优先级和响应优先级的分组的概念

i) GPIO注意事项

作为高低电平的I/O,所需设置:RCC初始化里面打开RCC_APB2

PeriphClockCmd(RCC_APB2Periph_GPIOA);GPIO里面管脚设定:IO输出(50MHz,Out_PP);IO输入(5 0MHz,IPU);

j) GPIO应用

GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET);//重置

GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//写入1

GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//写入0

GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) ;//读入IO

k) 简单Delay函数

void Delay(vu32 nCount)//简单延时函数

{for(; nCount != 0; nCount--);}

实验步骤:

RCC初始化函数里添加:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPI OA | RCC_APB2Periph_GPIOB , ENABLE);

不用其他中断,NVIC初始化函数不用改

GPIO初始化代码:

//IO输入,GPIOB的2、10、11脚输出

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ;//管脚号

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输入输出模式

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化

简单的延迟函数:

void Delay(vu32 nCount) //简单延时函数

{ for (; nCount != 0; nCount--);} //循环计数延时

完成之后再在main.c的while里面写一段:

GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x01);//写入1

Delay(0xffff);

GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)0x00);//写入0

Delay(0xffff);

就可以看到连接在PB2脚上的LED闪烁了,单片机就跑起来了。

sw笨笨的STM32笔记之八:来跟PC打个招呼,基本串口通讯

a) 目的:在基础实验成功的基础上,对串口的调试方法进行实践。硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中。

b) 初始化函数定义:

void USART_Configuration(void); //定义串口初始化函数

c) 初始化函数调用:

void UART_Configuration(void); //串口初始化函数调用

初始化代码:

void USART_Configuration(void) //串口初始化函数

{

//串口参数初始化

USART_InitTypeDef USART_InitStructure; //串口设置恢复默认参数

//初始化参数设置

USART_https://www.doczj.com/doc/bb3984099.html,ART_BaudRate = 9600; //波特率9600

USART_https://www.doczj.com/doc/bb3984099.html,ART_WordLength = USART_WordLength_8b; //字长8位

USART_https://www.doczj.com/doc/bb3984099.html,ART_StopBits = USART_StopBits_1; //1位停止字节

USART_https://www.doczj.com/doc/bb3984099.html,ART_Parity = USART_Parity_No; //无奇偶校验

USART_https://www.doczj.com/doc/bb3984099.html,ART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控制

USART_https://www.doczj.com/doc/bb3984099.html,ART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打开Rx接收和Tx发送功能

USART_Init(USART1, &USART_InitStructure); //初始化

USART_Cmd(USART1, ENABLE); //启动串口

}

RCC中打开相应串口

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);

GPIO里面设定相应串口管脚模式

//串口1的管脚初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //管脚9

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

GPIO_Init(GPIOA, &GPIO_InitStructure); //TX初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //管脚10

GPIO_Init(GPIOA, &GPIO_InitStructure); //RX初始化

d) 简单应用:

发送一位字符

USART_SendData(USART1, 数据); //发送一位数据

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)

{} //等待发送完毕

接收一位字符

while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)

{} //等待接收完毕

变量= (USART_ReceiveData(USART1)); //接受一个字节

发送一个字符串

先定义字符串:char rx_data[250];

然后在需要发送的地方添加如下代码

int i; //定义循环变量

while(rx_data!='\0') //循环逐字输出,到结束字'\0'

{USART_SendData(USART1, rx_data); //发送字符

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待字符发

送完毕

i++;}

e) USART注意事项:

发动和接受都需要配合标志等待。

只能对一个字节操作,对字符串等大量数据操作需要写函数

使用串口所需设置:RCC初始化里面打开RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx); GPIO里面管脚设定:串口RX(50Hz,IN_FLOATING);串口TX(50Hz,AF_PP);

f) printf函数重定义(不必理解,调试通过以备后用)

(1)需要c标准函数:

#include "stdio.h"

(2)粘贴函数定义代码

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) //定义为putchar应用(3) RCC中打开相应串口

(4) GPIO里面设定相应串口管脚模式

(6)增加为putchar函数。

int putchar(int c) //putchar函数

{

USART_SendData(USART1, c); //发送字符

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待发送结束

return c; //返回值

}

(8)通过,试验成功。printf使用变量输出:%c字符,%d整数,%f浮点数,%s字符串,/n或/r为换行。注意:只能用于main.c中。

3、 NVIC串口中断的应用

a) 目的:利用前面调通的硬件基础,和几个函数的代码,进行串口的中断输入练习。因为在实际应用中,不使用中断进行的输入是效率非常低的,这种用法很少见,大部分串口的输入都离不开中断。

b) 初始化函数定义及函数调用:不用添加和调用初始化函数,在指定调试地址的时候已经调用过,在那个NVIC_Configuration里面添加相应开中断代码就行了。

c) 过程:

i. 在串口初始化中USART_Cmd之前加入中断设置:

USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//TXE发送中断,TC传输完成中断,RXN E接收中断,PE奇偶错误中断,可以是多个。

ii. RCC、GPIO里面打开串口相应的基本时钟、管脚设置

iii. NVIC里面加入串口中断打开代码:

NVIC_InitTypeDef NVIC_InitStructure;//中断默认参数

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道设置为串口1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //中断占先等级0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中断响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断

NVIC_Init(&NVIC_InitStructure); //初始化

iv. 在stm32f10x_it.c文件中找到void USART1_IRQHandler函数,在其中添入执行代码。一般最少三个步骤:先使用if语句判断是发生那个中断,然后清除中断标志位,最后给字符串赋值,或做其他事情。

void USART1_IRQHandler(void) //串口1中断

{

char RX_dat; //定义字符变量

if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断发生接收中断

{USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中断标志

GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)0x01); //开始传输

理除去前两位

USART_SendData(USART1, RX_dat); //发送数据

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}//等待发送结束

}

}

d) 中断注意事项:

可以随时在程序中使用USART_ITConfig(USART1, USART_IT_TXE, DISABLE);来关闭中断响应。

NVIC_InitTypeDef NVIC_InitStructure定义一定要加在NVIC初始化模块的第一句。

全局变量与函数的定义:在任意.c文件中定义的变量或函数,在其它.c文件中使用extern+定义代码再次定义就可以直接调用了。

sw笨笨的STM32笔记之九:打断它来为我办事,EXIT (外部I /O中断)应用

a) 目的:跟串口输入类似,不使用中断进行的IO输入效率也很低,而且可以通过E XTI插入按钮事件,本节联系EXTI中断。

b) 初始化函数定义:

void EXTI_Configuration(void); //定义IO中断初始化函数

c) 初始化函数调用:

EXTI_Configuration();//IO中断初始化函数调用简单应用:

d) 初始化函数:

void EXTI_Configuration(void)

{

EXTI_InitTypeDef EXTI_InitStructure; //EXTI初始化结构定义

EXTI_ClearITPendingBit(EXTI_LINE_KEY_BUTTON);//清除中断标志

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);//管脚选择

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//事件选择

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//触发模式

EXTI_InitStructure.EXTI_Line = EXTI_Line3 | EXTI_Line4; //线路选择

EXTI_Init(&EXTI_InitStructure);//初始化

}

e) RCC初始化函数中开启I/O时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);

GPIO初始化函数中定义输入I/O管脚。

//IO输入,GPIOA的4脚输入

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入

GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化

f) 在NVIC的初始化函数里面增加以下代码打开相关中断:

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; //通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//占先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //启动 NVIC_Init(&NVIC_InitStructure); //初始化

g) 在stm32f10x_it.c文件中找到void USART1_IRQHandler函数,在其中添入执行代码。一般最少三个步骤:先使用if语句判断是发生那个中断,然后清除中断标志位,最后给字符串赋值,或做其他事情。

if(EXTI_GetITStatus(EXTI_Line3) != RESET) //判断中断发生来源

{ EXTI_ClearITPendingBit(EXTI_Line3); //清除中断标志

USART_SendData(USART1, 0x41); / /发送字符“a”

GPIO_WriteBit(GPIOB, GPIO_Pin_2, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_2)));//LED发生明暗交替

}

h) 中断注意事项:

中断发生后必须清除中断位,否则会出现死循环不断发生这个中断。然后需要对中断类型进行判断再执行代码。

使用EXTI的I/O中断,在完成RCC与GPIO硬件设置之后需要做三件事:初始化EXTI、NVIC 开中断、编写中断执行代码。

sw笨笨的STM32笔记之十:工作工作,PWM输出

a) 目的:基础PWM输出,以及中断配合应用。输出选用PB1,配置为TIM3_CH4,是目标板的LED6控制脚。

b) 对于简单的PWM输出应用,暂时无需考虑TIM1的高级功能之区别。

c) 初始化函数定义:

void TIM_Configuration(void); //定义TIM初始化函数

d) 初始化函数调用:

TIM_Configuration(); //TIM初始化函数调用

e) 初始化函数,不同于前面模块,TIM的初始化分为两部分——基本初始化和通道初始化:

void TIM_Configuration(void)//TIM初始化函数

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定时器初始化结构

TIM_OCInitTypeDef TIM_OCInitStructure;//通道输出初始化结构

//TIM3初始化

TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //周期0~FFFF

TIM_TimeBaseStructure.TIM_Prescaler = 5; //时钟分频

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//模式

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //基本初始化

TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);//打开中断,中断需要这行代码

//TIM3通道初始化

TIM_OCStructInit(& TIM_OCInitStructure); //默认参数

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //工作状态

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //设定为输出,需要PWM输出才需要这行代码

TIM_OCInitStructure.TIM_Pulse = 0x2000; //占空长度

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平

TIM_OC4Init(TIM3, &TIM_OCInitStructure); //通道初始化

TIM_Cmd(TIM3, ENABLE); //启动TIM3

}

f) RCC初始化函数中加入TIM时钟开启:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE);

g) GPIO里面将输入和输出管脚模式进行设置。信号:AF_PP,50MHz。

h) 使用中断的话在NVIC里添加如下代码:

//打开TIM2中断

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; //通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//占先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //启动

NVIC_Init(&NVIC_InitStructure); //

初始化

中断代码:

void TIM2_IRQHandler(void)

{

if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) //判断中断来源

{

TIM_ClearITPendingBit(TIM2, TIM_IT_CC4); //清除中断标志

GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_11)));//变换LED色彩

IC4value = TIM_GetCapture4(TIM2); //获取捕捉数值

}

}

i) 简单应用:

//改变占空比

TIM_SetCompare4(TIM3, 变量);

j) 注意事项:

管脚的IO输出模式是根据应用来定,比如如果用PWM输出驱动LED则应该将相应管脚设为A F_PP,否则单片机没有输出。

STM32 IIC 学习笔记总结

STM32系列IIC学习笔记经验总结一、各寄存器内容与组织:控制、地址匹配、数据、状态、时钟控制、上升沿控制

二、IIC协议及STM32的master实现 EVENT后的第一个符号表示事件发生后对应的标志位的状态,着重看7位地址的通信;

三、基础知识(主要讨论起主机模式,从机模式的配置与使用可类比) 1.默认工作在从机模式,产生起始信号后自动转为主机模式,产生终止信号或仲裁失权后自动转为从机模式;起止信号由主 机模式下的软件实现,地址也只能由主机发送,响应信号由接收器发出(软件实现),要注意区别主机、从机、发送机、接收机; 2.数据通信的直接通道,SDA LineShift RegisterDRMemory(数据寄存器与存储器直接的数据交换发生在DMA模式, 另外若从机在SDA接收到的是地址则直接会与地址寄存器比较,而不会送入数据寄存器) 3.主机产生时钟信号,一串数据总是以起始于start信号,终止于stop信号,一旦SDA线上产生start位信号,主机模 式便被选中;9个寄存器的功能分配简单明了:I2C_CR2主要配置时钟与模块中断及DMA使能位,I2C_CR1则主要产生Start等控制信号,I2C_SR2主要是MSL、TRA和BUSY标志位,I2C_SR1则是其他事件的标志位,接下来就是存储数据的I2C_DR,时钟设置的I2C_CC4R和I2C_TRISE,地址匹配的I2C_OAR1和I2C_OAR2; 4.主机模式必要操作序列:外围时钟输入最少2M(标准模式)、4M(快速模式) 1)配置I2C_CR2寄存器以产生正确时序; 2)配置时钟控制寄存器I2C_CCR; 3)配置上升时间寄存器I2C_TRISE; 4)配置I2C_CR1寄存器以使能接口电路; 5)配置I2C_CR1寄存器,置位START位以产生起始信号; 5.时序具体解析 1)Start信号,置位I2C_CR1的START位以产生起始信号(在总线空闲时,即I2C_SR2的BUSY清零),使转为主机模式(置位I2C_SR2的MSL);在主机模式下,置位START位会在当前字节传输完成后产生一个重启ReStart信号;一旦Start信号送出,I2C_SR1的SB位会由硬件置位并产生中断(前提是ITEVFEN位被置位,貌似文档有误,我认为应是IC2_SR2的ITEVTEN位),然后需要读SR1和写DR以清零SB(这也符合操作时序); 2)从机地址发送,7位模式下,地址字节一旦送出,I2C_SR1的ADDR位会由硬件置位并产生中断(前提是ITEVFEN 置位),然后主机等待读取SR1和SR2以清零ADDR(稍微符合,读SR2貌似饶了一步);7位模式下,地址字节最低位若是0则说明主机要进入发送模式,若是1则是接收模式;I2C_SR2的TRA表示主机在发送模式还是接收模式; 3)主机发送模式,地址送出且ADDR清零后,主机会将DR中数据发送到SDA line(当然经过Shift Register),主机会等到第一个数据写入DR(EV8_1阶段),若收到响应脉冲,SR1中的TxE位会置位(前提是ITEVFEN和ITBUFEN已置位);在最后一个字节传输结束前的传输过程中,若TxE置位且某数据字节没有写入DR,BTF会置位直到(硬件清零)该数据字节被写入到DR,这个过程中SCL会一直被拉低; 4)主机发送模式关闭通信,最后一个字节被写入DR,CR1的STOP位要由软件置位而产生停止信号,接口自动转为从机模式(MSL清零);置位Stop位即对应于EV8_2事件; 5)主机接收模式,地址送出且ADDR清零后,主机会进入接收模式,接口会从SDA line中读数据到DR中(同样经过Shift Register);每个字节接收后的操作序列为,产生应答信号(前提是CR1的ACK位置位),RxNE位置位并产生中断(前提是SR2的ITEVFEN和ITBUFEN置位);在最后一个字节传输结束前的传输过程中,若RxNE 置位且某数据未从DR中读取,BTF会置位直到(硬件清零)该数据字节被读出,这个过程SCL会一直被拉低; 6)主机接收模式关闭通信,收到最后一个字节后会发送NACK信号给从机,从机收到NACK会释放总线(SDA和SCL),此时主机便可发送一个Stop或Restart信号;在读完倒数第二个字节后(RxNE中断后),要清零ACK 位以产生NACK应答,要置位STOP/START位以产生Stop/Restart信号;在单字节数据接收状况,NACK 要在ADDR清零前(EV6)设置,STOP信号要在ADDR清零后配置;Stop信号产生后,主机自动进入从机模式(SR2的MSL清零); 7)最后一字节数据接收的ACK响应前若RxNE清零(ACK清零与Stop请求)没有完成,则建议采取以下步骤以确保ACK位在最后一字节数据接收前被清零,STOP位在最后一字节数据接受完后(没有附加数据)被置位: (1)2字节的数据接收:等到ADDR=1;清零ACK,置位POS;清零ADDR;等到BTF=1(数据1在DR,

STM32学习笔记

STM32学习笔记整理 端口复用配置过程 引脚具体可以复用为啥功能,参考芯片手册STM32F103ZET6.Pdf 具体每个引脚配置成什么模式,参考STM32中文参考手册,第八章,通用IO和复用。NVIC中断

假定设置中断优先级组为2,然后设置 中断3(RTC中断)的抢占优先级为2,响应优先级为1。中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。 那么这3个中断的优先级顺序为:中断7>中断3>中断6 特别说明: 一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。 首先,系统运行后先设置中断优先级分组。调用函数: void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 整个系统执行过程中,只设置一次中断分组。 然后,中断初始化函数 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化NVIC寄存器 结构体内容NVIC_InitTypeDef typedef struct {

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的GPIO学习笔记讲课教案

s t m32的G P I O学习 笔记

I/O口工作模式: 1.高阻输入 输入模式的结构比较简单,就是一个带有施密特触发输入(Schmitt-triggered input)的三态缓冲器(U1),并具有很高的阻抗。施密特触发输入的作用是能将缓慢变化的或者是畸变的输入脉冲信号整形成比较理想的矩形脉冲信号。 执行 GPIO管脚读操作时,在读脉冲(Read Pulse)的作用下会把管脚(Pin)的当前电平状态读到内部总线上(Internal Bus)。 2.推挽输出 推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高. 在推挽输出模式下,GPIO还具有回读功能,实现回读功能的是一个简单的三态门 U2。注意:执行回读功能时,读到的是管脚的输出锁存状态,而不是外部管脚 Pin的状态。 3.开漏输出 开漏是用来连接不同电平的器件,匹配电平用的,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻,很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平,比如加上上拉电阻就可以提供TTL/CMOS电平输出等。

开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管 T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到 GND(有一定内阻) 开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管 T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到 GND(有一定内阻). 4.钳位二级管 其作用是防止从外部管脚 Pin输入的电压过高或者过低。 提高输出电压一种简单的做法:是先在 GPIO管脚上串联一只二极管(如 1N4148),然后再接上拉电阻。 ///////////////////////////////////////////////////////////////////////////////////////////////////////// STM32的GPIO管脚深入分析: 概述:STM23的每个GPIO引脚都可以由软件配置成输出(推挽或开漏),输入(带或不带上拉或下拉)或复用的外设功能端口。多数GPIO引脚与数字或模拟的复用外设共用;除了具有模拟输入(ADC)功能的管脚之外,其他的GPIO引脚都有大电流通过能力。 tip:每个IO口可以自由编程,单IO口寄存器必须要按32位bit被访问。 STM32的每个IO端口都有7个寄存器来控制 一.具体如下8种模式:

STM32各模块学习笔记

STM32 中断优先级和开关总中断 一,中断优先级: STM32(Cortex-M3) 中的优先级概念 STM32(Cortex-M3) 中有两个优先级的概念 —— 抢占式优先级和响应优先级,有人把响应优 先级称作 '亚优先级 '或 '副优先级 ',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应, 即中断嵌 套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时, 这两个中断将没有嵌套关系, 当一个中断到来后, 如 果正在处理另一个中断, 这个后到来的中断就要等到前一个中断处理完之后才能被处理。 如 果这两个中断同时到达, 则中断控制器根据他们的响应优先级高低来决定先处理哪一个; 如 果他们的抢占式优先级和响应优先级都相等, 则根据他们在中断表中的排位顺序决定先处理 哪一个。 既然每个中断源都需要被指定这两种优先级, 就需要有相应的寄存器位记录每个中断的优先 级;在 Cortex-M3 中定义了 8 个比特位用于设置中断源的优先级,这 8 个比特位可以有 8 种分配方式,如下: 这就是优先级分组的概念。 Cortex-M3 允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此 STM32 把指定中断优先级的寄存器位减少到 4 位,这 4个寄存器位的分组方式如下: 第 0 组:所有 4 位用于指定响应优先级 第 1 组:最高 1 位用于指定抢占式优先级,最低 第 2 组:最高 2 位用于指定抢占式优先级,最低 第 3 组:最高 3 位用于指定抢占式优先级,最低 第 4 组:所有 4 位用于指定抢占式优先级 所有 8 位用于指定响应优先级 最 高 1 位用于指定抢占式优先级, 最高 2 位用于指定抢占式优先级, 最高 3 位用于指定抢占式优先级, 最高 4 位用于指定抢占式优先级, 最高 5 位用于指定抢占式优先级, 最高 6 位用于指定抢占式优先级, 最高 7 位用于指定最低 7 位用于指定响应优先级 最低 6 位用于指定响应优先级 最低 5 位用于指定响应优先级 最低 4 位用于指定响应优先级 最低 3 位用于指定响应优先级 最低 2 位用于指定响应优先级 最低 1 位用于指定响应优先级 3 位用于指定响应优先 级 2 位用于指定响应优先 级

stm32pwm输入捕捉模式学习笔记

stm32 pwm输入捕捉模式学习笔记 (本文来自:android_chunhui的博客) PWM输入是输入捕获的一个特殊应用,输入捕获就是当连接到定时器的引脚上产生电平变化时对应的捕获装置会立即将当前计数值复制到另一个寄存器中。你可以开启捕获中断然后在中断处理函数中读出保存的计数值。主要用于读取pwm的频率和占空比。 与输入捕获不同的是PWM输入模式时,用到两个通道(一般用TIMx_CH1或TIMx_CH2),只给其中一个通道分配gpio时钟即可,另一个在内部使用。给一个通道分配gpio时钟后,需要设置另一个为从机且复位模式。(例如使用ch2,ch1就得设置成从机模式)。当一个输入信号(TI1或TI2)来临时,主通道捕获上升沿,从机捕获下降沿。 假设pwm从低电平开始触发,当上升沿来临时,两个通道TIM_CNT均复位开始计数,下一个下降沿来临,从机读取TIM_CNT中的值,记为CCR1,下一个上升沿来临,主通道读取TIM_CNT的值,记为CCR2。所以CCR2/f,为pwm周期,倒数即频率。CCR1/CCR2就是占空比。 下面是pwm捕获模式下的配置: void Tim2_PWMIC_Init(void) { TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //***通道选择,通道一为从机TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿触发 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //管脚与寄存器对应关系TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入预分频。意思是控制在多少个输入周期做一次捕获,如果 //输入的信号频率没有变,测得的周期也不会变。比如选择4分频,则每四个输入周期才做一次捕获,这样在输入信号变化不频繁的情况下, //可以减少软件被不断中断的次数。 TIM_ICInitStructure.TIM_ICFilter = 0x0; //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF TIM_PWMIConfig(TIM2, &TIM_ICInitStructure); //根据参数配置TIM外设信息TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //选择IC2为始终触发源 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//TIM从模式:触发信号的上升沿重新初始化计数器和触发寄存器的更新事件 TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //启动定时器的被动触发 TIM_Cmd(TIM2,ENABLE); //启动TIM2 TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); //打开中断 } //中断服务函数

STM32学习笔记之二_中断

STM32中中断的理解 一、什么是中断 中断是指在计算机执行程序的过程中,当出现异常情况或者特殊请求时,计算机停止现行的程序的运行,转而对这些异常处理或者特殊请求的处理,处理结束后再返回到现行程序的中断处,继续执行原程序。 中断处理过程: (1)保护被中断进程现场。为了在中断处理结束后能够使进程准确地返回到中断点,系统必须保存当前处理机程序状态字PSW和程序计数器PC等的值。 (2)分析中断原因,转去执行相应的中断处理程序。在多个中断请求同时发生时,处理优先级最高的中断源发出的中断请求。 (3)恢复被中断进程的现场,CPU继续执行原来被中断的进程。 二、什么是中断服务程序 处理中断事件的程序被称为中断服务程序。 三、什么是中断向量 中断向量就是中断服务程序的入口地址。 四、什么是中断向量号 中断号也叫中断类型号,或者中断请求号。 中断是指在CPU运行期间,被CPU内部或外部事件所打断、暂停当前程序的执行而转去执行一段特定的处理内部或外部时间程序的过程。外部设备进行I/O操作时,会随机产生中断请求信号。这个信号中会有特定的标志,使计算机能够判断是哪个设备提出中断请求,这个信号就叫做中断号。 五、什么是中断向量地址 中断向量地址就是内存中存放中断服务程序入口地址的地址。 六、什么是中断向量表 CPU是根据中断向量号获取中断向量值,即对应中断服务程序的入口地址值。因此为了让CPU由中断向量号查找到对应的中断向量,就需要在内存中建立一张查询表,即中断向量表。 七、STM32中中断发生时系统找到对应中断服务执行的过程 (1)根据中断设发生备确定对应的中断向量号。

(3)执行中断服务程序。 以ALIENTEK Mini STM32开发板范例代码中的定时器中断实验为例来说明。 (1)根据中断设发生备确定对应的中断向量号。 在main.c中: TIM3_Int_Init(4999,7199); 在timer.c中: void TIM3_Int_Init(u16 arr,u16 psc) { . . . NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断号 . . . } 在stm32f10x.h中: typedef enum IRQn { . . . TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ . . . } 根据以上三个文件可以确定,定时器TIM3对应的中断向量号为TIM3_IRQn,而TIM3_IRQn = 29,所以,定时器TIM3对应的中断向量号为29。

详细的STM32单片机学习笔记

详细的STM32单片机学习笔记 STM32单片机学习笔记 1、AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中21,意思是APB2接高速设备 2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h 专门控制外围器件的配置,也就是开关头文件的作用 3、HSE Osc(High Speed External Oscillator)高速外部晶振,一般为8MHz,HSI RC(High Speed InternalRC)高速内部RC,8MHz 4、LSE Osc(Low Speed External Oscillator)低速外部晶振,一般为32.768KHz,LSI RC (Low Speed InternalRC)低速内部晶振,大概为40KHz左右,提供看门狗时钟和自动唤醒单元时钟源 5、SYSCLK时钟源有三个来源:HSI RC、HSE OSC、PLL 6、MCO[2:0]可以提供4源不同的时钟同步信号,PA8 7、GPIO口貌似有两个反向串联的二极管用作钳位二极管。 8、总线矩阵采用轮换算法对系统总线和DMA进行仲裁 9、ICode总线,DCode总线、系统总线、DMA总线、总线矩阵、AHB/APB桥 10、在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟 11、数据字节以小端存储形式保存在存储器中 12、内存映射区分为8个大块,每个块为512MB 13、FLASH的一页为1K(小容量和中容量),大容量是2K。 14、系统存储区(SystemMemory)为ST公司出厂配置锁死,用户无法编辑,用于对FLASH 区域进行重新编程。所以我们烧写程序务必选择BOOT1 = 0,这样通过内嵌的自举程序对

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自学笔记

一、原子位操作: 原子位操作定义在文件中。令人感到奇怪的是位操作函数是对普通的内存地址进行操作的。原子位操作在多数情况下是对一个字长的内存访问,因而位号该位于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学习笔记

MDK不会让你直接在入口参数处设置一个简单的字,因为这样代码可读性太差 MDK一般把取值范围的宏定义放在判断有效性语句的上方,这样是为了方便大家查找 可以通过|(或)的方式同时初始化多个IO口。这样操作的前提是,他们的Mode和Speed 参数相同,因为Mode和Speed参数并不能一次定义多种 在stm32f10x.h看那些外设是挂载在那个总线之下 GPIO操作步骤为: 1)使能IO口时钟。调用函数为RCC_APB2PeriphClockCmd()。 2)初始化IO参数。调用函数GPIO_Init(); 3)操作IO。 按键一端接高电平时另一端接I/O口则I/O口设置为下拉输入,因为按键按下时I/O口变成高电平;反之接低电平时I/O口设置为上拉输入因为按键按下时I/O口状态为低电平 Config意为配置 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);这个函数的作用是对中断的优 先级进行分组,这个函数在系统中只能被调用一次,一旦分组确定就最好不要更改 当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的表示 由2个字节组成:0X0D和0X0A)的第一个字节0X0D时,计数器将不再增加,等待0X0A 的到来,而如果0X0A没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接 收到0X0A,则标记USART_RX_STA的第15位,这样完成一次接收,并等待该位被其他 程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过USART_REC_LEN的时候,则会丢弃前面的数据,重新接收。 USART初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,硬件数据流控制, 模式(收,发)。 ①串口时钟使能,GPIO时钟使能 ②串口复位 ③GPIO端口模式设置 ④串口参数初始化 ⑤初始化NVIC并且开启中断 ⑥使能串口 SysTick是系统滴答计时器 在EXTI_GetITStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而

STM32学习笔记(7):USART串口的使用

1.串口的基本概念 在STM32的参考手册中,串口被描述成通用同步异步收发器(USART),它提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互联网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。还可以使用DMA方式,实现高速数据通信。 USART通过3个引脚与其他设备连接在一起,任何USART双向通信至少需要2个引脚:接受数据输入(RX)和发送数据输出(TX)。 RX: 接受数据串行输入。通过过采样技术来区别数据和噪音,从而恢复数据。 TX: 发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。 2.串口的如何工作的 一般有两种方式:查询和中断。 (1)查询:串口程序不断地循环查询,看看当前有没有数据要它传送。如果有,就帮助传送(可以从PC到STM32板子,也可以从STM32板子到PC)。 (2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则意味着要它帮助传输数据——它就马上进行数据的传送。同样,可以从 PC到STM3板子,也可以从STM32板子到PC。 3.串口的硬件连接 我用的奋斗STM32 V3开发板拥有二路RS-232 接口,CPU 的PA9-US1-TX(P68)、PA10-US1-RX(P69)、PA9-US2-TX(P25)、PA10-US2-RX(P26)通过MAX3232 实现两路RS-232 接口,分别连接在XS5 和XS17 接口上。 USART1 在系统存储区启动模式下,将通过该口通过PC对板上的CPU进行ISP,该口也可作为普通串口功能使用,JP3,JP4 的短路冒拔去,将断开第二路的RS232通信,仅作为TTL 通信通道。 4.编程实例 我们要对串口进行操作,首先要将STM32的串口和CPU进行连接。在Windows操作系统中,有一个自带的系统软件叫“超级终端”。VISTA以上的操作系统去掉了这个软件,不过可以从XP的系统中,复制“hypertrm.dll”和“hypertrm.exe”到“windows/system32”文件夹下,然后双击运行hypertrm.exe,就可以看见超级终端的运行界面了。 运行超级终端以后,会弹出“连接描述”,输入名称和选择图标,这个地方随便写个什么名称都可以。然后弹出“连接到”设置,在“连接时使用”选择你自己PC和STM32连

单片机STM32学习笔记

推挽输出与开漏输出的区别 推挽输出:可以输出高,低电平,连接数字器件; 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内). 推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 要实现“线与”需要用OC(open collector)门电路.是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小,效率高。输出既可以向负载灌电流,也可以从负载抽取电流。 问题: 很多芯片的供电电压不一样,有3.3v和5.0v,需要把几种IC的不同口连接在一起,是不是直接连接就可以了?实际上系统是应用在I2C上面。 简答: 1、部分3.3V器件有5V兼容性,可以利用这种容性直接连接 2、应用电压转换器件,如TPS76733就是5V输入,转换成3.3V、1A输出。 开漏电路特点及应用 在电路设计时我们常常遇到开漏(open drain)和开集(open collector)的概念。所谓开漏电路概念中提到的“漏”就是指MOSFET的漏极。同理,开集电路中的“集”就是指三极管的集电极。开漏电路就是指以MOSFET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上拉电阻组成。如图1所示:

组成开漏形式的电路有以下几个特点: 1. 利用外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up ,MOSFET到GND。IC内部仅需很下的栅极驱动电流。如图1。 2. 可以将多个开漏输出的Pin,连接到一条线上。形成“与逻辑” 关系。如图1,当PIN_A、PIN_B、PIN_C任意一个变低后,开漏线上的逻辑就为0了。这也是I2C,SMBus等总线判断总线占用状态的原理。 3. 可以利用改变上拉电源的电压,改变传输电平。如图2, IC的逻辑电平由电源Vcc1决定,而输出高电平则由Vcc2决定。这样我们就可以用低电平逻辑控制输出高电平逻辑了。 4. 开漏Pin不连接外部的上拉电阻,则只能输出低电平(因此对于经典的51单片机的P0口而言,要想做输入输出功能必须加外部上拉电阻,否则无法输出高电平逻辑)。 5. 标准的开漏脚一般只有输出的能力。添加其它的判断电路,才能具备双向输入、输出的能力。

STM32-串口实验学习笔记

STM32-串口实验学习笔记 USART1_IRQHandler(void)函数:当串口1 发生了相应的中断,就会跳到改函数执行。这里设计了一个小小的接收协议(系统并未定义):通过这个函数,配合一个数组USART_RX_BUF[ ],一个接收状态寄存器USART_RX_STA 实现对串口的数据的接收管理。USART_RX_BUF[ ]最大值为64,也就是一次接收的数据最大不能超过64 字节。USART_RX_STA 是一个接收状态寄存器,其各位的定义如表所示: (注意:这个是作者设计的协议,怎样判断串口接收一组数据完毕?由于每次接收的数据长度不一样,少的就3 个8 位数据,多的时候有十多个,这个数据个数是不定的,且没规律的数据,有什么好的方法让它接收完整? 协议的设计思路如下: 当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF 中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(0X0D,0X0A)的第一个字节0X0D 时,标志位即第六位置1,计数器将不再增加,等待0X0A 的到来,而如果0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到0X0A,则标记USART_RX_STA 的第七位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过64 个了,则会丢弃前面的数据,重新接收。由于这个寄存器是作者定义,我们理解时可能容易迷糊,其实这个跟普通寄存器类似,只不过是作者定义了一个8 位数,规定了它每位的定义,前两位是两个个标志位,后六位用来计数,

STM32学习笔记(初学者快速入门

STM32学习笔记(初学者快速入门 STM32 学习笔记 从51 开始单片机玩了很长时间了有51PICAVR 等等早就想跟潮 流玩玩ARM 但一直没有开始原因-----不知道玩了ARM 可以做什么对我自 己而言如果为学习而学习肯定学不好然后cortex-m3 出来了据说这 东西可以替代单片机于是马上开始关注也在第一时间开始学习可惜一开始 就有点站错了队选错了型仍是对我自己而言我希望这种芯片应该是满大 街都是随便哪里都可以买得到但我选的第一种显然做不到为此大概浪费

了一年多时间吧现在回到对我来说是正确的道路上来啦边学边写点东西 这里写的是我的学习的过程显然很多时候会是不全面的不系统的感 悟式的甚至有时会是错误的有些做法会是不专业的那么为什么我还要写 呢这是一个有趣的问题它甚至涉及到博客为什么要存在的问题显然博客 里面的写的东西其正确性权威性大多没法和书比可为什么博客会存在呢 理由很多我非专家只说我的感慨 我们读武侠小说总会有一些创出独门功夫的宗师功夫极高然后他的弟 子则基本上无法超越他我在想这位宗师在创造他自己的独门功

夫时必然会 有很多的次的曲折弯路甚至失败会浪费他的很多时间而他教给弟子时 则已去掉了这些曲折和弯路当然更不会把失败教给弟子按理说效率应该更 高可是没用弟子大都不如师为什么呢也许知识本身并不是最重要的获 取知识的过程才是最重要的也许所谓的知识并不仅仅是一条条的结论而是 附带着很多说不清道不明的东西如植物的根一条主根上必带有大量的小小的 触须 闲话多了些就权当前言了下面准备开始 一条件的准备

我的习惯第一步是先搭建一个学习的平台原来学51PICAVR 时都 是想方设法自己做些工具实验板之类现在人懒了直接购买成品了 硬件电路板火牛板 软件有keil 和iar 可供选择网上的口水仗不少我选keil理由很简单 这个我熟目前要学的知识中软硬件我都不熟所以找一个我有点熟的东西 就很重要在我相当熟练之前肯定不会用到IAR如果真的有一天不得不用I AR 相信学起来也很容易因为这个时候硬件部分我肯定很熟了再加上有ke il 的基础所以应该很容易学会了

超详细的STM32单片机学习笔记汇总

超详细的STM32单片机学习笔记汇总 1、AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中2>1,意思是APB2接高速设备 2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h 专门控制外围器件的配置,也就是开关头文件的作用 3、HSE Osc(High Speed External Oscillator)高速外部晶振,一般为8MHz,HSI RC(High Speed InternalRC)高速内部RC,8MHz 4、LSE Osc(Low Speed External Oscillator)低速外部晶振,一般为32.768KHz,LSI RC (Low Speed InternalRC)低速内部晶振,大概为40KHz左右,提供看门狗时钟和自动唤醒单元时钟源 5、SYSCLK时钟源有三个来源:HSI RC、HSE OSC、PLL 6、MCO[2:0]可以提供4源不同的时钟同步信号,PA8 7、GPIO口貌似有两个反向串联的二极管用作钳位二极管。 8、总线矩阵采用轮换算法对系统总线和DMA进行仲裁 9、ICode总线,DCode总线、系统总线、DMA总线、总线矩阵、AHB/APB桥 10、在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟 11、数据字节以小端存储形式保存在存储器中 12、内存映射区分为8个大块,每个块为512MB 13、 FLASH的一页为1K(小容量和中容量),大容量是2K。 14、系统存储区(SystemMemory)为ST公司出厂配置锁死,用户无法编辑,用于对FLASH 区域进行重新编程。所以我们烧写程序务必选择BOOT1 = 0,这样通过内嵌的自举程序对FLASH进行烧写,比如中断向量表和代码 15、STM32核心电压为1.8V

STM32学习笔记(关于时钟)

STM32学习----时钟(转载) 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 HSE/LSE时钟源 ③、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使用。

相关主题
文本预览
相关文档 最新文档