当前位置:首页 >> 信息与通信 >>

STM32各模块学习笔记


STM32 中断优先级和开关总中断 一,中断优先级: STM32(Cortex-M3)中的优先级概念 STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优 先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应, 即中

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

-------------------------------------------------------------------------------Cortex-M3 允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此 STM32 把指定中断优先级的寄存器位减少到 4 位,这 4 个寄存器位的分组方式如下: 第 0 组:所有 4 位用于指定响应优先级 第 1 组:最高 1 位用于指定抢占式优先级,最低 3 位用于指定响应优先级 第 2 组:最高 2 位用于指定抢占式优先级,最低 2 位用于指定响应优先级 第 3 组:最高 3 位用于指定抢占式优先级,最低 1 位用于指定响应优先级 第 4 组:所有 4 位用于指定抢占式优先级

可以通过调用 STM32 的固件库中的函数 NVIC_PriorityGroupConfig()选择使用哪种优先级分 组方式,这个函数的参数有下列 5 种: NVIC_PriorityGroup_0 => NVIC_PriorityGroup_1 => NVIC_PriorityGroup_2 => NVIC_PriorityGroup_3 => NVIC_PriorityGroup_4 => 选择第 0 组 选择第 1 组 选择第 2 组 选择第 3 组 选择第 4 组

接下来就是指定中断源的优先级, 下面以一个简单的例子说明如何指定中断源的抢占式优先 级和响应优先级: // 选择使用优先级分组第 1 组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 使能 EXTI0 中断 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别 1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别 0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能 EXTI9_5 中断 NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别 0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别 1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 要注意的几点是: 1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将 可能得到意想不到的结果; 2)抢占式优先级别相同的中断源之间没有嵌套关系; 3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优 先级别,则可以为这个中断源指定任意有效的响应优先级别。 二,开关总中断: 在 STM32/Cortex-M3 中是通过改变 CPU 的当前优先级来允许或禁止中断。

PRIMASK 位: 只允许 NMI 和 hard fault 异常, 其他中断/异常都被屏蔽(当前 CPU 优先级=0)。 FAULTMASK 位:只允许 NMI,其他所有中断/异常都被屏蔽(当前 CPU 优先级=-1)。 在 STM32 固件库中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定义了四个函数操作 PRIMASK 位和 FAULTMASK 位,改变 CPU 的当前优先级,从而达到控制所有中断的目的。 下面两个函数等效于关闭总中断: void NVIC_SETPRIMASK(void); void NVIC_SETFAULTMASK(void); 下面两个函数等效于开放总中断: void NVIC_RESETPRIMASK(void); void NVIC_RESETFAULTMASK(void); 上面两组函数要成对使用,不能交叉使用。 例如: 第一种方法: NVIC_SETPRIMASK(); //关闭总中断 NVIC_RESETPRIMASK();//开放总中断 第二种方法: NVIC_SETFAULTMASK(); //关闭总中断 NVIC_RESETFAULTMASK();//开放总中断 常常使用 NVIC_SETPRIMASK(); NVIC_RESETPRIMASK(); // Disable Interrupts // Enable Interrupts

STM32 时钟系统 STM32 资料 2009-09-23 14:53 阅读 72 评论 0 字号: 大大 中中 小小 在 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。

图 1 HSE/LSE 时钟源 其中 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 外部中断之二 STM32 资料 2009-09-10 21:18 字号: 大大 中中 小小 STM32 外部中断配置 阅读 243 评论 0

1 配置中断 1、 分配中断向量表: /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 2、 设置中断优先级: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置中断优先级 3、 初始化外部中断: /*允许 EXTI4 中断 */

NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; //中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;// 强占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //次优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能 NVIC_Init(&NVIC_InitStructure); //初始化中断

注意:如果我们配置的外部针脚为 PA4,或 PB4,或 PC4,PD4 等,那么采用的外部中断也 必须是 EXTI4,同样,如果外部中断针脚是 PA1,PB1,PC1,PD1 那么中断就要用 EXTI1, 其他类推。 2 配置 GPIO 针脚作为外部中断的触发事件 1、 选择 IO 针脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 注意,如果的针脚是端口的 4 号针脚,配置的中断一定是 EXTI4 2、 配置针脚为输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 3、 初始化针脚 GPIO_Init(GPIOD,&GPIO_InitStructure);

