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

📄 main.c

📁 从零开始学51单片机源代码
💻 C
字号:
// Target : STC12C5A60S2 
// Crystal: 11.0592Mhz	
#include <reg52.h> 
#include "fun.h" 

//声明 
void init_devices(void);

void port_init(void)
{
 //设置P3.2~P3.4为输入,P3.5~P3.7为开漏输出 		 
 P3M1 = 0xfc;	//1111 1100
 P3M0 = 0xe0;	//1110 0000
 //设置P2.0为开漏输出 
 P2M1=0X01;
 P2M0=0X01;

 d_vote = 1;	//关闭投票指示灯 
 //关闭d1 d2 d3 ,按键s1 s2 s3为高电平 
 P3 = 0xff;
 
 //设置P1.4为推挽输出,P1.0、P1.7为高阻输入(AD转换用) 
 P1M1 = 0x81;	//1000 0001
 P1M0 = 0x10;	//0001 0000


 m_power = 0; //打开无线模块电源 
}

//Watchdog initialize
//约568.8ms
void watchdog_init(void)
{
 WDT_CONTR = 0x33;//启动定时器,11.0592MHz晶振下,溢出时间568.8ms
}


//外部中断0
void  INT0_interrupt() interrupt 0
{
 //external interupt on INT0
 //关外部中断0、外部中断1
 IE &= 0xfa;  //1111 1010

 m_power = 0; //打开无线模块电源  
 d_vote = 1;	//关闭投票指示灯  
 P3 |= 0xe0;   //关闭d1 d2 d3 
 
 d3 = 0;  //点亮d3
 msdelay(500);
 WDR();	//喂狗 
 d2 = 0;  //点亮d2
 msdelay(500);
 WDR(); 
 d1 = 0;  //点亮d1
 msdelay(500);
 WDR();
 d_vote = 0;  //点亮 d_vote
 msdelay(500);
 WDR(); 

 init_devices();

 m_power = 0; //打开无线模块电源  
 d_vote = 1;	//关闭投票指示灯  
 P3 |= 0xe0;   //关闭d1 d2 d3
}

//外部中断1
void  INT1_interrupt() interrupt 2
{
 //external interupt on INT1
 //关外部中断0、外部中断1
 IE &= 0xfa;  //111 1010

 m_power = 0; //打开无线模块电源 
 
 //LED从下到上依次点亮  
 d_vote = 1;	//关闭投票指示灯  
 P3 |= 0xe0;   //关闭d1 d2 d3 
 
 d3 = 0;  //点亮d3
 msdelay(500);
 WDR();	//喂狗 
 d2 = 0;  //点亮d2
 msdelay(500);
 WDR(); 
 d1 = 0;  //点亮d1
 msdelay(500);
 WDR();
 d_vote = 0;  //点亮 d_vote
 msdelay(500);
 WDR(); 

 init_devices();

 m_power = 0; //打开无线模块电源  
 d_vote = 1;	//关闭投票指示灯  
 P3 |= 0xe0;   //关闭d1 d2 d3
}

//TIMER0 initialize 
// desired value: 16mSec
// actual value: 16mSec 
void timer0_init()
{
	AUXR &=0x7F; //T0x12 = 0,定时器0使用12分频 

	TMOD |= 0X01;
	TH0 = T0_16ms >> 8;
	TL0 = T0_16ms,
	ET0 = 1; //允许T0中断 
}

//定时器0中断 ,16ms一次 
void Timer0_interrupt() interrupt 1
{
	//重装初值 
 	TH0 = T0_16ms >> 8;	   //TH0 = T0_16ms / 256 = 0xc6
	TL0 = T0_16ms;			//TL0 = T0_16ms % 256 = 0x66	
  
  cnt++;
  if (cnt==me) //轮到自己发 
  {  
    if  (addr!=0)//地址没有问题,可以发送  
	{    
	TR0 = 0; //关定时器 
	REN = 0; //禁止接收数据          
	putchar(sent[0]);
	putchar(sent[1]);
	putchar(sent[2]);	 
	REN = 1; //允许接收数据  
	}
	else
	{
	 TR0 = 0; //关定时器 
	 REN = 1; //允许接收数据 
	}									    
  }
}

//TIMER2 initialize 
// desired value: 50mSec
// actual value: 50.000mSec (0.0%)
void timer1_init()
{
	AUXR &=0xbF; //T1x12 = 0,定时器1使用12分频 

	TMOD |= 0X10;	//定时器1模式1,16bit
	TH1 = T1_50ms >> 8;	  
	TL1 = T1_50ms;				
	ET1 = 1; //允许T1中断 
}

