51 单片机【外部中断、定时器中断、回调函数】

这篇具有很好参考价值的文章主要介绍了51 单片机【外部中断、定时器中断、回调函数】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

51 单片机【外部中断、定时器中断、回调函数】

​ 这里的外部中断类似监听器,时时刻刻监视某引脚的电平变化;这里的定时器中断类似于定时任务,可以定时执行某函数;这里将回调函数和中断结合起来,案例里有点设计模式的味道(忘了哪个了,也可能就是感觉,关于高层不能调用低层的解决),也有点函数式编程的味道。

1、中断(包括 外部中断 和 定时器中断,串口todo)

​ 中断可以狭义地看作是监听。它可监听 如 按钮按下、定时器溢出、CPU内部某值的改变等。

以下都是以89C52的某个(大概不是所有)单片机为例,(我也不知道这个是哪个,用哪个就查看哪个的手册) 它共有8个中断,这8个中断包含 4个外部中断、3个计时器中断、1个串口中断。中断有四个优先级可供我们设置。

  • 关于这8个中断。
    • 串口中断 todo
    • 外部中断。  太长了,放下面了,和 “中断” 同级了 
    • 定时器中断。 太长了,放下面了,和 “中断” 同级了
  • 关于优先级。
    • 优先级需要我们自己设置,没设置的话每个中断没有优先级,所以看作它们是同一个优先级,这时需要通过查询顺序区分先后。
    • 优先级可以管控的情况分为两种,第一种——A中断正在执行,B中断触发了; 第二种——A和B中断同时触发了。这两种情况都会比较A和B的优先级进行区分谁去执行。
    • 每一个当下没执行但已经触发了的中断到后来都会被执行的。
    • 如果两个中断平级,则按查询顺序决定哪个中断先执行。
    • 查询顺序(不是优先级)给中断排一下顺序: 外部中断0(INT0')、 定时器中断0(Timer0)、外部中断1(INT1')、定时器1(Timer1)、串口中断(UART)、定时器中断2(Timer2)、外部中断2(INT2')、外部中断3(INT3')。
    • 通过查手册设置优先级。
2、外部中断

外部中断有4个,分别监视四个引脚(P32、P33、P42、P43)。

  • 我们需要先配置外部中断,进行一系列的参数开启,才可以让它监视起来。 这里只记录一丢丢,具体操作需要查询数据手册。看下图,当我们想使用 INT0' 中断时,我们 要做的是 把 总开关 EA、管控 INT0' 的 EX0打开,然后通过 IT0控制是下降沿触发还是低电平触发即可。

    外部中断配置起来简单,但要注意的是,有些寄存器的位在头文件里没有定义,可通过数据手册或下面的第三个图找到它的寄存器然后操作即可。

    中断请求标志位写代码时用不到。

    51 单片机【外部中断、定时器中断、回调函数】

    51 单片机【外部中断、定时器中断、回调函数】

    51 单片机【外部中断、定时器中断、回调函数】

    /**
    * 以0号中断为例
    */
    #include <STC89C5xRC.H>
    #define LED_0 P00
    
    /**
     * @brief 初始化0号中断,这个函数需要被调用一次以开启中断
     */
    void Init_Int0(){
        // 打开中断总开关
        EA = 1;
    
        // 打开外部中断1开关
        EX0 = 1;
    
        // 配置中断为下降沿触发
        IT0 = 1;
    }
    
    /**
    * 0号中断触发后要执行的代码
    */
    void Func_Int0() interrupt 0 {	// interrupt后面的数是啥看手册
        LED_0 = ~LED_0;
    }
    
3、定时器中断。

​ 关于配置定时器中断用到的寄存器位看下图 或者 从数据手册找。

​ 定时器的触发条件是计数寄存器溢出时触发。

​ 计数寄存器有两个,可通过模式决定如何使用这两个寄存器。修改M0和M1的值,如下第三张图片,或者查手册。

​ C/T、GATE、M1、M0 这四个位都在TMOD寄存器里,这个寄存器8bit,另外4bit操控另一个定时器的这四个位,这四个位如何配置看图或手册。

51 单片机【外部中断、定时器中断、回调函数】