3 配置 EXTI 线,使中断线和 IO 针脚线连接上 1、 将 EXTI 线连接到 IO 端口上 将 EXTI 线 4 连接到端口 GPIOD 的第 4 个针脚上 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4); 注意:如果配置的针脚是 4 号,那么参数必须是 GPIO_PinSource4 如果配置的针脚是 3 号,那么参数必须是 GPIO_PinSource3

2、配置中断边沿 /*配置 EXTI 线 0 上出现下降沿,则产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line4; 注意:如果配置的 4 号针脚,那么 EXTI_Line4 是必须的 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_GenerateSWInterrupt(EXTI_Line4); 到此中断配置完成,可以写中断处理函数。 举例: 配置函数 /************************************************************************* * 函数名 * 描述 * 输入 * 输出 * 返回值 NVIC_Configration 配置各个中断寄存器 无 无 无 //中断线使能 //初始化中断 //EXTI_Line4 中断允许

****************************************************************************/ void NVIC_Configration(void) { NVIC_InitTypeDef NVIC_InitStructure;

//#ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //#else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ //NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //#endif NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置中断优先级 /*允许 EXTI4 中断 */ NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*允许 EXTI9 中断*/ NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*配置 SysTick 处理优先级:优先级以及子优先级*/

} /************************************************************************ * 函数名 * 描述 * 输入 * 输出 * 返回 :无 :无 :GPIO_Configuration(void) :配置 TIM2 阵脚 :无

************************************************************************/ void GPIO_Configuration(void){ /* GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOC,&GPIO_InitStructure); /*配置 GPIOD 的第一个管角为浮动输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOD,&GPIO_InitStructure);

/*配置 GPIOB 的第 9 个管脚为浮动输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStructure); }

/************************************************************** * 函数 * 描述 * 输入 * 输出 * 返回值 无 SysTick_Configuration 设置 SysTick 无 无

***************************************************************/ void SysTick_Configuration(void) { /*配置 HCLK 时钟做为 SysTick 时钟源*/ SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // 系 统 时 钟 8 分 频 72MHz NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 8,2); /*SysTick Interrupt each 1000Hz with HCLK equal to 72MHz*/ SysTick_SetReload(9000);//中断周期 1ms /*Enable the SysTick Interrupt */ SysTick_ITConfig(ENABLE);//打开中断

SysTick_CounterCmd(SysTick_Counter_Enable); SysTick_CounterCmd(SysTick_Counter_Clear); }

/****************************************************************************** * 函数名 * 描述 * 输入 * 输出 * 返回值 EXTI_Configuration 配置 EXTI 线 无 无 无

******************************************************************************/ void EXTI_Configuration(void){ /*将 EXTI 线 0 连接到 PA0*/ GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4); /*配置 EXTI 线 0 上出现下降沿,则产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_GenerateSWInterrupt(EXTI_Line4);

/*将 EXTI 线 9 连接到 PB9 上*/ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9); /*将 EXTI 线 9 上出现下降沿产生中断*/ EXTI_InitStructure.EXTI_Line = EXTI_Line9; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_GenerateSWInterrupt(EXTI_Line9); } 中断函数: void EXTI4_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line4)!= RESET){ EXTI_ClearITPendingBit(EXTI_Line4); if(Ledflag == 0){ Ledflag = 1; GPIOC->ODR |= 0X00000080; } else{ Ledflag = 0; GPIOC->ODR &= 0XFFFFFF7F;

} } } 注:时钟设置的时候最好加上这句: RCCRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能 AFIO 时钟

STM32 中定时器的时钟源 STM32 资料 2009-07-24 21:34 字号: 大大 中中 小小 阅读 277 评论 0