//定时器1中断 ,50ms一次 
void Timer1_interrupt() interrupt 3
{
 //重装初值 
 TH1 = T1_50ms >> 8;
 TL1 = T1_50ms;
 time++;   //按键计时 
 time_f++;	//空闲计时 
 if (time==10) //按键之后500ms
 {
   //关按键灯 
   P3 |= 0xe0; //关d1 d2 d3
 }
 
 if (time==40)//按键之后2S
 {
   key1=0; //进入工厂模式步骤清零 
 }
 
 if (time_f==10) //500ms未接收到数据 
 {
   recnum=0; //接收数据清零 
 }
 
 if (time_f==1200) //1分钟未接收到数据 没有按键 
 {
   sleep(); //休眠 power down
 }
}

//UART0 initialize
// desired baud rate: 9600
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
 	//BRTR=1允许BRT  BRTx12=1   S1BRS = 1使用BRT
 	AUXR |=0x15; //0001 0101 
	//方式1,8 N 1,允许接收 
	SCON = 0x50; //SM0 = 0,SM1=1,REN=1; 

	//11.0592MHz,9600
	BRT =  256 - (fosc/32/9600); //BRT = 0xdc	
	ES = 1; //允许串口中断 
}

//串口中断 
void  USART_interrupt() interrupt 4
{
 //uart has received a character in SBUF  
 unsigned int i;

//如果是接收中断 
if (RI)
{
 RI=0; //清接收中断 
 time_f=0;  //空闲时间计数器清零

  disable(); //关闭定时器0、定时器1、ADC转换

 //防止缓冲区数组溢出错误 
 if (recnum < 5)
 { 
  rec[recnum]=SBUF;
  recnum++;	  //接收计数指针+1

	loop:  	//开始处理流程 
  	if (recnum>2)	 //至少收了3个数据 
  	{
   	 	if ((rec[0]&0x0c)==0x00 && ((rec[0]&0x80)==0x00))  //包头正确  上位机下发的 
	 	{
	    	//计算校验 
	    	checkXOR=rec[0] ^ rec[1];
				
			if ((checkXOR==rec[2])) //校验正确 
			{
				recieve();  //当作协议处理 
				recnum=0;	//接收清零 

				goto loop1;	//跳走 
			}
			else  //校验不正确 
			{
				//缓冲区整体前移 
		 		for (i=1;i<recnum;i++)
	     		{
			 		rec[i-1]=rec[i];
		 		}
		 		recnum--;

		 		if (recnum<=0) //接收缓冲区没有数据了 
		 		{
			 		//计数器清零,开中断返回
		     		recnum=0;
					goto loop1;
		 		}
		 		else    //接收缓冲区还有数据
		 		{
		   			goto loop; //跳回去再检查 
		 		}
			}
	 	}
	 	else  //不是包头 
	 	{
	  	 	//缓冲区整体前移 
		 	for (i=1;i<recnum;i++)
	     	{
			 	rec[i-1]=rec[i];
		 	}
		 	recnum--;

		 	if (recnum<=0) //接收缓冲区没有数据了 
		 	{
			 	//计数器清零,开中断返回
		    	 recnum=0;
				 goto loop1;  //跳走 
		 	}
		 	else  //接收缓冲区还有数据 
		 	{
		   		goto loop;  //跳回去再检查 
		 	}
	 	}
  	}
  	else  //<=2
  	{
		//什么也不做,开中断返回主程序,等待接收下一个数据 
  	}
  }
  else //如果recnum >=5,缓冲区溢出 
  {
   	recnum = 0; //全部清空 
	// 开中断返回主程序,等待接收下一个数据 
  }
loop1:	//结束处理流程 
  enable(); //开中断返回
}

	//如果是发送中断 
  	if (TI)
	{
		TI = 0; //清除发送中断
	}

}

//ADC initialize
// Conversion time: 48uS
void adc_init(void)
{
 	P1ASF = 0x00; //P1.0用作AD转换 
	//转换结果清零 
	ADC_RES = 0;
	ADC_RESL = 0;

	//ADC_POWER=1,SPEED1=0,SPEED0=0,
	//ADC_FLAG=0,ADC_START=0,CHS2/CHS1/CHS0=000
	//11.0592MHz,540个时钟周期转换一次,速度约125KHz,时间约 48us
	ADC_CONTR = 0X80;
	//等待4周期	  
	_nop_();	
	_nop_();
	_nop_();
	_nop_();
	//ADRJ = 0,ADC_RES寄存器保存10位A/D转换结果的高8位,ADC_RESL保存结果的低2位 
	AUXR1 &= 0xfb; 
}

//AD转换中断
void  ADC_interrupt() interrupt 5
{
	ADC_CONTR &= 0Xef;	//ADC_FLAG清零 
	//计算电压值 
	ad_result10 = ADC_RES;
	ad_result10 = ( ad_result10 << 2 ) | ADC_RESL;

	f_adconverting = 0;
}