51 单片机【外部中断、定时器中断、回调函数】

51 单片机【外部中断、定时器中断、回调函数】

看代码吧

void Timer0_Init() {
    // 打开中断开关
    EA = 1;

    // 打开定时器中断开关
    ET0 = 1;

    // 开启TR0,允许 第一个定时器 中断计数
    TR0 = 1;

    // 设置TMOD,TMOD是一个寄存器,它高四位和低四位分别控制两个不同的定时器
    // 我们需要操作低四位的那个寄存器,高四位保持原态
    TMOD &= 0xF0;
    TMOD |= 0x01;

    // timer0 设置为 1ms 中断
    TL0 = T1MS;
    TH0 = T1MS >> 8;


    counter = 0;
}

总的来说一下,外部中断的配置需要 总开关EA,单个开关,下降沿/低电平的触发方式; 定时器中断配置需要 总开关EA,单个开关,TR0/1/2、控制电路的TMOD(也就是里面的位)、两个寄存器的值(通过它俩控制时间)

定时器的函数写在驱动层,即Dri层。

关于定时器的触发时间

​ 我们外部使用的时钟频率是11.0592MHZ,也就是每秒刷新11059200次。外部时钟频率与芯片内部时钟频率可选择12:1的转换或者6:1的转换,一般我们用12的;

​ 当内部时钟走过 11059200/12/1000 个时钟频率时,过去了1ms;

​ 已知定时器中的计数器溢出时中断触发,我们使用的01模式使用16位全都用来计数,所以当它计到65536时定时器触发;

​ 所以如果我们想让定时器1ms触发一次,只需要初始化定时器时或者每次定时器触发后,把定时器中的计数器置为11059200/12/1000 ,从它走到溢出,刚好走过了1ms。

4、回调函数+定时中断

​ 使用回调函数有个有点,就是可以在高一层定义回调,高一层不用调用低一层的代码,低一层直接调用高一层的回调来掉自己这一层的函数。

我们使用回调函数就是把我们想调用的函数套一层壳子,下面总结下这层壳子要怎么封装和之前写的定时器中断整合在一起。

  • 在定时器的驱动头文件中定义函数指针的类型;

    typedef void(*Timer0_Callback)(void);
    
  • 在定时器驱动C文件中定义函数指针的数组,用来注册函数;

    static Timer0_Callback s_timer0_callbacks[MAX_CALLBACK_COUNT];
    
  • 在初始化定时器中将函数指针的数组置空;

    // 初始化时函数指针的数组置空
    for (i = 0; i < MAX_CALLBACK_COUNT; i++){
       s_timer0_callbacks[i] = NULL;
    }
    
  • 写注册函数的函数,供外部调用

    u8 Dri_Timer0_RegisterCallback(Timer0_Callback callback) {
        u8 i;
        for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
            // 注册过,返回
            if (s_timer0_callbacks[i] == callback)  return 1;
        }
    
        // 没注册过,注册
        for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
            if (s_timer0_callbacks[i] == NULL) {
                s_timer0_callbacks[i] = callback;
                return 1;
            }
        }
    	
        return 0;
    }
    
  • 通过定时器执行注册过的函数

    void Dri_Timer0_Func() interrupt 1 {
        u8 i;
        // 更新计数器中的数,保证下次还是1ms后触发
        TL0 = T1MS;	  // 这个T1MS是宏定义,(65536 - 11059200 / 12 / 1000)
        TH0 = T1MS >> 8;
        
        // 调用所有的回调函数
        for(i = 0; i<MAX_CALLBACK_COUNT; i++){
            if (s_timer0_callbacks[i]) s_timer0_callbacks[i]();
        }
    }
    
  • 使用时,初始化定时器,调用注册回调函数将我们想实现的逻辑放进去就行了

    // 代码略
    

定时器中断可以用来解决之前的延时问题,使用起来很灵活,可根据实际情况操作,可以代替延时函数实现按键消抖、数码管的计数等,通过回调函数可以对定时器中断作优化,也很灵活,需要多多练习。文章来源地址https://www.toymoban.com/news/detail-760599.html