STM32 中有多达 8 个定时器, 其中 TIM1 和 TIM8 是能够产生三对 PWM 互补输出的高级定 时器,常用于三相电机的驱动,它们的时钟由 APB2 的输出产生。其它 6 个为普通定时器, 时钟由 APB1 的输出产生。 下图是 STM32 参考手册上时钟分配图中,有关定时器时钟部分的截图:

从图中可以看出,定时器的时钟不是直接来自 APB1 或 APB2,而是来自于输入为 APB1 或 APB2 的一个倍频器,图中的蓝色部分。 下面以定时器 2~7 的时钟说明这个倍频器的作用: APB1 的预分频系数为 1 时, 当 这个倍频 器不起作用,定时器的时钟频率等于 APB1 的频率;当 APB1 的预分频系数为其它数值(即 预分频系数为 2、4、8 或 16)时,这个倍频器起作用,定时器的时钟频率等于 APB1 的频率 两倍。 假定 AHB=36MHz,因为 APB1 允许的最大频率为 36MHz,所以 APB1 的预分频系数可以 取任意数值;当预分频系数=1 时,APB1=36MHz,TIM2~7 的时钟频率=36MHz(倍频器不起 作用); 当预分频系数=2 时, APB1=18MHz, 在倍频器的作用下, TIM2~7 的时钟频率=36MHz。 有人会问, 既然需要 TIM2~7 的时钟频率=36MHz, 为什么不直接取 APB1 的预分频系数=1? 答案是:APB1 不但要为 TIM2~7 提供时钟,而且还要为其它外设提供时钟;设置这个倍频 器可以在保证其它外设使用较低时钟频率时,TIM2~7 仍能得到较高的时钟频率。

再举个例子:当 AHB=72MHz 时,APB1 的预分频系数必须大于 2,因为 APB1 的最大频率 只能为 36MHz。如果 APB1 的预分频系数=2,则因为这个倍频器,TIM2~7 仍然能够得到 72MHz 的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设 计这个倍频器的初衷。 STM32 笔记之外部中断 GPIO STM32 资料 2009-07-14 13:35 阅读 331 评论 0 字号: 大大 中中 小小 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_InitStructure.EXTI_LineCmd = ENABLE;//启动中断 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 开中断、编写中断执行代码。 STM32 的 USART STM32 资料 2009-07-14 13:33 阅读 489 评论 4 字号: 大大 中中 小小 b) 初始化函数定义: void USART_Configuration(void); //定义串口初始化函数 c) 初始化函数调用: void UART_Configuration(void); //串口初始化函数调用 初始化代码: void USART_Configuration(void) //串口初始化函数 { //串口参数初始化 USART_InitTypeDef USART_InitStructure; //串口设置恢复默认参数 //初始化参数设置 USART_InitStructure.USART_BaudRate = //波特率 9600 USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; 字节 USART_InitStructure.USART_Parity = USART_Parity_No; 偶校验

9600; //字长 8 位 //1 位停止 //无奇

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打开 Rx 接收 和 Tx 发送功能 USART_Init(USART1, //初始化 USART_Cmd(USART1, //启动串口 } RCC 中打开相应串口 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); GPIO 里面设定相应串口管脚模式 //串口 1 的管脚初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); &USART_InitStructure); ENABLE);

//管脚 9 //复用推挽输出 //TX 初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //管脚 10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //RX 初始化 d) 简单应用: 发送一位字符 USART_SendData(USART1, 数据); while(USART_GetFlagStatus(USART1, //等待发送完毕 接收一位字符 while(USART_GetFlagStatus(USART1, //等待接收完毕 变量= (USART_ReceiveData(USART1));

//发送一位数据 USART_FLAG_TXE)

==

RESET){}

USART_FLAG_RXNE) //接受一个字节

==

RESET){}

发送一个字符串 先定义字符串: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 函数 { if (c == '\n'){putchar('\r');} //将 printf 的\n 变成\r 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 RXNE 接收中断,PE 奇偶错误中断,可以是多个。 ii. RCC、GPIO 里面打开串口相应的基本时钟、管脚设置 iii. NVIC 里面加入串口中断打开代码: NVIC_InitTypeDef NVIC_InitStructure;//中断默认参数 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道设置为串口 1 中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 初始化

//中断占先等级 0 //中断响应优先级 0 //打开中断 //

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); //开始传输 RX_dat=USART_ReceiveData(USART1) & 0x7F; //接收数据, 整理除去前两位 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+ 定义代码再次定义就可以直接调用了。 STM32 运行的必要硬件库 STM32 资料 2009-07-14 13:31 阅读 163 评论 0 字号: 大大 中中 小小 0、 实验之前的准备 a) 接通串口转接器 b) 下载 IO 与串口的原厂程序,编译通过保证调试所需硬件正常。 1、 a) flash,lib,nvic,rcc 和 GPIO,基础程序库编写 这几个库函数中有一些函数是关于芯片的初始化的,每个程序中必用。为保障程

序品质,初学阶段要求严格遵守官方习惯。注意,官方程序库例程中有个 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 输入(50MHz,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--);} 基于 STM32 的 PWM 输出 STM32 资料 2009-07-14 13:30 字号: 大大 中中 小小 阅读 449 评论 2

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_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, //启动 TIM3 }

TIM_OCInitStructure); //工作 //设定为输出, //占空长 //高电 //通道

ENABLE);

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 则应该将相应管脚设 为 AF_PP,否则单片机没有输出。 STM32 资料一(转载) STM32 资料 2009-06-14 20:15 字号: 大大 中中 小小 阅读 766 评论 1

注:下面是一些常用的代码,网上很多但是大多注释不全。高手看没问题,对于我们这些新 手就费劲了……所以我把这些代码集中,进行了逐句注释,希望对新手们有价值。 阅读 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,中断的初始化函数,包括设置中断向量表位置,和开启所需的中断两部分。所 有程序中必须的。 用法: { NVIC_InitTypeDef NVIC_InitStructure; //中断管理恢复默认参数 void NVIC_Configuration(void)

#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); RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK2Config(RCC_HCLK_Div2); HCLK 的一半 RCC_PCLK1Config(RCC_HCLK_Div2); HCLK 的一半 //flash 操作的延时 //AHB 使用系统时钟 //APB2 (高速) 为 //等待外部晶振就绪 //打开外部晶

//APB1 (低速) 为

//注:AHB 主要负责外部存储器时钟。PB2 负责 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 MH 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 //全局变量声明 void //systick 初始化函数 { SysTick_CounterCmd(SysTick_Counter_Disable); //停止系统定时器 SysTick_ITConfig(DISABLE); //停止 systick 中断 //systick 使 用 vu32 TimingDelay;

SysTick_Config(void)

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); HCLK 作为时钟源,频率值除以 8。 SysTick_SetReload(9000); //重置时间 1 毫秒(以 72MHz 为基础计算) SysTick_ITConfig(ENABLE); //开启 systic 中断 } void //延迟一毫秒的函数 { SysTick_CounterCmd(SysTick_Counter_Enable); 开始计时 TimingDelay = nTime; 给递减变量 while(TimingDelay != 0); SysTick_CounterCmd(SysTick_Counter_Disable); Delay (u32

nTime)

//systic

//计时长度赋值

//检测是否计时完成

//关闭计数器 SysTick_CounterCmd(SysTick_Counter_Clear); 数值 } void TimingDelay_Decrement(void) 应函数定义好了。 { if (TimingDelay != 0x00) { TimingDelay--; } } 注:建议熟练后使用,所涉及知识和设备太多,新手出错的可能性比较大。新手可用简化的 延时函数代替: void //简单延时函数 { for(; //循环变量递减计数 } 当延时较长,又不需要精确计时的时候可以使用嵌套循环: void Delay(vu32 nCount) 延时函数 {int i; for(; //递减变量计数 {for nCount != //简单的长时间 nCount != 0; nCount--); Delay(vu32 nCount) //检测计数变量是否达到 0 //计数变量递减 //递减变量函数,函数名由“stm32f10x_it.c”中的中断响 //清除计

//声明内部递减变量 0; nCount--)

