Ⅰ 单片机定时/应用问题请教下
开始5个代表什么意思 ORG 0000H LJMP MAIN 是不是在0000H单元 跳转到主程序 ORG 000BH?
-------开始 写ORG 000H, LJMP MAIN , 就是说LJMP MAIN 放在单片机的000H 位置,一般单片RESET 后开始运行的地址就是0000H, 这句话的作用是单片上电后或RESET后就跳到MAIN:这个地方,不是跳到ORG 000BH 这个地方,而是ORG 0100H这个地方,也就是MAIN的地方,ORG 的作用就是设定ORG 后面的程序从这个地方开始放。
LJMP DVTO 这两个又是什么意思 有什么联系 最后的ORG 0100H 代表什么?
------ ORG 000BH 这个地方是单片机的中断点,就是有中断,单片就会到这里,这里的程序LJMP DVTO就是跳到中断服务程序的了!ORG 0100H 代表MAIN:MOV TMOD,#01H, 开始从地址0100H 放!
中断程序中 CPL P1.0取反的作用 以及为什么又要在中断程序中重新设定计数初值 MOV TH0 #0D8H MOV TL0,#0F0H 不是最后的中断返回RETI 返回主程序 将中断响应时保存的断点从栈顶弹回送PC CPU从原来中断的地方执行程序 那么中断程序中设定计数初值的作用是什么?
-------CPL P1.0 的作用就是产生方波,高,低,变化。 中断返回的地方是这里SJMP $
,所以你也知道中断的程序里为什么会设定计数初值的了!
Ⅱ 介绍计数器 /定时器 程序 的编写步骤 (C语言的)
注意:
多数C语言编译器不支持多线程,而且ANSI C也没有线程库,因此C语言无法实现实际意义上的定时器(即包含触发机制的定时器)。
回到本问题:
1 计数器:
简单的int变量(一般为全局或相对全局)就可以实现。
2 计时器:
包含time.h,使用clock相关函数,通过运行时间差来实现计时功能。示例:
/*@*/ clock_t startstart = clock();
……
/*@*/ clock_t endend = clock();
float start2end = (float)(endend-startstart)/CLOCKS_PER_SEC;
// 这里的start2end就是时间差
3 定时器
使用系统API,比如Windows下的Sleep()函数(注意,是大写),原型如下:
VOID Sleep(
DWORD dwMilliseconds // sleep time in milliseconds
);
Ⅲ 单片机定时器计数器如何使用
使用12MHz晶振,其机器周期为1us
欲产生5000us周期方波,只需在p1.0以2500us时间交替输出高低电平
1.T0为方式0,则M1M0=00H。使用定时功能,C/T=0,GATE=0。T1不用,其有关位设为0。因此,TMOD=00H
2.方式0为13长度计数(TL0高3位不使用),设计数初值为X,则(8192-X)*1us=2500us,得X=5692D。X=1011000111100B。因为TL0高3位不用,所以10110001-00011100B得TH0=B1H,TL0=1CH
3.由控制寄存器TCON的TR0位来控制定时的启动和停止,TR0=1启动,TR0=0停止
C语言程序如下(编译器Keil C)
#include<REG51.H>
sbit FB=p1^0;
void initial(void)
{
TMOD=0x00;
TH0=0xb1;
TL0=0x1c;
IE=0x00;
TR0=1;
}
void main(void)
{
initial();
for(;;)
{
while(!TF0);
TF0=0;
FB=!FB;
}
}
汇编程序如下
ORG 0000H
AJMP START
ORG 30H
START: MOV P1.0,#0FFH
MOV TMOD,#00H
MOV TH0,#0B1H
MOV TL0,#1CH
SETB TR0
LOOP: JBC TF0,NEXT
LJMP LOOP
NEXT: CPL P1.0
MOV TH0,#0B1H
MOV TL0,#1CH
LJMP LOOP
END
Ⅳ 单片机高手给点拨下,定时器这个不太理解,定时器初始化有几种方法啊比如说定时1毫秒
51 单片机中定时器,是个 16 位的加法计数器。
其内容是 0000H ~ FFFFH,即:0 ~ 65535。
每隔一个机器周期,加一次一。加到 65536,就会溢出,产生中断。
在外部振荡器频率 = 11.0592 MHz 时,机器周期=1085.06944...us。
要想定时 1000us,这就有点困难了。
在外部振荡器频率 = 12 MHz 时,机器周期=1us。
要想定时 1000us,就可以设初始值为:65536 - 1000 = 64536。
分成高、低八位后,写入 THx、TLx,即可。
求出:初始值、分成高低八位,可以人工计算,那么,程序就是:
TH1 = 0XFC;
TL0 = 0X67;
也可以由编译软件来算,程序中,写出公式,这就是:
TH0 = (65535 - 1000)/256;
TL0 = (65535 - 1000)%256;
-------
又因为,中断响应,是不会及时发生的,通常,都会迟到 3 ~ 8 个机器周期。
用 C 语言编程,会耽误更多吧。
所以,定时时间,应该缩短一些,定时才准确。
因此,才有+ 28 的算法。
加上这个数之后,初始值,就大了一些,更接近 65536,定时时间,就短了。
这是个经验数据。
Ⅳ linux下的几种时钟和定时器机制
1. RTC(Real Time Clock)
所有PC都有RTC. 它和CPU和其他芯片独立。它在电脑关机之后还可以正常运行。RTC可以在IRQ8上产生周期性中断. 频率在2Hz--8192HZ.
Linux只是把RTC用来获取时间和日期. 当然它允许进程通过对/dev/rtc设备来对它进行编程。Kernel通过0x70和0x71 I/O端口来访问RTC。
2. TSC(Time Stamp Counter)
80x86上的微处理器都有CLK输入针脚. 从奔腾系列开始. 微处理器支持一个计数器. 每当一个时钟信号来的时候. 计数器加1. 可以通过汇编指令rdtsc来得到计数器的值。通过calibrate_tsc可以获得CPU的频率. 它是通过计算大约5毫秒里tsc寄存器里面的增加值来确认的。或者可以通过cat /proc/cpuinfo来获取cpu频率。tsc可以提供比PIT更精确的时间度量。
3. PIT(Programmable internval timer)
除了RTC和TSC. IBM兼容机提供了PIT。PIT类似微波炉的闹钟机制. 当时间到的时候. 提供铃声. PIT不是产生铃声. 而是产生一种特殊中断. 叫定时器中断或者时钟中断。它用来告诉内核一个间隔过去了。这个时间间隔也叫做一个滴答数。可以通过编译内核是选择内核频率来确定。如内核频率设为1000HZ,则时间间隔或滴答为1/1000=1微秒。滴答月短. 定时精度更高. 但是用户模式的时间更短. 也就是说用户模式下程序执行会越慢。滴答的长度以纳秒形式存在tick_nsec变量里面。PIT通过8254的0x40--0x43端口来访问。它产生中断号为IRQ 0.
下面是关于pIT里面的一些宏定义:
HZ:每秒中断数。
CLOCK_TICK_RATE:值是1,193,182. 它是8254芯片内部振荡器频率。
LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用来编程PIT。
setup_pit_timer()如下:
spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x34,0x43);
udelay(10);
outb_p(LATCH & 0xff, 0x40);
udelay(10);
outb (LATCH >> 8, 0x40);
spin_unlock_irqrestore(&i8253_lock, flags);
4. CPU Local Timer
最近的80x86架构的微处理器上的local apic提供了cpu local timer.他和pit区别在于它提供了one-shot和periodic中断。它可以使中断发送到特定cpu。one-shot中断常用在实时系统里面。
Ⅵ 单片机实验“定时/计数器及中断”的一些问题
1.1)主程序各行作用如下:
第一行:设置定时器模式
第二行:设置定时器高位寄存器初值
第三行:设置定时器低位寄存器初值
第四行:T0定时器中断使能
第五行:总中断使能
第六行:打开T0定时器
第七行:死循环(主程序停留在此行)
主程序整体实现的功能:初始化定时器T0
1.2)void Timer0_Int(void)是定时器0中断函数,每行作用如下:
第一行:重新设定定时器高位寄存器初值
第二行:重新设置定时器低位寄存器初值
第三行:如果P1_0 IO口是高电平则改为低电平,如是低电平改为高电平
整体实现的功能:P1_0 IO口高低电平1秒切换一次
妈呀,这么多问题,网上找找,应该有的
Ⅶ (微机原理)用8086,8253,8251,8255,8259和8237其中的几种设计一个简单的实验,请给点思路
可编程定时/计数器8253实验
一、实验要求
利用8086外接8253可编程定时/计数器,可以实现方波的产生。
二、实验目的
1、学习8086与8253的连接方法。
2、学习8253的控制方法。
3、掌握8253定时器/计数器的工作方式和编程原理
三、实验说明
8253芯片介绍
8253是一种可编程定时/计数器,有三个十六位计数器,其计数频率范围为0-2MHz,用+5V单电源供电。
8253的功能用途:
⑴延时中断;⑵可编程频率发生器;⑶事件计数器;⑷二进制倍频器⑸实时时钟;⑹数字单稳⑺复杂的电机控制器。
8253的六种工作方式:
⑴方式0:计数结束中断;⑵方式l:可编程频率发生;⑶方式2:频率发生器;⑷方式3:方波频率发生器;⑸方式4:软件触发的选通信号;⑹方式5:硬件触发的选通信号。
四、实验步骤
1、Proteus仿真
a.在Proteus中打开设计文档“8253_STM.DSN”;
b.建立实验程序并编译,仿真;
c.如不能正常工作,打开调试窗口进行调试。
参考程序:
CODE SEGMENT
ASSUMECS:CODE
START:
JMPTCONT
TCONTROEQU0A06H
TCON0EQU0A00H
TCON1EQU0A02H
TCON2 EQU0A04H
TCONT:
MOVDX,TCONTRO
MOVAL,16H;计数器0,只写计算值低8位,方式3,二进制计数
OUTDX,AL
MOVDX,TCON0
MOVAX,20 ;时钟为1MHZ,计数时间=1us*20=20us,输出频率50KHZOUTDX,AL
JMP$
CODEENDS
ENDSTART
五、实验电路及连线
1、Proteus实验电路
Ⅷ 关于51单片机定时/计数器装入初值的问题
这个有什么看不懂得呢 第一种 是吧十进制化成十六机制的方法 第二种呢 就是单纯的十进制
这样跟你说吧 因为th0只有一个字节 那就只能放下8位2进制 于是第一种表示就是把一个大于一个字节小于两个字节的数据转化成两个字节高八位和第八位的分离形式
第二种就简单了 0x9c就是65536-100的十六进制表示啊
那高八位就是前两个十六进制数ff就装到th0中 低八位就是后两个十六进制数9c 装到th1中呗3
这有啥看不懂的啊
这个真的基础到不行了 没法再解释啊
至于转化吗
你去找c语言教程 16进制与十进制的转化 再好好学学
这个是绝对的基础啊
Ⅸ 单片机定时器与计数器的区别
在51单片机的学习过程中,我们经常会发现中断、计数器/定时器、串口是学习单片机的难点,两者的区别是什么呢?下面就跟着我一起来看看吧。
单片机计数器与定时器的区别
计数器和定时器的本质是相同的,他们都是对单片机中产生的脉冲进行计数,只不过计数器是单片机外部触发的脉冲,定时器是单片机内部在晶振的触发下产生的脉冲。当他们的脉冲间隔相同的时候,计数器和定时器就是一个概念。
在定时器和计数器中都有一个溢出的概念,那什么是溢出了。呵呵,我们可以从一个生活小常识得到答案,当一个碗放在水龙头下接水的时候,过了一会儿,碗的水满了,就发生溢出。同样的道理,假设水龙头的水是一滴滴的往碗里滴,那么总有一滴水是导致碗中的水溢出的。在碗中溢出的水就浪费了,但是在单片机的定时计数器中溢出将导致一次中断,至于什么是中断我们下次再讲,这里只是初步的提下概念,中断就是能够打断系统正常运行,而去运行中断服务程序的过程,当服务程序运行完以后又自动回到被打断的地方继续运行。
在定时器计数器中,我们有个概念叫容量,就是最大计数量。方式0是2的13次方,方式1是2的13次方,方式2是2的8次方,方式3是2的8次方。把水滴比喻成脉冲,那么导致碗中水溢出的最后一滴水的就是定时计数器的溢出的最后一个脉冲。
在各种单片机书本中,在介绍定时计数器时都讲到一个计数初值,那什么是计数初值呢?在这里我们还是假设水滴碗。假设第一百滴水能够使碗中的水溢出,我们就知道这个碗的容量是100。问题1,我如何才能使碗接到10滴水就溢出呢?呵呵,我可以想象,如果拿一个空碗去接水,那么还是得要100滴水才能溢出,但是如果我们拿一个已经装有水的碗拿去接,那就不用100滴了。到此我们可以算出,要使10滴水让碗中的水溢出,那么碗中就先要装90滴水。
在定时计数器中,这90滴水就是我们所谓的初始值。问题2,在一个车间我们如何利用单片机对100件产品进行计件,并进行自动包装呢?
我们可以利用计数器计数100,在中断中执行一个自动包装的动作就可以了。
在这里计数初值有3个,假设有方式0:计数初值=8912(2的13次方)—100=8812。方式1:计数初值=65536(2的16次方)—100=65436。方式0:计数初值=256(2的8次方)—100=156。
根据所得的初始值,再将其转换为16进制或者2进制,就可以进行计数或者定时了。当然要让程序完全的运行起来还需要相应的寄存器进行设置。这些可以从各种单片机教程中找到。
单片机中定时器与计数器的区别
定时器实际上也是计数器,只是计数的是固定周期的脉冲
定时/计数器很容易理解的啊
定时器实际上也是工作在计数方式下,只是计数的是固定周期的脉冲,由于脉冲周期固定,由计数值可以计算时间,有定时功能
定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的。
单片机里的寄存器可以看成一个个电子开关,用来切换不同的功能、信号。
51里通过TMOD里的T/C 位切换计数信号的来源
当T/C工作在定时器时,对振荡源12分频的脉冲计数,即每个机器周期计数值加1,计数频率为1/12fosc,当晶振频率6MHZ时,计数频率为500KHz,每2us计数值加1;晶振12MHZ就是每1us加1 了。
当T/C工作在计数器是,计数脉冲来自外部脉冲输入管脚T0(P3.4)或T1(P3.5),当T0或T1脚上负跳变时计数值加1 ,识别管脚负跳变需要2个机器周期,即24个振荡周期。所以T0或T1脚输入的可计数的外部脉冲的最高频率为1/24fosc,当晶振12MHZ时,最高计数频率为500KHz,高于此频率将计数出错。
至于赋初值就是杯子原理了,由于51只能加计数,且只能在杯子刚刚满的那一刻发出中断,触发中断程序,所以我们就往杯子里先放好一定的豆子,再来相应数量的豆子就满了,然后中断程序就自动工作了。
注意:
定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的。
假设我们要定时一定时间(100个机器周期),我们就置初值为(溢出值-100)就行了,假设我们要计件100个,实际上也是置初值为(溢出值-100),然后将输入脉冲设为外部输入就可以了
所以说:定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的。
在中断里置初值是为下一个循环作准备,没什么好说的,看需要定了。
由于定时计数器的值也可以随时读出来,所以我们也可以从0开始计数,从而计算一段时间或一定脉冲的数量哦,这是照样可以打开中断,中断时就说明已经又计数了(定时器溢出值)个脉冲哦,在中断里进行溢出处理,就可以计算出远远大于(定时器溢出值)的数字了
此时也要注意一点:51读数时除了T/C2的捕捉功能,直接读TH和TL可是不断变化的哦,具体的还是看书。当你理解了定时计数器后,我们甚至还可以将计数值置为(溢出值-1),从而实现自动单步(定时模式)或作为外部中断(计数模式)用哦,仔细想想吧,呵呵;-)
至于中断中的需要保护现场的原因,是为了防止不小心修改了别的程序的参数,从而影响别的程序的运行,所以要且只要保护中断程序自己动过的数据,将动过的那些存储器在退出中断时恢复到进入时的状态,就不会影响被中断的程序了。
汇编需要自己保存现场,反正程序就是自己编的嘛,一切尽在掌握中;
C的话编译器会自动进行覆盖分析,自动保存需要保存的变量,一般应用时尽可放心,当然,如果你很了解编译器做了什么,也可以嵌入汇编天马行空自由发挥啊,但新手可不建议这样哦,还是交给编译器吧。
其实这些可以说都是基础知识啊,如果不明白肯定是你的书看的不够仔细哦.
猜你喜欢
1. 单片机的硬件结构是什么
2. 10秒定时器电路设计
3. 单片机技术论文
4. 单片机的发声原理
5. 单片机开题报告范文
6. 电子实习报告单片机
7. 单片机实训报告范文3篇
Ⅹ 89c51单片机定时计数器的工作原理
单片机C51计数器要求:编写一个计数器程序,将T0作为计数器来使用,对外部信号计数,将所计数字显示在数码管上。 该部分的硬件电路如图所示,U1的P0口和P2口的部份引脚构成了6位LED数码管驱动电路,数码管采用共阳型,使用PNP型三极管作为片选端的驱动,所有三极管的发射极连在一起,接到正电源端,它们的基极则分别连到P2.0…P2.5,当P2.0…P2.5中某引脚输是低电平时,三极管导通,给相应的数码管供电,该位数码管点亮哪些笔段,则取决于笔段引脚是高或低电平。图中看出,所有6位数码管的笔段连在一起,通过限流电阻后接到P0口,因此,哪些笔段亮就取决于P0口的8根线的状态。 编写程序时,首先根据硬件连线写出LED数码管的字形码、位驱动码,然后编写程序如下: #include "reg51.h"#define uchar unsigned char#define uint unsigned int uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};//位驱动码uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};//字形码uchar DispBuf[6]; //显示缓冲区 void Timer1() interrupt 3{ uchar tmp;uchar Count; //计数器,显示程序通过它得知现正显示哪个数码管TH1=(65536-3000)/256;TL1=(65536-3000)%256; //重置初值tmp=BitTab[Count]; //取位值P2=P2|0xfc; //P2与11111100B相或P2=P2&tmp; //P2与取出的位值相与tmp=DispBuf[Count];//取出待显示的数 tmp=DispTab[tmp]; //取字形码P0=tmp;Count++;if(Count==6)Count=0; }void main(){ uint tmp;P1=0xff;P0=0xff;TMOD=0x15; //定时器0工作于计数方式1,定时器1工作于定时方式1TH1=(65536-3000)/256;TL1=(65536-3000)%256; //定时时间为3000个周期TR0=1; //计数器0开始运行TR1=1;EA=1;ET1=1;for(;;){ tmp=TL0|(TH0<<8);//取T0中的数值DispBuf[5]=tmp%10;tmp/=10;DispBuf[4]=tmp%10; tmp/=10;DispBuf[3]=tmp%10;tmp/=10;DispBuf[2]=tmp%10;DispBuf[1]=tmp/10;DispBuf[0]=0;}} 这个程序中用到了一个新的知识点,即数组,首先作一个介绍。 数组是C51的一种构造数据类型,数组必须由具有相同数据类型的元素构成,这些数据的类型就是数组的基本类型,如:数组中的所有元素都是整型,则该数组称为整型数组,如所有元素都是字符型,则该数组称为字符型数组。 数组必须要先定义,后使用,这里仅介绍一维数组的定义,其方式为: 类型说明符数组名[整型表达式] 定义好数组后,可以通过:数组名[整型表达式]来使用数组元素。 在定义数组时,可以对数组进行初始化,即给其赋予初值,这可用以下的一些方法实现: 1.在定义数组时对数组的全部元素赋予初值:例:int a[5]={1,2,3,4,5}; 2.只对数组的部分元素初始化;例:int a[5]={1,2}; 上面定义的a数组共有5个元素,但只对前两个赋初值,因此a[0]和a[1]的值是1、2,而后面3个元素的值全是0。 3.在定义数组时对数组元素的全部元素不赋初值,则数组元素值均被初始化为0 4.可以在定义时不指明数组元素的个数,而根据赋值部分由编译器自动确定例:uchar BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};则相当于定义了一个BitTab[6]这样一个数组。 5.可以为数组指定存储空间,这个例子中,未指定空间时,将数组定义在内部RAM中,可以用code关键字将数组元素定义在ROM空间中。uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB}; 用这两种定义分别编译,可以看出使用了code关键字后系统占用的RAM数减少了,这种方式用于编程中不需要改变内容的场合,如显示数码管的字形码等是很合适的。 6.C语言并不对越界使用数组进行检测,例如上例中数组的长度是6,其元素应该是从BitTab[0]~BitTab[5],但是如果你在程序中写上BitTab[6],编译器并不会认为这有语法错误,也不会给出警告(其他语言如BASCI等则有严格的规定,这种情况将视为语法错误),因此,编程者必须自己小心确认这是否是你需要的结果。 程序分析:程序中将定时器T1用作数码管显示,通过interrupt 3关键字定义函数Timer1()为定时器1中断服务程序,在这个中断服务程序中,使用 TH1=(65536-3000)/256;TL1=(65536-3000)%256; 来重置定时器初值,这其中3000即为定时周期,这样的写法可以直观地看到定时周期数,是常用的一种写法。其余程序段分别完成取位码以选择数码管、从显示缓冲区获得待显示数值、根据该数值取段码以点亮相应笔段等任务。其中使用了一个计数器,该计数器的值从0~5对应第1到第6位的数码管。 主程序的第一部分是做一些初始化的操作,设置定时器工作模式、开启定时器T1、开启计数器T0、开启T1中断及总中断,随后进入主循环,主循环首先用unsigned int型变量tmp取出T0中的数值,这里使用了“tmp=TL0|(TH0<<8);”这样的形式,这相当于tmp=TH0*256+TL0,但比之于后一种形式,该方式可以得到更高的效,其后就是将tmp值不断地除10取整,这样将int型数据的各位分离并送入相应的显示缓冲区