到了这里,关于51 单片机【外部中断、定时器中断、回调函数】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机 | 定时器中断实验

      这一节介绍51单片机的定时器中断。 STC89C5X 含有 3 个定时器:定时器 0、定时器 1、定时器 2(注意: 51 系列单片机一定有基本的 2 个定时器(定时器 0 和定时器 1),但不全有 3 个中断,需要查看芯片手册,通常我们使用的是基本的 2 个定时器:定时器 0/1)。本节要实现

    2024年02月06日
    浏览(97)
  • 51单片机定时器中断TMOD

    最近在学定时器中断TMOD,写程序时,要对定时器进行配置 对TMOD进行赋值时,拌了好久。。。。 如何根据所用的      定时器0/1 ,  工作方式0/1/2/3      对TMOD赋值呢? 我们知道: 1.TMOD长这样 :  由八位组成,前四位是T1的参数;后四位是T0的参数;GATE 和 C/T\\\' 不用多讲,

    2024年02月12日
    浏览(30)
  • 51单片机中断定时器1用法

    中断为使单片机具有对内部或外部随机发生的事件实时处理而设置的。 中断技术不仅解决了快速主机与I/O设备的数据传送问题,而且还有具有如下的优点: 1. 分时操作:CPU可以分时为多个I/O设备服务,提高了计算机的利用率。 2. 实时操作:CPU能够及时处理应用系统的随机事

    2024年02月06日
    浏览(47)
  • C51单片机——中断与定时器

    中断是大多数CPU最精彩的部分之一,下面我们通过讲解和编程练习学习中断和定时器相关概念 目录 1.1.什么是中断 1.2.中断的种类 1.3中断的相关概念 1.4. 51单片机可用中断及相关引脚 1.4.寄存器 1.5.中断优先级 在未进行任何关于优先级的设置情况下,51 单片机(52 单片机)中断

    2024年02月03日
    浏览(55)
  • STM32单片机(六)TIM定时器 -> 第二节:TIM定时中断练习(定时器定时中断和定时器外部时钟)

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月09日
    浏览(34)
  • 【51单片机】:定时器的详解(包括对单片机定时解释、各类定时方式,以及中断方式)

              51定时/计数器的详解。                   码字不易,如有帮助请收藏,点赞哦。         前提:首先我们知道51单片机内部有21~26个特殊功能寄存器: P.x口寄存器:P0、P1、P2、P3 数据指针寄存器:DP0H、DP0L、DP1H、DP1L 定时器: TH1、TL1、TH0、TL0、TMOD、TCON 串口:

    2024年02月07日
    浏览(86)
  • 51单片机定时器中断按键消抖(无延时)

    单片机入门学习记录(二) 在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。按键的抖动对于人类来说是感觉不到的,但对单片机来说,则是完全可以感应到的,而且还是一个很“漫长”的过程,因为单片

    2024年02月14日
    浏览(49)
  • 51单片机——定时器中断实验,小白讲解,相互学习

    定时器介绍 1,CPU时序的有关知识 震荡周期:为单片机提供定时信号的震荡源的周期(晶振周期或外加震荡周期)。 状态周期:2个震荡周期为1个状态周期,用S表示。震荡周期又称S周期或时钟周期。 机器周期:1个机器周期含6个状态周期,12个震荡周期 指令周期:完成1条指

    2024年02月03日
    浏览(36)
  • C51单片机中断系统与定时器/计时器(理论部分)

    前言 文章的开始,有人可能会问,我们在前几节课学了延时函数,为什么不用延时函数来取代定时器,而必须学定时器呢?这里,有如下几个理由: 1.使用delay函数时,单片机的cpu做不了其他事情,只能等待延时结束。 2.用了定时器cpu就可以做其他的事情,只要定时器溢出时

    2023年04月15日
    浏览(32)
  • 【51单片机】如何设置中断函数(场景:在定时器工作完跳转到中断程序时,怎么识别我们的中断程序在哪里呢?)

    前言 大家好吖,欢迎来到 YY 滴单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 本章是【利用定时器和中断实现一个简单项目】中的一部分,感兴趣的老铁可以跳转传送门查看 传送门 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专

    2024年02月19日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包