(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); 基础应用 3,从管脚读入 0 或 1 用法:GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) //写入 1

STM32 笔记之七:让它跑起来,基本硬件功能的建立 0、 a) b) 1、 实验之前的准备 接通串口转接器 下载 IO 与串口的原厂程序,编译通过保证调试所需硬件正常。 flash,lib,nvic,rcc 和 GPIO,基础程序库编写

a) 这几个库函数中有一些函数是关于芯片的初始化的,每个程序中必用。为保障程 序品质,初学阶段要求严格遵守官方习惯。注意,官方程序库例程中有个 platform_config.h 文件,是专门用来指定同类外设中第几号外设被使用,就是说在 main.c 里面所有外设序号 用 x 代替,比如 USARTx,程序会到这个头文件中去查找到底是用那些外设,初学的时候参 考例程别被这个所迷惑住。 b) c) d) 全部必用代码取自库函数所带例程,并增加逐句注释。 习惯顺序——Lib(debug) ,RCC(包括 Flash 优化) ,NVIC,GPIO 必用模块初始化函数的定义: //定义时钟初始化函数 //定义管脚初始化函数 //定义中断管理初始化函数 //定义延迟函数

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 输入(50MHz,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_GPIOA | 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 闪烁了,单片机就跑起来了。 STM32 笔记之八:来跟 PC 打个招呼,基本串口通讯 a) 目的:在基础实验成功的基础上,对串口的调试方法进行实践。硬件代码顺利完 成之后,对日后调试需要用到的 printf 重定义进行调试,固定在自己的库函数中。 b) 初始化函数定义: //定义串口初始化函数

void USART_Configuration(void); c) 初始化函数调用:

void UART_Configuration(void); 初始化代码:

//串口初始化函数调用

void USART_Configuration(void) { //串口参数初始化 USART_InitTypeDef USART_InitStructure; //初始化参数设置 USART_InitStructure.USART_BaudRate //波特率 9600

//串口初始化函数

//串口设置恢复默认参数

=

9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; 字节 USART_InitStructure.USART_Parity = USART_Parity_No; 偶校验 USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;//无流控制

//字长 8 位 //1 位停止

//无奇

=

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//打开 Rx 接收 和 Tx 发送功能 USART_Init(USART1, //初始化 USART_Cmd(USART1, //启动串口 } RCC 中打开相应串口 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); GPIO 里面设定相应串口管脚模式 //串口 1 的管脚初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //管脚 9 &USART_InitStructure);

ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

//复用推挽输出 //TX 初始化 //管脚 10

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); d) 简单应用: //RX 初始化

发送一位字符 USART_SendData(USART1, 数据); while(USART_GetFlagStatus(USART1, //等待发送完毕 接收一位字符 while(USART_GetFlagStatus(USART1, //等待接收完毕 变量= (USART_ReceiveData(USART1)); 发送一个字符串 先定义字符串:char rx_data[250]; 然后在需要发送的地方添加如下代码 int i; 义循环变量 while(rx_data!='\0') 结束字'\0' {USART_SendData(USART1, rx_data); //发送字符 //定 USART_FLAG_RXNE) == RESET){} //发送一位数据 USART_FLAG_TXE) == RESET){}

//接受一个字节

//循环逐字输出, 到

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) (1) printf 函数重定义(不必理解,调试通过以备后用) 需要 c 标准函数:

#include "stdio.h" (2) 粘贴函数定义代码

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) //定义为 putchar 应用 (3) (4) (6) RCC 中打开相应串口 GPIO 里面设定相应串口管脚模式 增加为 putchar 函数。 //putchar 函数

