热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

单片机中断全局变量保护方法

首先要明白这几个知识点:关键字volatile的使用,原子操作,临界区的使用。明白的直接跳到文中的4.全局变量的使用及保护处查看。1.关键字volatile关键字volatile用

首先要明白这几个知识点:关键字volatile的使用,原子操作,临界区的使用。明白的直接跳到文中的4.全局变量的使用及保护处查看。

1.关键字volatile

关键字volatile用于告诉编译器,说明被修身的变量可能会被意想不到地改变,防止编译器对代码进行优化。

比如如下程序:

1 ucNms=0x65;
2 ucNms=0x66;
3 ucNms=0x67;
4 ucNms=0x68;

上述4条语句,如果变量在声明的时候(unsigned char ucNms;)没有使用volatile,那么编译器有可能对其优化,只编译最后一条语句ucNms=0x68;(即忽略前三条语句,只产生一条机器汇编代码);如果变量在声明的时候(volatile unsigned char ucNms;)使用了volatile,则编译器会逐一地进行编译并产生四条相应的机器代码(产生四条代码)。

精确地说就是,编译器在编译这个变量语句时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。所以下面几个情况在声明的时候需要用volatile关键字对其修饰:

1)并行设备的硬件寄存器(如:状态寄存器)

2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3)多线程应用中被几个任务共享的变量

2.原子操作

原子操作可以理解为不被打断的操作,可以是一个步骤的操作,也可以是多个步骤的操作,总之确保操作不被打断。

3.临界区

指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。



4.全局变量的使用及保护

单片机裸机编程,使用全局变量时,一般是一个或多个*.c文件(或模块)中会使用到某个全局变量(假设为A),还有中断中也会用到这个全局变量。这样在使用时就要考虑变量的安全性。单片机裸机编程是前后台系统,如下图:


 

 



单片机裸机编程前后台系统

首先要明白大循环(后台)对这个变量的访问是依次的,不管全局变量A是在哪一个模块或者*.c文件中,每一个时刻只有一个地方对变量A访问。然后中断和中断嵌套程序中也会有对全局变量A的访问。

于是就存在这样的问题,大循环(后台)在访问全局变量A时(比如说访问到一半时),被中断(前台)程序打断并修改了全局变量A,这样大循环(后台)程序再次对全局变量A访问,就会导致访问到的A存在不确定性。从而会影响程序的不正常运行。

这样就可以很明确的知道,只要在大循环(后台)访问A时,不让中断(前台)打断其访问即可。确保对A的访问是原子操作。于是就有这样的解决方法:

关中断-->>全局变量A-->>开中断

有的时候,如果访问变量A的过程比较长,可以对全局变量A做一个副本拷贝a,用拷贝的a作为模块处理的数据。于是就有了这样:

关中断-->>访问全局变量A-->>副本拷贝a-->>开中断->>操作副本拷贝a

这种复杂的情况也可以做一个锁这样做:

大循环(后台):

关中断-->>上锁-->>开中断-->>访问变量A-->>关中断-->>解锁-->>开中断

中断(前台):

如果是解锁的,操作全局变量A,如果是上锁的就不操作

当然,如果访问全局变量A本身就是一个原子操作(比如一条指令就可以访问完成),这样也就不需要做开关中断的处理了。



示例1:禁止中断方法保护全局变量

大循环(后台)

ET0=0; //禁止定时中断
访问全局变量A;
其他代码部分;
ET0=1; //开启允许定时中断

定时器中断(前台)

操作全局变量A;


示例2:加锁的方法保护全局变量

大循环(后台)

ET0=0; //禁止定时中断
Lock = 1;
ET0=1; //开启允许定时中断
访问全局变量A;
其他代码部分;
ET0=0; //禁止定时中断
Lock =0;
ET0=1; //开启允许定时中断

定时器中断(前台)

If(lock ==0) 操作全局变量A;
else{;}


示例3:加锁的方法保护全局变量

大循环(后台)

Lock = 1;//若此条语句对应汇编指令是原子操作可以不用开关中断保护此锁
访问全局变量A;
其他代码部分;
Lock =0;//若此条语句对应汇编指令是原子操作可以不用开关中断保护此锁

定时器中断(前台)

If(lock ==0) 操作全局变量A;
else{;}


总结下:中断全局变量尽量要用volatile修饰,中断全局变量要原子操作访问,要时刻明白中断全局变量是临界区资源,共享访问时需要保护。

 

转发自:http://www.360doc.com/content/19/0117/10/39315025_809417729.shtml#



推荐阅读
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • PHPMailer邮件类邮件发送功能的使用教学及注意事项
    本文介绍了使用国外开源码PHPMailer邮件类实现邮件发送功能的简单教学,同时提供了一些注意事项。文章涵盖了字符集设置、发送HTML格式邮件、群发邮件以及避免类的重定义等方面的内容。此外,还提供了一些与PHP相关的资源和服务,如传奇手游游戏源码下载、vscode字体调整、数据恢复、Ubuntu实验环境搭建、北京爬虫市场、进阶PHP和SEO人员需注意的内容。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Linux下安装免费杀毒软件ClamAV及使用方法
    本文介绍了在Linux系统下安装免费杀毒软件ClamAV的方法,并提供了使用该软件更新病毒库和进行病毒扫描的指令参数。同时还提供了官方安装文档和下载地址。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有