1.延时函数移植
1.把文件放入工程文件夹的system 里面
2.添加c文件 ;
3.添加头文件
4..在主文件当中添加 头文件 #include "delay.h"
调用初始化函数 delay_init(168);
调用延时函数:delay_us(); delay_ms();
代码:
#include "stm32f4xx.h"
#include "delay.h"
int main(void)
{
delay_init(168);//时间初始化
while(1)//防止程序跑飞
{
delay_us(1);//微妙
delay_ms(1);//毫秒
}
}
5.还有一些 操作 (时间才能准确)
进去 stm32f4xx.h 搜寻 HSE_VALUE 改变值 (搜索 CTRL + F)
2. 中断的知识
抢占优先级 & 响应优先级区别:
1.高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
2.抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
3.抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
4.如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
中断优先级分组函数
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 在主函数中只调用一次 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分为两个组
注意:
一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。
外部中断:
STM32F4的每个IO都可以作为外部中断输入。 STM32F4的中断控制器支持22个外部中断/事件请求:
EXTI线0~15:对应外部IO口的输入中断。
EXTI线16:连接到PVD输出。
EXTI线17:连接到RTC闹钟事件。
EXTI线18:连接到USB OTG FS唤醒事件。
EXTI线19:连接到以太网唤醒事件。
EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。
EXTI线21:连接到RTC入侵和时间戳事件。
EXTI线22:连接到RTC唤醒事件。
代码:
void EXTI0_IRQHandler(void)//中断响应函数
{
delay_ms(10);
if(WK_UP==1)
{
BEEP=!BEEP;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
void EXTI2_IRQHandler(void)//中断响应函数
{
delay_ms(10);
if(KEY2==0)
{
LED0=!LED0;
}
EXTI_ClearITPendingBit(EXTI_Line2);
void EXTI3_IRQHandler(void)//中断响应函数
{
delay_ms(10);
if(KEY1==0)
{
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line3);
}
void EXTI4_IRQHandler(void)//中断响应函数
{
delay_ms(10);
if(KEY0==0)
{
LED0=!LED0;
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
void EXTIX_Init(void)//外部中断初始化
{
NVIC_InitTypeDef NVIC_InitStructure;//配置总中断
EXTI_InitTypeDef EXTI_InitStructure;//外部中断初始化函数
KEY_Init();//LED 灯的初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//配置时钟,配置中断功能时钟
//配置外部中断 // 引脚复用映射,配置引脚功能 PE2 3 4 配置成外部中断功能
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//这个是 PA 0
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//0 号 引脚 - 0号线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //下降沿触发中断功能
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//外部中断使能
EXTI_Init(&EXTI_InitStructure);//中断初始化函数 初始化配置
EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4; PE2 3 4
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发中断功能
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//外部中断使能
EXTI_Init(&EXTI_InitStructure);//中断初始化函数 初始化配置
//在总中断配置中选择 外部中断0 号引脚
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStructure);//初始化
//在总中断配置中选择 外部中断2 号引脚
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStructure);
//在总中断配置中选择 外部中断3 号引脚
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStructure);
//在总中断配置中选择 外部中断4 号引脚
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
NVIC_Init(&NVIC_InitStructure);
}
3.systick 定时器
1.什么是SysTick
1,系统节拍时钟(SysTick)是一个简单的系统时钟节拍计数器。通常用作嵌入式操作系统(uc/os-iii,Android)的系统节拍定时。
2.复杂的嵌入式系统设计中会考虑操作系(uc/os,FreeRTOS),普通的单片机程序一个主程序就能完成任务。当单片机程序设计中不需要操作系统时,SysTick通常作为普通定时器来使用。既简单,又方便。
3.systick是内核的一部分,不是外设。
1. Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
2. SysTick定时器被捆绑在NVIC中,用于产生SYSTICK中断(中断号:15)。
3. Systick中断的优先级也可以设置。
接下来我们看SysTick_Config函数什么时候返回1,什么时候返回0;
SysTick_Config函数返回0后就不会在执行if语句,执行下一条语句关闭定时器,然后执行一次定时器的回调函数SysTick_Handler();
初始化系统定时器,1S 内核触发 1000 次中断,说白了定时 1ms,能够成功
SysTick_Config(SystemCoreClock/1000);
初始化系统定时器,1S 内核触发 10 次中断,说白了定时 100ms,现象失败
SysTick_Config(SystemCoreClock/10);
初始化系统定时器,1S 内核触发 11 次中断,说白了定时 90.90ms,能够成功
SysTick_Config(SystemCoreClock/11);
总结:填写中断频率值不能小于11,否则定时时间不准确。
看不懂的列子:
//使用前,请先初始化:
//SysTick_Init();
static __IO uint32_t TimingDelay;//定义一个定时器
void Delay(__IO uint32_t nTime)//延时函数
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void SysTick_Handler(void)//在定时的时候自动运行这个代码 中断函数
{
if (TimingDelay != 0x00) //定时的数 不等于 0 就一直减
{
TimingDelay--;
}
}
int main(void)
{
//中断函数的执行时间 1 ms(SystemCoreClock / 1000)
if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms 初始化systick,时钟为HCLK, 并开启中断
{
while (1);
}
//上面是开启函数
while(1)
{
Delay(200);//利用 定时器 200ms
}
}