int putchar(int c) { if (c == '\n'){putchar('\r');} USART_SendData(USART1, c);

//将 printf 的\n 变成\r //发送字符

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 RXNE 接收中断,PE 奇偶错误中断,可以是多个。 ii. iii. RCC、GPIO 里面打开串口相应的基本时钟、管脚设置 NVIC 里面加入串口中断打开代码:

NVIC_InitTypeDef NVIC_InitStructure;//中断默认参数 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;//通道设置为串口 1 中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 初始化 //中断占先等级 0 //中断响应优先级 0 //打开中断 //

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

变量 if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断发生接收中断 {USART_ClearITPendingBit(USART1, USART_IT_RXNE); GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)0x01); RX_dat=USART_ReceiveData(USART1) & 0x7F; 整理除去前两位 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+ 定义代码再次定义就可以直接调用了。 STM32 笔记之九:打断它来为我办事,EXIT (外部 I/O 中断)应用 a) 目的:跟串口输入类似,不使用中断进行的 IO 输入效率也很低,而且可以通过 EXTI 插入按钮事件,本节联系 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_InitStructure.EXTI_LineCmd = ENABLE;//启动中断 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) 断中断发生来源 { //清除中断标志 USART_SendData(USART1, //发送字符“a” GPIO_WriteBit(GPIOB, GPIO_Pin_2, GPIO_Pin_2)));//LED 发生明暗交替 } h) 中断注意事项: //判

EXTI_ClearITPendingBit(EXTI_Line3);

0x41);

(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,

中断发生后必须清除中断位, 否则会出现死循环不断发生这个中断。 然后需要对中断类型进 行判断再执行代码。 使用 EXTI 的 I/O 中断,在完成 RCC 与 GPIO 硬件设置之后需要做三件事:初始化 EXTI、 NVIC 开中断、编写中断执行代码。 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; TIM_TimeBaseStructure.TIM_Prescaler = 5; TIM_TimeBaseStructure.TIM_ClockDivision = 0; //周期 0~FFFF //时钟分频 //时钟分割

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_OCMode = TIM_OCMode_PWM1; 状态 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 需要 PWM 输出才需要这行代码 TIM_OCInitStructure);

//工作

//设定为输出,

TIM_OCInitStructure.TIM_Pulse = 0x2000; 度 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 平 TIM_OC4Init(TIM3, &TIM_OCInitStructure); 初始化 TIM_Cmd(TIM3, //启动 TIM3 } f) RCC 初始化函数中加入 TIM 时钟开启:

//占空长

//高电

//通道

ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3, ENABLE); g) h) GPIO 里面将输入和输出管脚模式进行设置。信号:AF_PP,50MHz。 使用中断的话在 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 则应该将相应管脚设 为 AF_PP,否则单片机没有输出 我的测试程序可以发出不断循环三种波长并捕获,对比结果如下: 捕捉的稳定性很好,也就是说,同样的方波捕捉到数值相差在一两个数值。 捕捉的精度跟你设置的滤波器长度有关,在这里 TIM_ICInitStructure.TIM_ICFilter = 0x4; 定 0x0~0xF //滤波设置,经历几个周期跳变认定波形稳

这个越长就会捕捉数值越小,但是偏差几十个数值,下面是 0、4、16 个周期滤波的比较, out 是输出的数值,in 是捕捉到的。 现在有两个疑问: 1、在 TIM2 的捕捉输入通道初始化里面这句 TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); //选择时钟触发源

按照硬件框图,4 通道应该对应 TI4FP4。可是实际使用 TI1FP1,TI2FP2 都行,其他均编译 错误未注册。这是为什么?

2、关闭调试器和 IAR 程序,直接供电跑出来的结果第一个周期很正常,当输出脉宽第二次 循环变小后捕捉的数值就差的远了。不知道是为什么 STM32 笔记之十二:时钟不息工作不止,systic 时钟应用 a) b) 目的:使用系统时钟来进行两项实验——周期执行代码与精确定时延迟。 初始化函数定义:

void SysTick_Configuration(void); c) 初始化函数调用:

SysTick_Configuration(); d) 初始化函数:

void SysTick_Configuration(void) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//时钟除 8 SysTick_SetReload(250000); 计数周期长度 SysTick_CounterCmd(SysTick_Counter_Enable); SysTick_ITConfig(ENABLE); //打开中断 } e) 在 NVIC 的初始化函数里面增加以下代码打开相关中断: //启动计时器 //

NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 1, 0);//中断等级设置,一般设置 的高一些会少受其他影响 f) 在 stm32f10x_it.c 文件中找到 void SysTickHandler 函数

void SysTickHandler(void) {

执行代码 } g) 简单应用:精确延迟函数,因为 systic 中断往往被用来执行周期循环代码,所以 一些例程中使用其中断的启动和禁止来编写的精确延时函数实际上不实用, 我自己编写了精 确计时函数反而代码更精简,思路更简单。思路是调用后,变量清零,然后使用时钟来的曾 变量,不断比较变量与延迟的数值,相等则退出函数。代码和步骤如下: i. ii. 定义通用变量:u16 Tic_Val=0; //变量用于精确计时 在 stm32f10x_it.c 文件中相应定义:

extern u16 Tic_Val;//在本文件引用 MAIN.c 定义的精确计时变量 iii. iv. 定义函数名称:void Tic_Delay(u16 Tic_Count);//精确延迟函数 精确延时函数: //精确延时函数 //变量清零

void Tic_Delay(u16 Tic_Count) { Tic_Val=0; while(Tic_Val != Tic_Count){printf("");}//计时 } v.

在 stm32f10x_it.c 文件中 void SysTickHandler 函数里面添加 Tic_Val++;//变量递增

vi. vii.

调用代码:Tic_Delay(10);

//精确延时

疑问:如果去掉计时行那个没用的 printf("");函数将停止工作,这个现象很奇怪

C 语言功底问题。是的,那个“注意事项”最后的疑问的原因就是这个 Tic_Val 应该改为 vu16 while(Tic_Val != Tic_Count){printf("");}//计时 就可以改为: while(Tic_Val != Tic_Count); //检查变量是否计数到位

STM32 笔记之十三:恶搞,两只看门狗 a) 目的:

了解两种看门狗(我叫它:系统运行故障探测器和独立系统故障探测器,新手往往被这个并 不形象的象形名称搞糊涂)之间的区别和基本用法。 b) 相同:

都是用来探测系统故障, 通过编写代码定时发送故障清零信号 (高手们都管这个代码叫做“喂 狗”) ,告诉它系统运行正常。一旦系统故障,程序清零代码(“喂狗”)无法执行,其计数器 就会计数不止, 直到记到零并发生故障中断 (狗饿了开始叫唤) 控制 CPU 重启整个系统 , (不 行啦,开始咬人了,快跑……) 。 c) 区别:

独立看门狗 Iwdg——我的理解是独立于系统之外,因为有独立时钟,所以不受系统影响的 系统故障探测器。 (这条狗是借来的,见谁偷懒它都咬! )主要用于监视硬件错误。 窗口看门狗 wwdg——我的理解是系统内部的故障探测器,时钟与系统相同。如果系统时钟 不走了,这个狗也就失去作用了。 (这条狗是老板娘养的,老板不干活儿他不管! )主要用于 监视软件错误。 d) 初始化函数定义:鉴于两只狗作用差不多,使用过程也差不多初始化函数栓一起 了,用的时候根据情况删减。 void WDG_Configuration(void); e) 初始化函数调用:

WDG_Configuration(); f) 初始化函数 //看门狗初始化

void WDG_Configuration() { //软件看门狗初始化

WWDG_SetPrescaler(WWDG_Prescaler_8); //时钟 8 分频 4ms // (PCLK1/4096)/8= 244 Hz (~4 ms)

WWDG_SetWindowValue(65); WWDG_Enable(127); // WWDG timeout = ~4 ms * 64 = 262 ms WWDG_ClearFlag(); WWDG_EnableIT(); //独立看门狗初始化

//计数器数值 //启动计数器,设置喂狗时间

//清除标志位 //启动中断

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//启动寄存器读写 IWDG_SetPrescaler(IWDG_Prescaler_32);//40K 时钟 32 分频 IWDG_SetReload(349); IWDG_ReloadCounter(); IWDG_Enable(); } g) RCC 初始化:只有软件看门狗需要时钟初始化,独立看门狗有自己的时钟不需 要但是需要 systic 工作相关设置。 RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); h) 独立看门狗使用 systic 的中断来喂狗,所以添加 systic 的中断打开代码就行了。 软件看门狗需要在 NVIC 打开中断添加如下代码: NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQChannel; //通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //占先中断等级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); //响应中断优先级 //打开中断 //计数器数值 //重启计数器 //启动看门狗

i) 中断程序,软件看门狗在自己的中断中喂狗,独立看门狗需要使用 systic 的定时 中断来喂狗。以下两个程序都在 stm32f10x_it.c 文件中。

