⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 temp.c

📁 单片机显示程序,通过轮循方式是数码管亮,十分经典
💻 C
字号:
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int

sbit SDA=P3^0;
sbit SCL=P3^1;

sbit Ok_Key=P0^7;
sbit Up_Key=P2^7;
sbit Down_Key=P1^7;

bit Key;
bit Flash;
bit Write;

uchar b;
uchar s;
uchar g;

uint Tcount;
uint TimeCount;
uint TimeSet;
uchar KeyCount; 

//unsigned code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//上面注释的是标准的数码管字形码,由于P0.0、P1.0和P2.0是键盘端口
//所以,就将这些字形码的最高位置1,这样不会对键盘扫描产生负面影响

unsigned code tab[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
//函数列表
void delay(void);
void Delay(int time);
void delay1(void);
void write_8bit(unsigned char ch);
void ACK(void);
uchar ReadIIC_24C01(unsigned char address);
void WriteIIC_24C01(unsigned char address,unsigned char ddata);
void init(void);
void DataDivision(uint Ddata);
void LedFlash(uchar No);
void KBScan(void);
void Display(void);
void delays(void);

//键盘中断服务程序
//首先INT0触发,进入中断服务程序。然后检测是哪个键按下
//如果是Ok_Key按下,检测它处于哪个状态(分为四个状态:修改百位、十位、个位和确认),然后显示对应的要修改信息
//如果下一个外部中断触发,同样确认是哪个键,再根据Ok_Key键所处的状态,对的位进行增加、减少修改,同时也可以进行
//进行数据确认并写入EEPROM,这样,时间设定就完成了,接下来单片机进行倒计时
void intersvr0(void) interrupt 0 using 1
{
	ET0=0;
	TR0=0;	
	if(!Ok_Key)            //中断触发后,确认是哪一个键按下
		{
			if(KeyCount==0)//第一次按Ok_Key键,进入第一个状态,修改百位
			{
				KeyCount++;
				P1=0x80;
				P2=0x80;
				P0=tab[b];	
			}
			else if(KeyCount==1)//第二次按Ok_Key键,进入第二个状态,修改十位
			{
				KeyCount++;
				P0=tab[b];
				P2=tab[s];
				P1=0x80;
			}
			else if(KeyCount==2)//第三次按Ok_Key键,进入第三个状态,修改个位
			{
				KeyCount++;
				P0=tab[b];
				P2=tab[s];
				P1=tab[g];	
			}
			else               //确认,并把数据写入EEPROM
			{
				KeyCount=0;
				Write=1;
			}
		}
		else if(!Up_Key)       //中断触发后,确认是哪一个键按下
		{
			if(KeyCount==1)    //Ok_Key键位于第一个状态,对百位数据进行调整
			{
				if(b==9)
					b=0;
				else
					b=b+1;
				P1=0x80;
				P2=0x80;
				P0=tab[b];
			}
			else if(KeyCount==2) //Ok_Key键位于第二个状态,对百位数据进行调整
			{
				if(s==9)
					s=0;
				else
					s=s+1;
				P1=0x80;
				P2=tab[s];
				P0=tab[b];
			}
			else if(KeyCount==3) //Ok_Key键位于第三个状态,对百位数据进行调整
			{
				if(g==9)
					g=0;
				else
					g=g+1;
				P1=tab[g];
				P2=tab[s];
				P0=tab[b];
			}
			else
				return;
		}
		else if(!Down_Key)      //中断触发后,确认是哪一个键按下
		{
			if(KeyCount==1)     //Ok_Key键位于第一个状态,对百位数据进行调整
			{
				if(b==0)
					b=9;
				else
					b=b-1;
				P1=0x80;
				P2=0x80;
				P0=tab[b];
			}
			else if(KeyCount==2) //Ok_Key键位于第二个状态,对百位数据进行调整
			{	
				if(s==0)
					s=9;
				else
					s=s-1;
				P1=0x80;
				P2=tab[s];
				P0=tab[b];
			}
			else if(KeyCount==3)//Ok_Key键位于第三个状态,对百位数据进行调整
			{	
				if(g==0)
					g=9;
				else
					g=g-1;
				P1=tab[g];
				P2=tab[s];
				P0=tab[b];
			}		
			else
				return;
		}	
}


/////////////////
//12M晶振最大延时为65.536ms,这里延时为50ms
void time0(void) interrupt 1 using 1
{  		
	
	TH0=(65536-50000)/256;             //设置定时器高8位初值
  	TL0=(65536-50000)%256;             //设置定时器低8位初值

	if(Tcount==20)                     //通过调整数字可以确定计数的最小单位
	{                                  //例如,如果为20,表示每1s数码管数据改变一次,如果为1200,则是1m改变一次
		Tcount=0;
		TimeCount=TimeCount-1;         //用来长时间定时
	}
	b=TimeCount/100;                   //将当前数据的百、十、个位分离
	s=(TimeCount/10)%10;
	g=TimeCount%10;

	P0=tab[b];                         //分离后的数据显示到数码管
	P2=tab[s];
	P1=tab[g];
	Tcount=Tcount+1;
}


//短延时函数
void delay(void)
{
	unsigned int i=1200;
	while(i--);
}
//这里,延时30可以使数码管闪烁
void Delay(int time)  
{
	while(time--)	
		delay();
}

/*----------------------------------------------------------------------------
调用方式:write_8bit(unsigned char ch)  ﹫2001/03/23
函数说明:内函数,私有,用户不直接调用。
-------------------------------------------------------------------------------
*/
void  write_8bit(unsigned char ch)
{
    unsigned char i=8;
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    while (i--)
    {
        SDA=(bit)(ch&0x80);
        _nop_();_nop_();_nop_();_nop_();_nop_();
        ch<<=1;
        SCL=1;
        _nop_();_nop_();_nop_();_nop_();_nop_();
        SCL=0;
        _nop_();_nop_();_nop_();_nop_();_nop_();
    }
    _nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();
}

/*------------------------------------------------------------------------------
调用方式:void ACK(void)  ﹫2001/03/23
函数说明:内函数,私有,用户不直接调用。
-------------------------------------------------------------------------------
*/
void ACK(void)
{
   unsigned char time_1;
    SDA=1;
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
    SCL=1;
    time_1=5;
    while(SDA) {if (!time_1) break;} //ACK
    SCL=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();
}


unsigned char ReadIIC_24C01(unsigned char address)
{
      unsigned char ddata=0;
      unsigned char i=8;

    SCL=1;
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();   //Tsu:STA
    SDA=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
    SCL=0;             //START

    write_8bit( (address<<1) | 0x01);   //写页地址和操作方式
    ACK();

    while (i--)
    {
        SDA=1;
        ddata<<=1;
        SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=1;
        if (SDA) ddata|=0x01;
    }

    SCL=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
    SDA=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
        SDA=1;   //STOP
    delay();
    return ddata;

}
void WriteIIC_24C01(unsigned char address,unsigned char ddata)
{

    SCL=1;
    _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();   //Tsu:STA
    SDA=0;
    _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
    SCL=0;             //START

    write_8bit( (address<<1) & 0xfe);   //写页地址和操作方式,对于24C32-24C256,page不起作用

    ACK();
    write_8bit(ddata);      //发送数据
    ACK();
    SDA=0;
        _nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
        SDA=1;   //STOP
        delay();
}
//芯片初始化
void init(void)
{
	uchar i=10;
	Tcount=0;                        //用来产生长延时的标志                      
	KeyCount=0;                      //Ok_Key键所处状态标志
	Write=0;                         //修改后的数据是否写入EEPROM标志
	
	b=ReadIIC_24C01(0x00);           //从EEPROM里读取百位数据
	s=ReadIIC_24C01(0x01);           //从EEPROM里读取十位数据
	g=ReadIIC_24C01(0x02);           //从EEPROM里读取个位数据
	
	TimeSet=b*100+s*10+g;            //根据从EEPROM里读取的数据,计算出预设的时间初值
	TimeCount=TimeSet;	             //所要定时的标志

	while(i--)                       //开机后,将原来所存初始值取出,闪烁10次
	{
		P0=tab[b];
		P2=tab[s];
		P1=tab[g];	
		Delay(50);
		P0=0x80;
		P2=0x80;
		P1=0x80;
		Delay(50);
	}

	EA=1; //开全局中断                                                  
	ET0=1;//开定时器中断
	TR0=1;//开定时器0中断

	EX0=1;//开外部中断
	IT0=1;//开INTO中断
	TH0=(65536-50000)/256;  //设置定时器高8位初值
  	TL0=(65536-50000)%256;  //设置定时器低8位初值
	
}

main()
{
	init();
	while(1)
	{
		if(Write) //如果向EEPROM写标志使能,将调整后的数据写入EEPROM内
		{
			WriteIIC_24C01(0x00,b);
			WriteIIC_24C01(0x01,s);
			WriteIIC_24C01(0x02,g);
			TimeSet=b*100+s*10+g;   //根据设定值来计算出设定值
			TimeCount=TimeSet;	    //将设定值赋给定时标志

			ET0=1;                  //定时器中断使能
			TR0=1;	
			TH0=(65536-50000)/256;  //设置定时器高8位初值
	  		TL0=(65536-50000)%256;  //设置定时器低8位初值*/
			Write=!Write;
		}
		if(TimeCount==0)
		{
			TimeCount=TimeSet;      //如果定时完成,重新开始
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -