历史上的今天
返回首页

历史上的今天

今天是:2026年01月30日(星期五)

正在发生

2023年01月30日 | M20 中断、定时器与程序存储方式

2023-01-30 来源:zhihu

void main() //主程序 不同单片机写法基本一致
{
}

interrupt() //不同单片机 中断程序写法不同
{
}


  • 多个中断类似于多个中断车道的车行进,如果都来抢占红色小车的主车道,会造成红车行进缓慢。

  • 所以中断程序写最简短的代码,尽量少的占用主车道的时间。


以上提到了四个关键名词:

  • 中断

  • 定时器

  • 主程序

  • 中断程序

书籍会给一个名词简短一两句话,作为解释或者定义,实际上大部分名词很难用一句话说明。很多同学学习过程中感觉越学越困难,越来越看不懂,实际上,关键问题就是很多名词需要一本书1000页打底的书来解释才行,我们把自己限定到仅看课本或者一两本关联度很少的书,这样自然是越学越累。因为这些关键名词都没有理解,他们又是后续章节的基础,后续的故事...

继续说这四个名词,

中断是一种机制,为了实现:

  • 提升时间利用率

  • 快速响应信号

  • 尝试一心二用、一心三用

我喜欢单片机比作一个人。

以人的行为来理解中断,我们看一本小说或者看一个电影,看小说的过程中,拿起手机来接了个电话,电话接完了,接着又看小说剩下的内容,过了一会口渴了,又去喝了杯水,接着再看..

  • 看小说是大脑主程序在运行

  • 接电话 大脑切换到电话中断程序

  • 喝水 大脑切换到喝水中断程序

空间和时间是永恒的主题!


从时间上理解中断:

从空间上理解中断:

程序要存储在两个主要的地方

A、电脑中,我们编写的程序源代码(主程序和中断程序都存储在main.c中)


B、编译完成形成二进制代码下载到单片机的程序存储器中(ProgramFlash)



a、首先我们要找到中断程序的位置(以stc单片机为例,其他51单片机类似)

b、看看程序存储器大小

c、写了一段定时器0的中断小程序,我们依照这个程序继续往下分析

源码下载在这里:

向导团队/step by step study singlechip

目录:step-by-step-study-singlechipstepbysteptimertimer0keil

本程序实现功能

  • 启用定时器0

  • 1ms定时并开启定时器中断

  • 1ms定时到达开始计数,计数1000次 LED灯状态反转

  • 主循环空转

  • 主要运行函数为定时器初始化函数和中断函数

#include "reg51.h" //引用头文件


//以下两个类型转换语句只是为了用短单词替代两个单词,写程序时方便

typedef unsigned char BYTE; //BYTE 代替 unsinged char 代表一个字节长度

typedef unsigned int WORD; //WORD 代替 unsigned int  代表两个字节(一个字)长度



//-----------------------------------------------


/* define constants */

#define FOSC 11059200L //主晶振宏定义


#define T1MS (65536-FOSC/12/1000) //1ms timer calculation method in 12T mode //宏定义 1ms定时器在12T模式下的计算方法


/* define SFR */

sbit TEST_LED = P1^0; //work LED, flash once per second //工作LED 1秒闪烁1次


/* define variables */

WORD count; //1000 times counter //1000毫秒计数器


unsigned char runCode; //运行代码 主要函数和关键语句添加,通过观察此变量了解程序运行到的位置


//-----------------------------------------------


/* Timer0 interrupt routine */


void tm0_isr() interrupt 1

{

    runCode=5;


    TL0 = T1MS; //reload timer0 low byte //重新装入定时器0低字节

    TH0 = T1MS >> 8; //reload timer0 high byte //重新装入定时器0高字节

    if (count-- == 0) //1ms * 1000 -> 1s //1ms定时计数1000次 后是1秒

    {

        runCode=6;

        count = 1000; //reset counter //复位计数器

        TEST_LED = ! TEST_LED; //work LED flash //LED灯闪烁

    }

}



void init_timer0()

{

    runCode=3;


    TMOD = 0x01; //set timer0 as mode1 (16-bit) //设置定时器0 16bit工作模式

    TL0 = T1MS; //initial timer0 low byte //初始化定时器0 低字节

    TH0 = T1MS >> 8; //initial timer0 high byte //初始化定时器0 高字节

    TR0 = 1; //timer0 start running //启动定时器0

    ET0 = 1; //enable timer0 interrupt //开启定时器0中断

    EA = 1; //open global interrupt switch //打开所有中断

    count = 0; //initial counter //初始化计数器

}


