单片机减1计数

2017-07-14 21:51:00 dijituo5097 阅读数 162

#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar temp,aa,bai,shi,ge;
sbit dula=P2^6;
sbit wela=P2^7;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void display(uchar bai,uchar shi,uchar ge);
void delay(uint z);
void init();

void main()
{
init();//初始化程序
while(1)
{
if(aa==20)
{
aa=0;
temp++;
if(temp==100)
{
temp=0;
}
bai=temp/100;
shi=temp%100/10;
ge=temp%10;

}
display(bai,shi,ge);
}
}

void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}

void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
aa++;

}
void init()
{
wela=0;
dula=0;
temp=0;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void display(uchar bai,uchar shi,uchar ge)
{
dula=1;
P0=table[bai];
dula=0;
P0=0xff; //消影
wela=1;
P0=0xfe;
wela=0;
delay(5);

dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(5);

dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
delay(5);

}

 

转载于:https://www.cnblogs.com/yeyz/p/7172439.html

2016-01-25 11:39:50 baidu_33836580 阅读数 3951

如图所示电路,要求完成实现按钮按压次数的计数及显示,按一次按钮,计数值加1(要求按十进制累加)。

单片机汇编语言编程:按键、计数及显示 - 非著名博主 - 电子信息角落
http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/album/item/2f609f80899bcfe2bd3e1ec9.html
计数及显示范围是:0~99,超过99则自动归零。
要求对按钮的检测用中断实现,数码显示用动态扫描(数码管为共阴数码管)。
请设计实现该功能的完整程序。
悬赏分:50 - 解决时间:2010-5-12 17:51
最佳答案:
;----------------------------------------------------------------------
;用PROTEUS仿真,显示器使用7SEG-MPX2-CC
;===================================
    ORG 0000H
    AJMP START
    ORG 0013H
    AJMP X1_INT
START:
    MOV SP, #60H
    MOV IE, #84H
    MOV R3, #0
;-------------------
MAIN:
    LCALL DISPLAY
    SJMP MAIN
;-----------------------------------
X1_INT:
    MOV A, R3
    ADD A, #1
    DA   A
    MOV R3, A          ;R3 = 00~99H
X1_LOOP:
    LCALL DISPLAY
    JNB P3.3, X1_LOOP
    RETI
;-----------------------------------
DISPLAY:   
    MOV A, R3
    ANL A, #0FH       ;取出个位.
    MOV DPTR, #TAB
    MOVC A, @A + DPTR
    MOV P2, #0FFH      ;关闭显示.
    MOV P0, A          ;输出段码.
    CLR P2.1           ;P2.1=0
    LCALL DELAY
;-------------------
    MOV A, R3
    SWAP A
    ANL A, #0FH       ;取出十位.
    MOVC A, @A + DPTR
    MOV P2, #0FFH      ;关闭显示.
    MOV P0, A          ;输出段码.
    CLR P2.0           ;P2.0=0
    LCALL DELAY
    RET
;-----------------------------------
DELAY:
    MOV R4, #250
    DJNZ R4, $
    RET
;-----------------------------------
TAB:
    DB 3FH, 06H, 5BH, 4FH, 66H
    DB 6DH, 7DH, 07H, 7FH, 6FH
end
;===================================
回答者:    做而论道 - 十三级   2010-5-8 00:23
提问者对于答案的评价:good
原题网址:http://z.baidu.com/question/151649564.html
;----------------------------------------------------------------------

2020-05-10 10:35:23 terminator3A 阅读数 38

51 单片机汇编语言:8位加减计数器


用51 单片机汇编语言编程,实现8位加减计数器,按下面的按钮选择加计数或者减计数
使用仿真工具:Proteus 8.6
在这里插入图片描述
通过构建子程序完成功能,所需子程序有:
数码管显示子程序、延迟子程序、计数子程序
程序如下:

        ORG   0000H
        JMP   Start
        ORG   0100H
Start:	
cDisplayBuffer   EQU   30H
cDisplayBit      EQU   38H

	    MOV	  cDisplayBuffer,#9       
		MOV	  cDisplayBuffer+1,#9
		MOV	  cDisplayBuffer+2,#9
		MOV	  cDisplayBuffer+3,#9
		MOV	  cDisplayBuffer+4,#9
		MOV	  cDisplayBuffer+5,#9
		MOV	  cDisplayBuffer+6,#8
		MOV	  cDisplayBuffer+7,#0     ; (37H)=0
		MOV	  cDisplayBit,#0 
Main:  
	    MOV   R6,#4        ;计数周期为1s
L1:	    MOV   R5,#0
L2:	    MOV   R4,#0
	    LCALL Display     
	    LCALL Delay       
	    DJNZ  R4,$
	    DJNZ  R5,L2
	    DJNZ  R6,L1	  
	    LCALL COUNT      ;计数
	    SJMP  Main
;---------------------------------------------
DispTable:	 DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
Display:                       ;通用显示子程序
	    MOV   A,cDisplayBit
	    MOV	  P2,A
	    MOV	  DPTR,#DispTable
	    MOV   A,#cDisplayBuffer
	    ADD   A,cDisplayBit
	    MOV	  R0,A
	    MOV   A,@R0
	    MOVC  A,@A+DPTR
	    MOV	  P1,A
	    INC	  cDisplayBit
	    ANL	  cDisplayBit,#7
	    RET
;---------------------------------------------
Delay:                           ;延迟子程序            
	    MOV   R2,#100 
	    DJNZ  R2,$
	    RET  
;---------------------------------------------
COUNT:                           ;计数子程序
	    MOV   R1, #cDisplayBuffer+7
	    JNB   P3.7,DeCount     
InCount:	                     ;P3.7=1时加法计数器
	    INC   @R1
	    CJNE  @R1,#10,RET1       
	    MOV   @R1,#0             ;自增到10时清零
	    DEC   R1
	    CJNE  R1, #cDisplayBuffer-1,InCount   ;cDisplayBuffer-1相当于2FH
	    RET
DeCount:	    			     ;P3.7=0时减法计数器
	    DEC   @R1
	    CJNE  @R1,#255,RET1
	    MOV   @R1,#9
	    DEC   R1
	    CJNE  R1, #cDisplayBuffer-1, DeCount
RET1:   RET	 	   	    
        END

2017-04-19 22:00:33 little_white__ 阅读数 4758

1.基本概念:

89C51有两个计数器T0和T1,每个计数器都是由两个8位的RAM 单元组成的,即每个计数器都是16 位的计数器,最大的计数容量是2的6次方=65536,记住是从0-65535。

定时器的本质也是计数器,只不过定时器的脉冲来自内部的晶振,而计数器的脉冲来自外部,当检测的脉冲的下降沿时,计数寄存器加一,直到溢出,然后单片机产生一个中断。所以需要定时时,先给计数寄存器设定一个初值,每有一个内部的脉冲时钟信号(相当与一段时间),计数器加一,直到溢出,一次定时完成。之后继续循环上述步骤。

2.内部结构:

这里写图片描述

3.相关寄存器:

  1. 定时/计数器方式寄存器TMOD(只能段寻址)
    这里写图片描述
    GATE—门控制位。
    GATE=0,定时器/计数器启动与停止仅受TCON寄存器中TRX(X=0,1)来控制。
    GATE=1,定时器计数器启动与停止由TCON寄存器中TRX(X=0,1)和外部中断引脚(INT0或INT1)上的电平状态来共同控制
    C/T—定时器和计数器模式选择位。
    C/T=1,为计数器模式;C/T=0,为定时器模式。
    M1M0—工作模式选择位。
    这里写图片描述

  2. 定时器/控制器控制寄存器TCON(可以位寻址)
    这里写图片描述
    IT0:外部中断0触发方式控制位
    当IT0=0时,为电平触发方式(低电平有效)
    当IT0=1时,为边沿触发方式(下降沿有效)
    IE0:外部中断0中断请求标志位 (硬件自动完成)
    IT1:外部中断1触发方式控制位(同IT0)
    IE1:外部中断1中断请求标志位 (同IE0)
    TF0:定时/计数器T0溢出中断请求标志位
    TF1:定时/计数器T1溢出中断请求标志位
    TR1:定时器1运行控制位。
    由软件清0关闭定时器1。当GATE=1,且INIT为高电平时,TR1置1启动 定时器1;当GATE=0时,TR1置1启动定时器1。
    TR0—定时器0运行控制位,其功能及操作方法同TR1。

  3. 计数寄存器TH0/TL0(8位) , TH1/TL1(8位)
    关于如何设初值,首先要明白几个周期的概念:

     ***时钟周期:***
    

时钟周期也叫振荡周期或晶振周期,即晶振的单位时间发出的脉冲数,一般有外部的振晶产生,比如12MHZ=12×10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,也就是1/12微秒。通常也叫做系统时钟周期。是计算机中最基本的、最小的时间单位。

		***机器周期:***

在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本操作。完成一个基本操作所需要的时间称为机器周期。8051单片机的机器周期由12个状态周期组成。

在标准的51单片机中,一般情况下,一个机器周期等于12个时钟周期,也就是机器周期=12*时钟周期,(上面讲到的原因)如果是12MHZ,那么机器周期=1微秒。单片机工作时,是一条一条地从RoM中取指令,然后一步一步地执行。单片机访问一次存储器的时间,称之为一个机器周期,这是一个时间基准。

机器周期不仅对于指令执行有着重要的意义,而且机器周期也是单片机定时器和计数器的时间基准。例如一个单片机选择了12MHZ晶振,那么当定时器的数值加1时,实际经过的时间就是1us,这就是单片机的定时原理。

接下来就是如何设初值了:

一般我们取12M晶振时,一个周期刚好是1us,计数1000个就是1ms,这是因为标准的51单片机是12时钟周期的(STC有6时钟和1时钟方式)。那么,如果我们晶振是12M,就比较好算,如果是其它的,就用12去除好了。比如是6M的,那么就是12/6=2,每个计数是2us,那么你要定时1ms就只要计数500个即可以。

定时器的初值跟定时器的工作方式,跟晶振频率都有关系。一个机器周期Tcy=晶振频率X12,计数次数N=定时时间t/机器周期Tcy,那么初值就X=65536-N,得出的数化成十六进制就行了。这里是用定时器O工作方式1做例子,如果是其它工作方式,就不能是65535了。工作方式0是8192,方式2,3是256。这里有一个公式:

TH=(65536-time/(12/ft))/256

其中,time就是要延时的100ms(要取100000us),ft是晶振频率。这个式子又可以简化成

TH=(65536-time*ft/12)/256

TL=(65536-time*ft/12)%256

4.实例分析:

通常定时器初始化过程如下:
(1)对TMOD赋值,以确定T0和 T1的工作方式。
(2)计算初值,并将初值写入TH0、TL0或TH1、TL1。
(3)中断方式时,则对IE赋值,开放中断。
(4)使TR0和TR1置位,启动定时器/计数器定时或计数。

这里写图片描述

	产生一个1khz的方波

主程序:

采用定时器0的模式1

#include <reg51.h>
#include <intrins.h>

#define uint unsigned int 

sbit led = P1^0 ;

void Time0_Init(void)
{
	TMOD = 0x1 ;  //定时器0模式1,C/T = 0 , GATE0 = 0 ;
	TH0 = (65536 - 500)/256 ;  //设初值
	TL0 = (65536 - 500)%256 ;
	ET0 = 1 ;        //开定时器0中断
	EA = 1 ;        //开总中断
	TR0 = 1 ;      // 开定时器0
}

void Time0() interrupt 1
{
	TH0 = (65536 - 500)/256 ; //重新设初值
	TL0 = (65536 - 500)%256 ;
	led = ~led ;
}
void main(void)
{
	Time0_Init() ; // 定时器0初始化
	led = 0 ;

	while(1)
	{

	}
}

采用定时器0的模式2:

#include <reg51.h>
#include <intrins.h>

#define uint unsigned int 

sbit led = P1^0 ;

uint T0_count = 0 ;

void Time0_Init(void)
{
	TMOD = 0x2 ;  //定时器0模式2 ,C/T = 0 ,GATE0 = 0 ;
	TH0 = 256 - 100;  //设初值
	ET0 = 1 ;
	EA = 1 ;
	TR0 = 1 ;      // 开定时器0
}

void Time0() interrupt 1
{
	T0_count ++ ;//每次0.1ms加一
	if(T0_count == 5)
	{
		led = ~led ;
		T0_count = 0 ;
	}
}
void main(void)
{
	Time0_Init() ; // 定时器0初始化
	led = 0 ;
	while(1)
	{
	}
}

感觉自己水水的,请多指教。

2020-04-23 19:31:49 qq_44139826 阅读数 1130

51单片机作业,自己网上查资料,看课本,弄了一个下午加一个晚上,这个专业真的太苦逼!
需要的小伙伴看看吧
要求:现有AT89S51单片机、2按键和2位数码管,电路形式不限制,利用Proteus设计一电路并完成仿真调试,实现如下功能:上电后数码管显示00,按K1键,数码管每秒自动加1顺序显示00~99,中途再次按K1键则暂停计数;按K2键则显示00并停止计数。
keil程序:

#include<reg52.h>
sbit led0 = P0^0;  
sbit led1 = P0^1;  
typedef unsigned int uint;
void display(uint i,uint j); 
void delay_xms(uint x);
uint i,j;
uint k=0;
uint s=1;
uint sum=0;
unsigned char code DSY_CODE[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管共阳极 
void delay_xms(uint x)//延时函数
{
 uint m,n;
 for(m=0;m<x;m++)
 {
  for(n=0;n<113;n++);
 }
}
void EX0_INT(void) interrupt 0 //中断函数
{
 k=!k;   
}
void EX1_INT(void) interrupt 2//中断函数
{
    s=!s;
}
void display(uint i,uint j) //显示函数
{
 i = sum/10;   
 j = sum%10; 
  led1=0;
 P2=DSY_CODE[i];
 led0=1;
 delay_xms(500);
 
 led0=0;
 P2=DSY_CODE[j];
 led1=1;
 delay_xms(500);
 
 sum++;
 if(sum==100)
  sum=0;
}
void main()
{
 IE = 0X85;
 IT0 = 1;
 IT1 = 1;
 i = sum/10;   
 P2=DSY_CODE[i];
 while(1)
 {
  while(s==0)
  {
   sum=0;
   i = sum/10; 
   led0=1;
   led1=1;
     P2=DSY_CODE[i];
  }
  while(k==1&s==1)
  display(i,j);
 } 
}

proteus模拟图:
在这里插入图片描述

程序可以直接复制粘贴运行,然后仿真,对你有用的话点个赞吧,忙了一天了!