stm32单片机入门基础知识——延时、滴答计时器、外部中断、定时器中断

自学单片机有一段时间了,因为概念不清走了不少弯路,现在整理一些基础知识,供大家参考,有错误欢迎指正。

1.延时、滴答计时器

我们经常在程序里看到一些延时函数,延时函数一般分为三种:普通延时函数、SysTick 定时器延时中断方式、SysTick 定时器延时非中断方式,其实都是一些固定的程序代码,这里直接粘贴,不过多叙述。

普通延时:粗略的延时

//微秒级的延时

void delay_us(u16 time)
{    
   u16 i=0;  
   while(time--)
   {
      i=10;  //自己定义
      while(i--) ;    
   }
}
//毫秒级的延时
void delay_ms(u16 time)
{    
   u16 i=0;  
   while(time--)
   {
      i=12000;  //自己定义
      while(i--) ;    
   }
}

//秒级的延时

void Delay(__IO uint32_t nCount)

{

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

}

 Delay(0xffffee); 

精准延时:SysTick 定时器延时——不进入SysTick中断

void delay_us(u32 nus)
{
 u32 temp;
 SysTick->LOAD = 9*nus;
 SysTick->VAL=0X00;//清空计数器
 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
     SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
 u32 temp;
 SysTick->LOAD = 9000*nms;
 SysTick->VAL=0X00;//清空计数器
 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
 do
 {
  temp=SysTick->CTRL;//读取当前倒计数值
 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}

2.外部中断

每个工程只能有一种分组方式:

按NVIC_PriorityGroup_0来分组:抢占优先级为1个,子优先级为16个;

按NVIC_PriorityGroup_1来分组:抢占优先级为2个,子优先级为8个;

按NVIC_PriorityGroup_2来分组:抢占优先级为4个,子优先级为4个;

按NVIC_PriorityGroup_3来分组:抢占优先级为8个,子优先级为2个;

按NVIC_PriorityGroup_4来分组:抢占优先级为16个,子优先级为1个;

抢占优先级高的中断可以打断抢占优先级低的中断;抢占优先级相同时比较响应优先级(子优先级)。

先设定分组方式

例:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);    //按NVIC_PriorityGroup_4来分组

此时,有一中断EXTI0_IRQChannel,你指定他为抢占优先级8,则
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8; // 指定抢占式优先级别,可取0-15

又有1中断SPI1_IRQChannel,设定如下
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别,可取0-15

SPI1_IRQChannel的抢占优先级高,EXTI0_IRQChannel做事的时候可以打断(嵌套)

 

又:若分组方式为:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);    //按NVIC_PriorityGroup_3来分组

此时就有8个抢占优先级,2个子优先级;

EXTI0_IRQChannel中断,你指定他为抢占优先级3,则:
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 指定抢占式优先级别,可取0-7
还需要指定他的阶层:
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别,可取0-1

又有TIM2_IRQn中断,设定如下:

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 指定抢占式优先级别,可取0-7

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 指定响应优先级别,可取0-1

由于抢占优先级相同,响应优先级EXTI0_IRQChannel中断高于TIM2_IRQn中断,所以EXTI0_IRQChannel可以打断TIM2_IRQn;

还有一USB_LP_CAN1_RX0_IRQn,设定如下:

NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;   //CAN1 RX0中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   //响应优先级别0,可取0-1

USB_LP_CAN1_RX0_IRQn优先级最高,前两中断发生时,它都可以打断。

附:

void NVIC_Config(void)

{       

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);//一个工程中只能使用一种分组方式
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //CAN1 RX0中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 指定抢占式优先级别,可取0-7
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 指定响应优先级别,可取0-1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 指定抢占式优先级别,可取0-7
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别,可取0-1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

}

 

你可能感兴趣的:(stm32单片机入门基础知识——延时、滴答计时器、外部中断、定时器中断)