/* main program 主程序*/

void main()

{

    runCode=1;

    init_timer0(); //初始化定时器函数



    while (1) //主循环

    {

        runCode=2;

        ; //分号代表空转,不做任何事情,但是;也会占用单片机运行时间

    } //loop

}

中断函数很特殊是被keil内部程序调用的,它与主函数(main)是一个等级,不能被主函数直接调用,其他函数可以被主函数调用。

e、继续往下进行,我们只在keil中编写完了程序还不行,需要知道程序是怎么一步步编译成单片机能够存储的格式的。

  • 源程序编写完成

  • 编译链接成二级制格式文件

我们从C语言源文件很难看出中断程序最终存储在那个位置,keil有个强大的功能是可以直接变成汇编语言查看。汇编语言更接近机器语言,从里面我们就能够找到程序的具体位置。

先进行几步设置

1)keil 设置为内部仿真模式

2)点击调试按钮

3)打开汇编语言窗口 打开存储器窗口

4)我们观察下中断程序 C语言 汇编语言格式和存储代码对应的空间

5)理解一个概念 单片机程序存储空间就是用硅晶体组成的一个个电路,也就是一组组开关。然后集成在单片机里面。回头看这张图

0000H~3FFFH 把main.c 内部的程序代码都装进去了,只是变成了单片机认识的二进制的0,1,再进一步实际上是把单片机内部的一个个开关打开还是关上了,1关闭,0开启。

我们看4)中存储器是16进制数 16进制能够一一对应二进制数,例如十六进制FF=11111111

从下图我们可以看出程序就是从哪里执行,运行中从那个地址再调用函数... 所有的代码无论开始的格式是什么样的,最终都变成二进制0、1。(16进制作为中间过程)

6)我们洋洋洒洒写了很多程序代码,实际编译完成写入单片机是很短的代码

f、现在我们再看程序是怎么从C编译成二进制01的就容易理解了


g、重新编译生成hex文件,可用于proteus仿真或烧写单片机

h、最终调试观察运行结果




通过学习,我们知道中断程序(中断函数)和主程序都存储在单片机程序存储器中,通过代码的相互调用反复执行。

先在定时器寄存器中放置一个值 当这个值累加到超过寄存器能存储的最大数就触发中断,累加1实际上会消耗一定的时间,累加到特定数值就可以判断出总时间1ms,本程序64614为初始值,

#define FOSC 11059200L //主晶振宏定义

#define T1MS (65536-FOSC/12/1000)

11059200÷10÷1000=921.6 65536-921.6=64614.4 =FC66(16进制)

所以定时器寄存器要存FC66, FC66不断+1 直到等于65536(0x10000)超出了定时器的计数范围(16位定时器只能存FFFF也就是65535)1ms时间到。


推荐阅读

史海拾趣

Curtis Electromusic Specialties Inc公司的发展小趣事

在电子行业的激烈竞争中,CUI公司凭借其在材料科学领域的深厚积累,成功研发出了一种新型高性能碘化亚铜材料。这种材料不仅具有优异的导电性能,而且稳定性极高,能够在极端环境下保持稳定的性能。凭借这一技术创新,CUI公司的产品迅速获得了市场的认可,并在多个关键领域得到广泛应用,从而实现了公司的快速发展。

弘凯光电(BRIGHTEK)公司的发展小趣事

随着技术的不断进步和市场的逐步打开,弘凯光电开始将业务拓展至全球范围。公司的客户群迅速扩大,遍布60多个国家和地区,同时在欧洲、北美、南美、东南亚和中东地区均设立了经销网点。此外,弘凯光电还积极寻求国际认证,以证明其产品的品质和可靠性。通过取得ISO9001质量保证体系、ISO14001国际环境管理体系认证等一系列认证,公司进一步提升了品牌形象和市场竞争力。

Heimann Optoelectronics Gmbh公司的发展小趣事

进入2015年后,随着物联网、5G等新兴技术的兴起,光电子器件的市场需求呈现出爆发式增长。Hei Inc Optoelectronic Division敏锐地捕捉到了这一市场趋势,及时调整产品策略,加大了对低功耗、小型化光电子模块的研发力度。公司推出的新一代光电子模块不仅满足了市场对于高效能、低能耗的需求,还凭借其优异的性价比迅速占领了市场份额。这一举措不仅推动了公司的快速增长,还进一步巩固了其在光电子领域的市场地位。

Aromat Corp公司的发展小趣事

在快速发展的过程中,Aromat Corp始终关注社会责任。公司积极参与公益活动,支持教育事业和环保事业。同时,Aromat Corp还注重员工的成长与发展,提供良好的工作环境和福利待遇,激发员工的创新精神和团队合作精神。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实的基础。

这五个故事只是虚构的Aromat Corp公司的发展概况,并不代表任何真实公司的实际情况。每个公司的发展历程都是独一无二的,受到市场环境、技术趋势、管理决策等多种因素的影响。

Herrmann Kg公司的发展小趣事

近年来,Herrmann Kg积极推进数字化转型,以提升公司的竞争力和市场响应速度。公司任命了具有丰富行业经验的首席数字官(CDO),负责推动集团内部流程的数字化转型。通过数字化整合业务流程,Herrmann Kg简化了与客户之间的沟通方式,优化了工作速度和透明度,同时为全球客户提供了一致的优质体验。这一战略转型不仅提升了公司的运营效率,还为客户创造了更多的附加价值技术的。

Good-Ark公司的发展小趣事
检查各部件之间的连接线是否接触良好,是否存在松动或断裂等问题。

问答坊 | AI 解惑

谁有mega8学习板的电路图啊!分享一下!谢谢!

哪位仁兄有mega8学习板的原理图,分享一下嘛!小弟我找了好久都没找到啊!:\'(…

查看全部问答>

Linux动态加载驱动模块的问题

本人初学驱动开发 照着例子写了个简单的GPIO驱动 控制开发板上的LED 可是动态加载驱动后显示错误 过程如下: 硬件:s3c2440开发板      GPB5-8接4个LED 软件:linux-2.6.29内核      arm-linux-gcc- ...…

查看全部问答>

请问有4路24位的TTL电平信号的数据采集怎么设计和选型?

模拟信号都好采集,但是有的传感器是BCD码输出的,每个传感器的引脚是24条线输出,有4个,请问怎么设计和选型? 这里面可能要用到数据选择器或者寄存器;还有USB控制器…

查看全部问答>

请教,USART中的LIN模式如何配置`

请教,USART中的LIN模式如何配置GPIO、RCC以及USART的初始化,我用的STM32f103的,哪位用过次芯片的高手赐教下~~~…

查看全部问答>

nand flash驱动unable to mount partition

我的nand flash驱动加载时可以创建分区,也可以找到对应的文件系统驱动,但却无法mount这个分区,所以也出现不了盘符,请大家帮帮忙啊~~…

查看全部问答>

怎样将手机的摄像头作为Wince设备的USB设备

我的手机有一个摄像头,而且可以以USB接口连接到桌面计算机上,作为摄像头使用。请问怎样在WinCE设备里也可以这样用呢?需要怎样开发相关驱动?…

查看全部问答>

显示器怎么了,显示brilho=0

我的电脑前些天还好好的现在开机显示器黑屏只显示Brilho=0 我拿去别的机子试了不是主机的问题,各位大哥大姐教教小第 我该怎么处理啊 显示器调节按钮 按了都没反应。…

查看全部问答>

VS2005调试目标机上应用程序时,用TCP/IP方式连接总是“设备未就绪”??

使用VS2005开发win ce的应用程序,在调试的时间用TCP/IP方式连接到开发板,老说“设备未就绪”,该怎么解决啊?…

查看全部问答>

请教,关于ADS编译C++的问题

请教,我用ads1.2编译c++程序总是报一些头文件找不到,我把system path加了vc的库,结果有出了“only win32 and Mac supported\"这个问题,请问怎么办?ads1.2上可以编译c++吗?要怎么做? …

查看全部问答>

stm8l的Waitmode

Wait mode: The CPU clock is stopped, but selected peripherals keep running. 想请教前辈如何使用这种模式,我不明白进入等待模式后外设工作的时钟源从哪里来,是不是要使能LSI ? CPU停止工作应该不代表HSI停止工作吧?  有 ...…

查看全部问答>