//call this routine to initialize all peripherals
void init_devices(void)
{
 char i=0;
 //stop errant interrupts until set up
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 EA = 0; //disable all interrupts
 port_init();
 watchdog_init();  //设置且启动看门狗 
 timer0_init();
 timer1_init();
 uart0_init();
 adc_init();

 PCON &= 0xfd; //关闭power down模式,PD位置0

 //all peripherals are now initialized
 //按键清零 
 ty=0;
 qq=0;
 fd=0;
 key0=0;
 key1=0;
 //时间、计数清零 
 time=0;
 time_m=0;
 time_f=0;  
 cnt=0; 

 //状态清零 
 f_start=0;
 f_sleep=0;
 f_volt=0;
 f_adconverting = 0;
 
 readset();//读取本机地址 
 me=addr;
 WDR();	  //喂狗 
 
 //刚上电,AD不准,多检查一次 
 checkpower(); //检查电源 
 WDR();
 checkpower();
 WDR();
 
 if (vin<1.75)  //如果需要充电 
 {
    //灯全关 
	d_vote = 1;
	P3 |= 0xe0; 
	for (i=0;i<5;i++)
	{	//闪烁5次d_vote
		d_vote=0;	 //亮d_vote
		msdelay(500);
		WDR();
		d_vote=1;	//灭d_vote
		msdelay(500);
		WDR(); //喂狗 
	}
 }
}


void main(void)
{
 int i;

 init_devices();
 //insert your functional code here...
 EA = 1;  //开总中断 

while(1)
{
	//关INT0 INT1中断 
   IE &= 0xfa;  //111 1010
   WDR();
   if (recnum>5) //任意时刻接收计数器大于5,清零 
   {
   	  recnum=0;
   }
   
   if (f_sleep==1)	 //休眠标 
   {
           msdelay(10);
	       f_start=0;
		   f_sleep=0;
		   sleep(); //休眠power down
   }

   if (f_volt==1)  //低电提示 
   {
   	  f_volt=0;
	  //灯全关 
	  d_vote = 1;
	  P3 |= 0xe0;
	  for (i=0;i<5;i++)
	  {
		  	//闪烁5次d_vote
			d_vote=0;	 //亮d_vote
			msdelay(500);
			WDR();
			d_vote=1;  //灭d_vote
			msdelay(500);
			WDR();  //喂狗 
	   }
   }

        //---------------------------------------------------
		 if (s1==0)	 //按键S1 P3.4	同意 
		 {
		    ty++;
			time_f=0;
			msdelay(10); 
			if ((s1==0) && (ty==1))
			{
		    	offled(1);	//点亮D1,关闭D2、D3	
				time=0;
				if (f_start==1)	//如果是投票状态 
				{		
					key0=1; 
				}
		    	key1++;						 //按键次数加1
		    	if(key1>3)
				{
					key1=0;			 //按三次
				} 
			}
		 }
		 else
		 {
		   ty=0;
		 }
		 //----------------------------------------------------
		 if ((s2==0)&(s1=1))//s2按下,s1未按,key0=3
		 {
		   qq++;
		   time_f=0;
		   msdelay(10); 
		   if ((s2==0)&(s1=1) & (qq==1))
		   {
		     offled(2);//点亮D2,关闭D1、D3
			 time=0;
		     if (f_start==1)  key0=3;
		     if ((key1>2)&(key1<5))
		     {
     	       key1++; //同意按三次后弃权按过2次
		     }
		     else key1=0;
		   }
		 }
		 else
		 {
		   qq=0;
		 }
		//-------------------------------------------------------- 
		 if (s3==0)			//s3按下,key0=2
		 {
		    fd++;
			time_f=0;
			msdelay(10);
			if ((s3==0) && (fd==1))
		    {
			  offled(3); //点亮D3,关闭D2、D1
			  if (f_start==1)  key0=2;
			  time=0;
			  d3=1;  //关d3
			  if ((key1>4)&(key1<8))
			  {
			    key1++;  //之后反对按3下
			  }
			  else key1=0;
			}
			if(key1==8) //按第3下反对 一整套进入工厂模式动作做完 
			{
				REN=1; //允许串口接收 
				key1=0;
				//offled(1);
				key0=12; //key0=12,编地址状态
			}  
		  }
		  else
		  {
			 fd=0;
		  }
		//-------------------------------------------------
		if(key0==12) //工厂模式
		{
			 //从下往上循环亮灯 
			 //灯全关 
	 		 d_vote = 1;
	  		 P3 |= 0xe0;
		     d3=0;	  //开d3
 			 msdelay(500);
			 WDR();
			 d3=1;	//关d3
 			 d2=0;
 			 msdelay(500);
			 WDR();  //喂狗 
			 d2=1;
 			 d1=0;
 			 msdelay(500);
			 WDR();
			 d1=1;
 			 d_vote=0;
			 msdelay(500);
			 WDR();  //喂狗
			 d_vote=1;
			 
			 time_m++;
		}
		if ((key0==12) && (time_m>5))  //循环超过5次 
 		{
   		    key0=0;
			time_m=0;
   		 	//灯全关 
	  		d_vote = 1;
	  		P3 |= 0xe0;
 		}	
	}
}

⌨️ 快捷键说明

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