精华内容
下载资源
问答
  • 【当前特权不低于中断处理程序的特权 CPL (当前程序运行的权限级别)与门描述符DPL 作比较,有效 权限级别高于DPL ,则通过,否则不允许访问  再与段描述符的DPL 作比较,有效权限级别高于DPL ,则通过, ...

    实模式和保护模式

    	实模式是早期CPU运行的工作模式,而保护模式则是现代CPU运行的模式。
    
    	实模式出现于早期8088CPU时期。当时由于CPU的性能有限,一共只有20位地址线(所以地址空间只有1MB),以及8个16位的通用寄存器,以及4个16位的段寄存器。所以为了能够通过这些16位的寄存器去构成20位的主存地址,必须采取一种特殊的方式。当某个指令想要访问某个内存地址时,它通常需要用下面的这种格式来表示:
    

    (段基址:段偏移量)
      其中第一个字段是段基址,它的值是由段寄存器提供的。段寄存器有4种,%cs,%ds,%ss,%es。具体这个指令采用哪个段寄存器是由这个指令的类型来决定的。比如要取指令就是采用%cs寄存器,要读取或写入数据就是%ds寄存器,如果要对堆栈操作就是%ss寄存器。总之,不管什么指令,都会有一个段寄存器提供一个16位的段基址。

    第二字段是段内偏移量,代表你要访问的这个内存地址距离这个段基址的偏移。它的值就是由通用寄存器来提供的,所以也是16位。那么问题来了,两个16位的值如何组合成一个20位的地址呢?这里采用的方式是把段寄存器所提供的段基址先向左移4位。这样就变成了一个20位的值,然后再与段偏移量相加。所以算法如下:

    物理地址 = 段基址<<4 + 段内偏移

    指令中真实出现的是逻辑地址。一个逻辑地址是由两部分组成的,一个段选择子(segment selector),一个段内偏移量(offset),通常被写作segment:offset。
    而且采用哪个段选择子通常也是在指令中隐含的,程序员通常只需要指明段内偏移量。然后分段管理机构(segmentation hardware)将会把这个逻辑地址转换为线性地址(linear address)。如果该机器没有采用分页机制(paging hardware)的话,此时linear address就是最后的主存物理地址。但是如果机器中还有分页设备的话,比如内存大小实际只有1G,但是根据前面我们知道可访问的空间有4G。所以此时还需要分页机构(paging hardware)把这个线性地址转换为最终的真实物理地址。

    在这里插入图片描述

    IA32体系

    基本概念:
    中断控制器(PIC 或APIC )
    • 负责将硬件的中断信号转换为中断向量,引发CPU 中断

    实模式:中断向量表(Interrupt Vector )

    保护模式:中断描述符表(Interrupt Descriptor table )
    • 采用门(gate) 描述符数据结构描述中断向量

    门:任务门,中断门,陷阱门,调用门

    具体顺序为:

    中断/ 异常的硬件处理过程 :
    1:确定与中断或异常关联的向量i
    2:通过IDTR 寄存器找到IDT 表,获得中断描述符 (表中的第i 项)拥有段选择符和偏移量
    3:从GDTR 寄存器获得GDT的地址,结合中断描述符中的段选择符获得对应的段描述符;从该段描述符中得到中断或异常并得到 处理程序所在的段基址
    4:将偏移量和段基址得到虚拟地址,再得到物理地址
    • 特权级检查
    确保CPL (CS 寄存器中)≤ 门描述符DPL
    避免应用程序访问特殊的陷阱门或中断门
    确保CPL ≤ 段描述符DPL
    【当前特权级不低于中断处理程序的特权级
    CPL (当前程序运行的权限级别)与门描述符DPL 作比较,有效
    权限级别高于DPL ,则通过,否则不允许访问
     再与段描述符的DPL 作比较,有效权限级别高于DPL ,则通过,
    否则不允许访问】

    在这里插入图片描述
    在这里插入图片描述
    三、存储系统
    支持OS 运行硬件环境的一个重要方面:
    • 进程必须将其程序和数据放在内存中才能运行
    • 操作系统本身也要放在内存中运行
    • 多道程系统中,若干个程序和相关的数据要放入内存
    →→ 操作系统要管理、保护程序和数据,使它们不至于受到破坏
    在这里插入图片描述

    高速缓存cache:不归操纵系统管,仅归硬件管 所含内容是内存的一部分,子集
    在这里插入图片描述

    时钟
    时钟为计算机完成以下必不可少的工作:
    • 在多道程序运行环境中 , 为系统发现陷入死循环 ( 编程错误 ) 的作业 ,
    防止机时的浪费
    • 在交互式系统中 , 实现进程间按时间片轮转
    • 在实时系统中 , 可完成延时与超时控制等功能
    • 定时唤醒要求延迟执行的各外部事件 ( 如定时为各进程计算优先数 ,
    银行中定时运行某类结账程序等 )
    • 记录用户使用设备的时间和某外部事件发生时间
    • 维持日历时间

    系统调用

    用户态——内核态
    在这里插入图片描述

    在这里插入图片描述一共有两个表,(2)中为中断向量表(识别中断和异常的类型),(4)中为系统调用表(识别系统调用的具体操作)
    在这里插入图片描述
    在这里插入图片描述

    参数传递过程问题
    • 怎样实现用户程序的参数传递给内核?
    常用的3种实现方法:
    • 由陷入指令自带参数: :陷入指令的长度有限,且还要
    携带系统调用功能号,只能自带有限的参数
    • 通过通用寄存器传递参数: :这些寄存器是操作系统和
    用户程序都能访问的,但寄存器的个数会限制传递参
    数的数量
    • 在内存中开辟专用堆栈区来传递参数

    在这里插入图片描述
    在上一篇博文中提到了中断的流程

    注意,只有系统调用会找中断描述符,再找系统调用表。如果是其他异常,那么根据中断描述符获得中断处理程序后就直接处理
    中断处理流程
    1:打印机给CPU 发中断信号                  硬件中断
    CPU 处理完当前指令后检测到中断[引脚],判断出中断来源并向相关设备发确认信号
    2:CPU 开始为软件处理中断做准备:             硬件中断
    处理器状态被切换到内核态
    在系统栈中保存被中断程序的重要上下文环境,主要是 程序计数器PC 、程序状态字PSW

    3:CPU 根据中断码查中断向量表,获得与该中断相关的处理程  硬件中断
    序的入口地址,并将PC 设置成该地址,新的指令周期开始时,

    4:CPU 控制转移到中断处理程序               软件中断
    中断处理程序开始工作

    在系统栈中保存现场信息
    检查I/O 设备的状态信息,操纵I/O 设备或者在设备和内存之间传送数据等等

    5:中断处理结束时,CPU 检测到中断返回指令,判断是否继续切换。 硬件中断
    若不切换,从系统栈中恢复被中断程序的上下文环境,CPU状态恢复成原来的状态,PSW 和PC 恢复成中断前的值
    若切换:则将系统栈中上下文环境保存到进程的PCB中。将选择的进程的PCB的内容[读取到系统栈中]

    现在补充这一流程黄线部分
    系统调用总入口程序 :保存现场;将参数保存在内核堆栈里;通过查系
    统调用表把控制权转给相应的系统调用处理例程或内核函数并且执行系统调用例程

    对于程序
    #include <unistd.h>
    int main(){
    char string[7] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’, ‘\n’};
    write(1, string, 7);
    return 0;
    }
    对应的汇编语言
    在这里插入图片描述

    LINUX的系统调用实现——基于X86体系结构

    函数调用流程

    用户态下调用C库的库函数,比如func() :
    func() 先做好参数传递工作,然后使用int 0x80 指令产生一次异常
    CPU 通过0x80 号在IDT 中找到对应的服务例程system_call() ,并调
    用之
    system_call() 根据系统调用号索引系统调用表,找到系统调用程
    序入口,比如sys_func()
    sys_func() 执行完后,经过
    ret_from_sys_call()

    其中int 0x80 中指令包括的部分

    执行 INT $0X80

    由于特权级的改变,要切换栈
    用户栈→ 内核栈
    CPU 要从任务状态段TSS 中装入新的栈指针(SS ︰ESP ),指向内核栈
    • 用户栈的信息(SS ︰ESP )、EFLAGS【程序状态字】 、用户态CS 【PC】、EIP【IR】寄存器的内容压栈
    (返回用)
    • 将EFLAGS 压栈后,复位TF ,IF 位保持不变
    • 用128 在IDT 中找到该门描述符,从中找出段选择符装入代码段寄存器CS
    • 代码段描述符中的基地址 + 量 陷阱门描述符中的偏移量 → 定位
    system_call()

    system_call:

    system_call:
    pushl %eax # 将系统调用号压栈
    SAVE_ALL

    cmpl $(NR_syscalls), %eax
    #检查 是否是合法的 系统调用号
    jb nobadsys
    movl $(-ENOSYS), 24(%esp)
    #堆栈中的eax 设置为-ENOSYS , 作为返回值
    jmp ret_from_sys_call
    nobadsys:

    call *SYMBOL_NAME(sys_call_table)(,%eax,4)
    #调用系统调用表中调用号为eax 的系统调用例程
    movl %eax,EAX(%esp)
    #将返回值存入堆栈中eax 中
    jmp ret_from_sys_call

    ret_from_sys_call :

    ret_from_sys_call :
    cli # 关中断
    cmpl $0,need_resched(%ebx)
    jne reschedule
    #如果进程描述符中的need_resched 位
    #不为0 ,则重新调度
    cmpl $0,sigpending(%ebx)
    jne signal_return
    #若有未处理完的信号,则处理

    restore_all:

    restore_all:
    RESTORE_ALL # 堆栈弹栈,返回用户态

    其中的参数传递:
    系统调用使用寄存器传递参数,要传递的参数包括:
    • 系统调用号
    • 系统调用所需的参数

    • 用于传递参数的寄存器有:
    • eax 用于保存系统调用号系统调用返回值
    • 系统调用参数保存在ebx,ecx,edx,esi 和edi 中,参数个数不超过6 个
    • 进入内核态后,system_call 再将这些参数保存在内核堆栈中
    栈中的结构如下所示
    在这里插入图片描述

    程序转换流程

    在这里插入图片描述

    所以总的进出流程如下
    在这里插入图片描述

    展开全文
  • CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256的可编程中断设置。 STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16可编程的中断优先级。 STM32F103系列上面,又只有60...

    5.1初识NVIC中断

    • CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
    • STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。
    • STM32F103系列上面,又只有60个可屏蔽中断,在107系列才有68个。

    《SMT32中文参考手册》中关于STM32F103系列的60个可屏蔽中断
    在这里插入图片描述
    在这里插入图片描述

    5.2NVIC中断优先级分组

    STM32对中断进行组0~4分组以管理中断优先级。分组配置是在寄存器SCB->AIRCR中配置。
    在这里插入图片描述
    抢占优先级 & 响应优先级区别:

    • 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
    • 抢古优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
    • 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
    • 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行。

    5.3中断优先级设置步骤

    系统运行后先设置中断优先级分组。调用函数:

    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
    

    整个系统执行过程中,只设置一次中断分组,在一般主函数中配置该函数。
    例如设置NVIC中断分组2:

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    

    针对每个中断,设置对应的抢占优先级和响应优先级,调用函数:

    void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
    

    而NVIC_InitTypeDef结构体:

    typedef struct
    {
      uint8_t NVIC_IRQChannel;/l设置中断通道
      uint8_t NVIC_IRQChannelPreemptionPriority;//设置响应优先级uint8_t   
      NVIC_IRQChannelSubPriority; //设置抢占优先级
      FunctionalState NVIC_IRQChannelCmd; //使能
    }NVIC_InitTypeDef;
    

    例如配置串口1中断优先级

        //GPIO端口设置
    	GPIO_InitTypeDef GPIO_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
    
    	//USART1_TX   GPIOA.9
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
    
    	//USART1_RX	  GPIOA.10初始化
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    
    	//Usart1 NVIC 配置
    	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
    
    展开全文
  • CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256的可编程中断设置。 STM32并没有使用CM3内核的全部东西,而是只用了它的一部分 STM32有84个中断,包括16个内核中断和68个可屏蔽中断,...

    1.NVIC中断优先级分组
    CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
    STM32并没有使用CM3内核的全部东西,而是只用了它的一部分
    STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。
    STM32F103系列上面,又只有60个可屏蔽中断(在107系列才有68个)

    2.中断管理方法
    首先,对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。
    在这里插入图片描述3.抢占优先级&响应优先级区别
    高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的(抢占优先级&响应优先级的值越小优先级越高)
    抢占优先级相同的中断,高响应优先级不可以打断低低响应优先级的中断
    抢占优先级相同的中断,当两个中断同时发生时, 响应优先级高的中断先执行
    如果两个中断的抢占优先级和响应优先级都是一样的话,则看那个中断先发生就先执行;
    例子:
    假设设置中断优先级组为2,然后设置中断3(RTC中断)的抢占优先级为2,响应优先级为1。中断6(外部中断0)的抢占优先级为3,响应优先级为0.中断7(外部中断1)的抢占优先级为2,响应优先级为0。

    中断的优先级顺序为:中断7>中断3>中断6

    4.中断优先级分组函数

    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
    
    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
    {
       assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
       SCB->AIRCR=AIRCR_VECTKEY_MASK|NVIC_PriorityGroup;
    }
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    
    

    5.中断参数初始化函数

    typedef struct
    {
    uint8_t NVIC_IRQChannel;设置中断通道
    uint8_t NVIC_IRQChannelPreemptionPriority;设置响应优先级
    uint8_t NVIC_IRQChannelSubPriority;//设置抢占优先级
    FunctionalState NVIC_IRQChannelCmd;//使能
    }
    
    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寄存器
    
    

    中断优先级设置步骤
    在这里插入图片描述

    展开全文
  • STM32入门()定时器与中断 STM32F103系列有11个定时器: 2个高级定时器(TIM1,TIM8):高级定时器除了具有基本定时器和通用定时器的功能以外,还具有输出互补带死区的信号,以及刹车等功能。 4个通用定时器...

    STM32入门(五)定时器与中断

    STM32F103系列有11个定时器:

          2个高级定时器(TIM1,TIM8):高级定时器除了具有基本定时器和通用定时器的功能以外,还具有输出互补带死区的信号,以及刹车等功能。
    
         4个通用定时器(TIM2,TIM3,TIM4,TIM5):通用定时器(TIM2~TIM5)除了基本的定时功能以外,还具有输入捕获和输出比较,产生pwm波形的功能。
    
         2个基本定时器(TIM6,TIM7):基本定时器(TIM6,TIM7)的主要功能就是定时,由各自的可编程预分频器驱动。
    
         2个看门狗定时器(IWDG,WWDG):看门狗定时器用于监测程序是否故障的,在超出一定时间程序跑飞了或者CPU不工作了,会产生一次系统复位或者是中断(只有窗口看门狗有中断功能)。
    
         1个系统滴答定时器:系统滴答定时器是封装在cortex-M3中的一个定时器,在运行操作系统时滴答定时器周期性产生中断,基于时间片轮转的系统会在时间片里切换任务,还能用这个定时器实现精准的延时。
    

    TIM1~TIM8这8个定时器都是16位的,最大能到65535,这个值我们称之为重装载值(arr),定时器计数模式有3种:

     (1)向上计数模式:从0开始计数,逐一递增到arr,产生溢出事件,重新从0开始计数;
    
     (2)向下计数模式: 从arr开始计数,逐一递减到0,产生溢出事件,重新从arr开始计数;
    
     (3)向上/向下模式:从0开始向上计数,计到arr产生溢出事件然后向下计数,计到0又产生溢出,再从0开始向上计数。
    

    TIM1~TIM8中,除了基本定时器TIM6,TIM7只具有向上计数模式之外,其他6个都支持3种计数模式。定时器定时时间计算,假设定时时间T,预分频值为psc,时钟为SYS_CLK(时钟源为系统时钟),则T=((psc+1)/SYS_CLK)*(arr+1)。

    接下来我们以通用定时器TIM3为实例,来说明要经过哪些步骤,才能达到这个要求,并产生中断。这里我们就对每个步骤通过库函数的实现方式来描述。首先要提到的是,定时器相关的库函数主要集中在固件库文件stm32f10x_tim.h和stm32f10x_tim.c文件中。

    1)TIM3时钟使能
    TIM3是挂载在APB1之下,所以我们通过APB1总线下的使能使能函数来使能TIM3。调用的函数是:

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    

    2)初始化定时器参数,设置自动重装值,分频系数,计数方式等。在库函数中,定时器的初始化参数是通过初始化函数TIM_TimeBaseInit实现的:

    voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
    

    第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结构体指针,结构体类型为TIM_TimeBaseInitTypeDef,下面我们看看这个结构体的定义

    typedef struct{
    uint16_t TIM_Prescaler;     
    uint16_t TIM_CounterMode;       
    uint16_t TIM_Period;         
    uint16_t TIM_ClockDivision;   
    uint8_t TIM_RepetitionCounter;   
    } TIM_TimeBaseInitTypeDef;  
    

    这个结构体一共有5个成员变量,要说明的是,对于通用定时器只有前面四个参数有用,最后一个参数TIM_RepetitionCounter是高级定时器才有用的,这里不多解释。

    第一个参数TIM_Prescaler是用来设置分频系数的,刚才上面有讲解。
    第二个参数TIM_CounterMode是用来设置计数方式,上面讲解过,可以设置为向上计数,向下计数方式还有中央对齐计数方式,比较常用的是向上计数模式TIM_CounterMode_Up和向下计数模式TIM_CounterMode_Down。
    第三个参数是设置自动重载计数周期值,这在前面也已经讲解过。
    第四个参数是用来设置时钟分频因子。
    针对TIM3初始化范例代码格式:

    TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 5000;
    TIM_TimeBaseStructure.TIM_Prescaler =7199; 
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    

    3)设置TIM3_DIER允许更新中断
    因为我们要使用TIM3的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定时器中断使能是通过TIM_ITConfig函数来实现的:

    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)

    第一个参数是选择定时器号,这个容易理解,取值为TIM1~TIM17。第二个参数非常关键,是用来指明我们使能的定时器中断的类型,定时器中断的类型有很多种,包括更新中断TIM_IT_Update,触发中断TIM_IT_Trigger,以及输入捕获中断等等。第三个参数就很简单了,就是失能还是使能。例如我们要使能TIM3的更新中断,格式为:

    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); 
    

    4)TIM3中断优先级设置。
    在定时器中断使能之后,因为要产生中断,必不可少的要设置NVIC相关寄存器,设置中断优先级。之前多次讲解到用NVIC_Init函数实现中断优先级的设置,这里就不重复讲解。

    5)允许TIM3工作,也就是使能TIM3。光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,通过TIM3_CR1的CEN位来设置。在固件库里面使能定时器的函数是通过TIM_Cmd函数来实现的:

    void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
    

    这个函数非常简单,比如我们要使能定时器3,方法为:

    TIM_Cmd(TIM3, ENABLE);    //使能TIMx外设
    

    6)编写中断服务函数。
    在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器SR的最低位。在处理完中断之后应该向TIM3_SR的最低位写0,来清除该中断标志。在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:

    ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
    

    该函数的作用是,判断定时器TIMx的中断类型TIM_IT是否发生中断。比如,我们要判断定时器3是否发生更新(溢出)中断,方法为:

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
    

    固件库中清除中断标志位的函数是:

    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
    

    该函数的作用是,清除定时器TIMx的中断TIM_IT标志位。使用起来非常简单,比如我们在TIM3的溢出中断发生后,我们要清除中断标志位,方法是:

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update    );
    

    这里需要说明一下,固件库还提供了两个函数用来判断定时器状态以及清除定时器状态标志位的函数TIM_GetFlagStatus和TIM_ClearFlag,他们的作用和前面两个函数的作用类似。只是在TIM_GetITStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而TIM_GetFlagStatus直接用来判断状态标志位。
    通过以上几个步骤,我们就可以达到我们的目的了,使用通用定时器的更新中断,来控制DS1的亮灭。

    time.c文件:

    #include "timer.h"
    #include "led.h"
    
    //通用定时器3中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器3!
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    	
    	//定时器TIM3初始化
    	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
     
    	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    
    	//中断优先级NVIC设置
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    
    
    	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
    }
    //定时器3中断服务程序
    void TIM3_IRQHandler(void)   //TIM3中断
    {
    	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
    		{
    		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
    		LED1=!LED1;
    		}
    }
    
    

    main文件:

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"
    #include "timer.h"
     
     int main(void)
     {		
     
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	LED_Init();			     //LED端口初始化
    	TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
       	while(1)
    	{
    		LED0=!LED0;
    		delay_ms(200);		   
    	}	 
    
     
    }	 
     
    
    

    此段代码对TIM3进行初始化之后,进入死循环等待TIM3溢出中断,当TIM3_CNT的值等于TIM3_ARR的值的时候,就会产生TIM3的更新中断,然后在中断里面取反LED1,TIM3_CNT再从0 开始计数。根据上面的公式,我们可以算出中断溢出时间为500ms,即
    Tout= ((4999+1)*( 7199+1))/72=500000us=500ms

    如果没有错误,我们将看DS0不停闪烁(每400ms闪烁一次),而DS1也是不停的闪烁,但是闪烁时间较DS0慢(1s一次)。

    展开全文
  • 定时器中断是由单片机中的定时器溢出而申请的中断。 51单片机中有两个定时器T0和T1: TF0:定时器T0溢出中断请求。当定时器TO产生溢出时,TO中断请求标志TF0置1,请求中断处理。 TF1:定时器T1溢出中断请求。当...
  • 从硬件结构上看, 处理过程分上下两个层面: 中断控制器, 使用中断的设备 ...也有下面一中断控制器gpg、gpf,对于gpg、gpf这两个中断控制器是pinctr节点里面的子节点,对应的设备树描述如下...
  • “五一”假期前后这约天时间,终于将MIPS中断系统进行了板验证及实例测试。因为老师给的交叉编译工具不会用,所以测试代码完全用MIPS汇编编写。使用MARS而没有用QtSpim,其实我觉得SPIM这个东西比较复杂,但是...
  • Pipeline-processor:基于Verilog HDL的五级流水线处理器 开发平台 VIVADO 16、xilinx FPGA开发板 设计要求 设计一个 5 级流水线的 MIPS 处理器,采用如下方法解决竞争问题: 采用完全的 forwarding 电路解决数据关联...
  • 2、ARM9采用五级流水线方式;3、支持外部中断和内部中断;二、s3c2440 支持的寄存器:2.1 外部中断寄存器24个外部中断占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用这些脚做中断输入,则必须配置引脚为...
  • 51的中断系统

    2019-04-30 22:41:35
    在单片机应用系统中,中断...1)系统有个中断请求源简称为终端源,两个终端优先级,可以实现两级中断服务程序的嵌套。 2)每个中断源都可以使用软件独立地控制为允许中断或者中断关闭 3)中断的优先级由软件设置...
  • 中断全过程

    千次阅读 2019-08-31 20:38:20
    1.执行过程 中断在嵌入式开发中十分重要,特别是对于裸机开发中,中断可以使程序更加简洁,减少程序负担,但是中断从头到尾到底经历了哪些阶段、做了哪些东西应该很多... 中断执行过程通常含有一下个过程: 中...
  • MIPS指令五级流水CPU设计暂停流水线 一旦发生此类冲突 暂停流水线一个时钟 让当前指令的控制信号全部为0,即不进行任何写入操作 让PC值保持不变 让IF/ID段寄存器保持不变 能处理数据冲突的数据通路 3.控制冲突 流水...
  • 实验........................................................................................................................................93 6 汉字显示技术............................................
  • 单片机的中断系统 概念 中断发生:CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理。...个中断源(2个优先级,二级中断嵌套) 外部中断 INT0‾\overline{INT0}INT0 INT1‾\overline{INT1}I
  • 参考书籍:  1.《IBM-PC汇编语言程序设计》  2.http://www.ctyme.com/intr/int-10.htm ... ◆ 设置显示方式: ... 调用参数:AL = 00H 40 × 25 黑白文本,16灰度  AL = 01H 40 × 25 16色文本  AL...
  • 嵌入式三整理

    2018-08-29 13:24:24
    实时时钟(RTC)组件是一种能够提供日历/时钟等功能的内置硬件,S3C2410的RTC具有的主要功能包括BCD数据、闰年产生器、告警功能、独立的电源端口、支持毫秒滴答时钟中断作为RTOS核的滴答时钟、循环复位功能等。...
  • 难度+长度预警:本章将会使用较多的内容讲解特权内容,因为特权中断以及后边将会实现的用户进程中都会有很多的应用,说实话,这部分内容比较繁琐,希望大家能够有耐心阅读下去,当然,为了便于阅读,笔者本人...
  • 包含个中断源,两级中断优先级,优先级可编程设置,通过IP进行设置:  51单片机中断优先级的设置方法解析  PX0(IP.0),外部中断0优先级设定位;  PT0(IP.1),定时/计数器T0优先级设定位;...
  • ARM中断处理过程

    2017-04-11 16:29:00
    以s3c2440 ARM9核为例: ... 2、ARM9采用五级流水线方式;  3、支持外部中断和内部中断; 二、s3c2440 支持的寄存器: 2.1 外部中断寄存器 24个外部中断占用GPF0-GPF7(EINT0-EINT7),GPG0-GP...
  • 1作业题 8051微控制器中有几个中断源几个中断优先级中断优先级是如何控制的在出现同级中断申请时CPU按什么顺序响应按由高级到低级的顺序写出各个中断源各个中断源的入口地址是多少 答8051微控制器中有中断源两个...
  • BIOS中断汇编函数

    2012-03-16 05:23:04
    BIOS中断表,相当于高级语言的api函数,很强,还有dos的,没时间搞,需要的Q我:2㈨㈧044八6
  • 80C51中断系统

    2009-11-26 09:44:09
    80C51有个中断源(c52六个),2个优先级,可实现二级中断嵌套。 1. INT0非(p3.2)可由IT0(TCON.0)选择低电平有效还是下降沿(负脉冲)有效。当p3.2引脚上出现有效的中断信号,中断标志IE0(TCON.1)置高电...
  • 个轮 每个轮里面有256个槽 精度1MS总共256*5=1280个槽 总共是2^40=1,099,511,627,776MS =12,725.829天 =34.865年34年,应该一般的场景够用了。适用于时间精度要求非常高的场景(精度毫秒),比如帧同步里的BUFF。...
  • 8051 微控制器中有几个中断源几个中断优先级中断优先级是如何控制的在出 现同级中断申请时 CPU 按什么顺序响应 按由高级到低级的顺序写出各个中断源 各个中断源的入口地址是多少 答 8051 微控制器中有中断源两...
  • 8051中断系统介绍

    千次阅读 2011-09-14 11:38:43
    8051没有专门的开中断和关中断的指令,中断的开放和关闭是由特殊功能寄存器IE来实现两控制的。有个总开关EA,然后又有ES,ET1,EX1,ET0,EX0个开关。为1表示开,为0表示关。 单片机在复位后,IE各位的状态为0,...
  • 但信号是软件层面上实现的中断,早期常被称为“软中断”。 信号的特点:由于信号是通过软件方法实现,其实现手段导致信号有很强的延时性。但对于用户来说,这个延迟时间非常短,不易察觉。· 每个进程收到的所有...
  • 五级流水: ( =》代表经过时钟边缘触发。对于a-》b=》c:b为时钟触发,a为触发前的输入,c为触发后的输出。 -》代表不经过时钟触发器的计算/处理 ) PC=>PC+4->PC->instruction->IR=>RegCtrl->IRex=>ExCtrl->IRmem=...
  • 中断(一)—— 综述

    2019-02-24 21:42:58
    目录 一、概述 二、中断的框架 2.1 硬件示意图 2.2 中断处理流程 2.2.1 中断处理过程中典型的...操作系统需要对硬件外设进行管理,但是二者的处理速度往往不在一个数量上,需要一种方法是CPU和外设协同工作而...
  • 协程的作用,是在执行函数A时,可以随时中断,去执行函数B,然后中断继续执行函数A(可以自由切换)。但这一过程并不是函数调用(没有调用语句),这一整个过程看似像多线程,然而协程只有一个线程执行。 简单实现协程...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 298
精华内容 119
关键字:

五级中断