void WWDG_IRQHandler(void) { WWDG_SetCounter(0x7F); WWDG_ClearFlag(); } void SysTickHandler(void) { IWDG_ReloadCounter(); } j) i. ii. 注意事项: 有狗平常没事情可以不理,但是千万别忘了喂它,否则死都不知道怎么死的! 初始化程序的调用一定要在 systic 的初始化之后。 //重启计数器(喂狗) //更新计数值 //清除标志位

iii. 独立看门狗需要 systic 中断来喂,但是 systic 做别的用处不能只做这件事,所以 我写了如下几句代码,可以不影响 systic 的其他应用,其他 systic 周期代码也可参考: 第一步:在 stm32f10x_it.c 中定义变量 int Tic_IWDG; //喂狗循环程序的频率判断变量

第二步:将 SysTickHandler 中喂狗代码改为下面: Tic_IWDG++; if(Tic_IWDG>=100) //变量递增 //每 100 个 systic 周期喂狗

{ IWDG_ReloadCounter();//重启计数器(喂狗) Tic_IWDG=0; } //变量清零


相关文章:
STM32各模块学习笔记
STM32各模块学习笔记_信息与通信_工程科技_专业资料。系统介绍STM32各模块的功能和应用,通俗易懂。STM32 中断优先级和开关总中断 一,中断优先级: STM32(Cortex-...
学习STM32笔记汇总
学习STM32笔记汇总_电子/电路_工程科技_专业资料。STM32F207 学习笔记 1、 使用...(可见, 工程建立时, 这些源码的路径指定 usr)②example 各个模块的标准例程 3...
STM32学习笔记
STM32各模块学习笔记 46页 1下载券 STM32学习笔记:外部中断... 8页 2下载券...一、 本课内容概述这一课的主要内容是 STM32 系统时钟定时器 systick 的配置...
STM32学习笔记
STM32各模块学习笔记 46页 1下载券 STM32学习笔记:外部中断... 8页 2下载券...25 00 STM32 学习笔记-基本硬件 拉电流/灌电流: 最大可以输出 8mA, 灌入 ...
stm32学习笔记(狼牙整理)
学习stm32 的笔记了,写的比较乱,不过比较详细,有兴趣的朋友一起学习啦,共同...STM32各模块学习笔记 46页 5下载券 STM32学习笔记 32页 1下载券 sw...
STM32学习笔记小结
12 1 STM32 学习笔记 一、入门 STM32 系列基于专为要求高性能、低成本、低...STM32各模块学习笔记 46页 5下载券 STM32学习笔记一 环境配... 14页 1下载...
STM32学习笔记
STM32学习笔记_IT/计算机_专业资料。野火硬件学习笔记 STM32 学习 一、初识库(...(特别是读速度)要比对 SD 卡的快,而且成本低; 2、 SPI 总线模块可存汉字...
STM32学习笔记
STM32学习笔记_计算机硬件及网络_IT/计算机_专业资料。STM32 单片机 ARM ...(参数);) 4、改写程序库里面所预设的模板,再进行其他模块的初始化子程序代码...
STM32学习笔记
u32 Bound, BRR; RCC_Configuration(); GPIO_Configuration(); USART1->CR1 ...STM32各模块学习笔记 48页 2下载券 STM32学习笔记(3):系统... 11页 1...
STM32学习笔记 原创
STM32学习笔记 原创_计算机硬件及网络_IT/计算机_专业资料。自己在学习野火STM32...STM32各模块学习笔记 46页 1下载券 自己整理STM32学习笔记(... 13页 1下载...
更多相关标签: