51单片机动态数码管+定时器
我想实现每过一秒使数码管自动加一
但是实现不了,把代码贴上,麻烦各位指点下……
- #include <reg52.h>
- #define TIME 50000
- char t_time = 0;
- char thr_bit = 0,thou_bit = 0; //thr_bit是百位,thou_bit是千位
- int sin_bit = 0,dou_bit = 0; //sin_bit是个位,dou_bit是十位
- char code bit_chosen[]={
- 0XBF,0XDF,0XEF,0XF7
- }; //choose the bit
-
- char code p_digit[] ={ //positive
- 0XC0,0XF9,0XA4,0XB0, //0~3
- 0X99,0X92,0X82,0XF8, //4~7
- 0X80,0X90,0X88,0X83, //8~B
- 0XC6,0XA1,0X86,0X8E //C~F
- };
- char code n_digit[]={ //negative
- 0XC0,0XCF,0XA4,0X86, //0~3
- 0X8B,0X92,0X90,0XC7, //4~7
- 0X80,0X82,0X81,0X98, //8~B
- 0X98,0X98,0X98,0X98, //C~F
- };
- void delay();
- void main(void)
- {
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- TH0 = (65536-TIME)/256; //?1
- TL0 = (65536-TIME)%256;
- while(1) //因为倒置的数码管,所以有两个需要倒置数字的code
- { //bit_chosen数组是位选,加了注释,尽量增加可读性了
- //如果有什么细节没讲到,我可以继续解释。
- P2 = bit_chosen[3];
- P0 = n_digit[sin_bit%10];
- delay();
- P2 = bit_chosen[2];
- P0 = n_digit[dou_bit%10];
- delay();
- P2 = bit_chosen[1];
- P0 = p_digit[thr_bit%10];
- delay();
- P2 = bit_chosen[0];
- P0 = p_digit[thou_bit%10];
- delay();
- }
-
-
- }
- void delay()
- {
- int i,j;
- for(i<50;i;i++)
- for(j=1;j;j--);
- }
- void timer() interrupt 1
- {
- TH0 = (65536-TIME)/256;
- TL0 = (65536-TIME)%256;
- t_time++;
-
-
- if(t_time ==40) //晶振24M,定时1s
- {
- sin_bit++; //过一秒加1
-
- if(!(sin_bit%10)) //10秒,十位加1
- dou_bit++;
- if(!(sin_bit%100)) //100s,百位加1
- thr_bit++;
- if(!(sin_bit%1000)) //1000s,千位加1
- thou_bit++;
- if(!(thou_bit%10000)) //9999之后归0
- sin_bit=0;
- }
-
- }
用tab排版之后可移植性果然差了很多……
顺便还有几个小问题。
1、主函数里面依然需要设置
TH0 = (65536-TIME)/256;
TL0 = (65536-TIME)%256;
吗?
因为我不了解具体的定时器的工作,是独立于CPU的么?
那样在interrupt 1 里面已经设置了
TH0 = (65536-TIME)/256;
TL0 = (65536-TIME)%256;
上电之后定时器就应该开始跑了吧……那在主函数里面再初始化不是很多余么。
呃呃呃呃呃呃呃
已解决
1、delay那个函数没写对,太粗心
2、TMOD没设置
3、99~100那句,thou_bit初始为0,所以sin_bit始终是0,这是最后debug出来的
首先,你的这个代码不够规范 工程首先要有一个总的说明与描述 然后每个函数都要有说明功能返回值,还有 语句 对齐与空格 还有注释 这些都很重要 一定要养成良好的习惯 不然程序一多了 自己先乱了 找错都费劲
其次,调试时有技巧的 分步,分功能去调试,我打个比方 四个数码管弄不清楚的话就一个一个来
最后,要有耐心,这是最关键的!也是最重要的
解决了就好
看看…………。……。……。…。……。…。…。……………。
谢谢你的点评
以后我会注意你所说的细节
分享一下自己写的程序
/*==========================================================
* 开发人员:laowang
* 当前版本:V1.0
* 创建时间:11/21/2013
* 修改时间:
* 功能说明:用定时器中断实现数码管的动态扫描,大家可以对比用普通的delay()函数来实现动态扫描有什么区别
*==========================================================*/
#include <reg52.h> //单片机头文件
sbit dula = P3^4; //段选
sbit wela = P3^5; //位选
unsigned char num1; //定义一个变量,用来对定时器中断进行计数
unsigned char code table1[]= //数码管(共阴)的段选编码,范围是0-F
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
unsigned char code table2[]= //数码管的位选编码,范围是1-8
{
0xfe,0xfd,0xfb,0xf7, //例如,0xfe=1111 1110 点亮第一个数码管
0xef,0xdf,0xbf,0x7f
};
/*==========================================================
*函数名称:Init()
*功 能:对定时器进行初始化
*入口参数:
*出口参数:
*说 明:定时器0,工作方式为1
*==========================================================*/
void Init()
{
TMOD = 0x01; // 定时器工作方式为1
TH0 = 63536/256; //赋初值,此处设定的中断时间为2ms,(65536-2000)/256
TL0 = 63536%256;
EA = 1; //开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //开启定时器
}
//主函数
void main()
{
Init(); //初始化
while(1); //程序一直在空循环,如果有中断发生,则去执行中断(进行数码管显示),
//平时执行空循环
}
/*==========================================================
*函数名称:Timer0()
*功 能:定时器中断服务内容
*入口参数:
*出口参数:
*说 明:
*==========================================================*/
void Timer0() interrupt 1 //中断序号为1
{
TH0 = 63536/256; //每次中断发生后,先进行赋初值
TL0 = 63536%256;
//以下部分为数码管的显示部分
P1=table1[num1+1]; //段选信号,将这一语句放在前面有消影的作用
dula=1;
dula=0;
P1=table2[num1]; //位选信号
wela=1;
wela=0;
num1++; //对定时器的中断进行计数,每中断一次,数码管更换一次内容
if(num1==8)
num1=0;
}
请问 你这个有汇编语言的吗?
