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

📄 ayb380-n0-v4.0-vip.c

📁 使用PIC系列单片机的双机单总线通信程序
💻 C
字号:
/************************************************
*文件名:AYB380-N0-V4.0-VIP.C
*功能:通用控制盒
*创建信息:2006年10月09日   sanjin555@126.com
*最后修改日期:2006年10月12日
*公司:上海超艺电子有限公司
************************************************/
//功能修改:从机时红色指示灯忽闪忽闪
//声音较高时,保持持续亮,使用延时标志
//功能扩展:新增加闪烁模式,旋钮可以调节闪烁频率,尚未校准09,26

//此程序已经OK,单总线终于可以精确到位了,哈哈!
#include <pic.h>
#include <delay.h>
#include <math.h>
#define key_sw 	  RA7//手动开关
#define adc_mic   RA1//麦克风A/D转换口
#define key_mod   RA2//模式切换键
#define t_sign    RA6//控制从机口
#define adc_sens  RA0//灵敏度检测口
#define r_sign RB0//中断口与接受信号口
#define led1   RB1//灯1控制口
#define led2   RB3//灯2控制口
#define led3   RB4//灯3控制口
#define led4   RB5//灯4控制口

#define pwm_o  RB2//指示灯PWM控制
#define spow_c RB6//从机电源控制口
#define indi_c RB7//指示灯电源口

//#define ON()   PORTB=PORTB|0x3a //B"00111010"
//#define OFF()  PORTB=PORTB&0xc5 //0b"11000101"

#define  ctrlmod_addr     0x02
unsigned char ctrlmod_data,ctrlmod_count,ctr_cnt,int_count,trims_data;
unsigned char swmod_data;//向EEPROM些数据,已方便下次做主机时的模式判别

volatile unsigned char pwmdata,cmd;  
persistent bit msmod_f,swmod_f,delay_f,add_f,ctrlmod_f,flash_f,flag1,slow_f,flag2,flag3;
unsigned char admic_data,adsens_data,delay_count,temp1,count,light_value,loop_times,loop_count;
unsigned char temp,tmp,c[2];

void ON(){
PORTB=PORTB|0x3a;
}

void OFF(){
 PORTB=PORTB&0xc5;
}
void flash_a(void)
  {PORTB=PORTB|0x12;
   CCPR1L=0 ;
   c[0]=0x05;
   
   
   indi_c=1;}//B"00111010"
void flash_b() {
 PORTB=PORTB|0x28; 
 CCPR1L=255;
  c[0]=0x0a;
 indi_c=1;} //B"00111010"

void flash_ab(){
 ON();
  c[0]=0xaa;
 indi_c=1;
  CCPR1L=50;
}
void servant(void);
void key_pro(void);
void master(void);
void transmit(void);
void mod1(unsigned char i,unsigned char j);//连闪模式的函数调用
void mod2(void);//
void mod3(void);//
void mod4(void);
void main (void)
{
//	init();
//**********************************************************
        OPTION=0X0F;
     	OSCCON=0x6F;//4Mhz
	//禁用看门狗与配置系统时钟模式均可以在烧写时设置
	//配置中断
	TRISA=0xbf;//设置RA6为输出,其他为输入模式
	TRISB=0x01;//设置RB0为输入,其他为输出模式
//中断设置
   	
	INTE=1;//开外部引脚中断
	PEIE=1;//允许外部中断
	INTF=0;//清外部中断标志
	GIE=1; //开总中断
	INTEDG=0;//下降沿触发
//ADC配置
	ADCON1=0x04;//设置左对齐格式,并选择通道0、1作为转换口
				//选择VCC为参考电压,具体通道在转换时才选择
//PWM配置	
	CCP1CON=0b11001100;//配置RB2为PWM输出
	PR2=99;//设置PWM频率
	T2CON=0B10000100;//使能时钟
	//PWM周期=[(PR2)+ 1]*4*TOSC*(TMR2 预分频比),用时间单位表示10k
	//设置PWM的占空比
	spow_c=1;//开从机和所有控制设备的电源
	indi_c=1;//开显示
	msmod_f=1;//自设为主机模式	
    
     t_sign=1;//向下位机发信号
    ctrlmod_count=0;
    ctr_cnt=0;
    swmod_f=0;//关电源
//	ctrlmod_data = EEPROM_READ(ctrlmod_addr);////ctrlmod,声控标志位
	t_sign=0;
     DelayUs(10); 
   	t_sign=0;
   	delay_f=1;//延时标志
//**********************************************************
	while(1)
	{    CLRWDT();
		 count++;
		if(msmod_f)master();
		else servant();
	
	}
}



//*******************************************************
void master(void)
{		unsigned char temp1,temp2,delay_count;  
	     key_pro();	
	
    if(swmod_f)//电源开
	    {   t_sign=1;
            if(ctrlmod_count==0){
                indi_c=1;
               if(delay_f/*&&count==160*/)	//麦克风控制模式
	            {     
	                 ADCON0=0x05; //时钟为f/2,选择通道1,启动转换"00001101"
		          	while(GODONE){;}//等待转换完成

                   	adsens_data=ADRESH+8;//采用左对齐,忽略低两位数据

             		CCPR1L=adsens_data/2;

		       		ADCON0=0x0d;//时钟为f/2选择通道0,启动转换
	           		while(GODONE){;}//等待A/D转换完毕
		      		admic_data=ADRESH;//采用左对齐,忽略低两位数据
//****************软件调节声音的AD转换值**************
                    
                    
		      		if(admic_data>adsens_data){
			       			ON();
			       			delay_f=1;
			        		c[0]=0xA5;//
			      		 }			
		       		else {
                        slow_f=1;
                        light_value=15;
                        	delay_f=0;//不延时采样
			   		}//判断输出的大小


	       	  }
	       	  
              else if(slow_f){
                          loop_count++;
                       if(loop_count>15){loop_count=0;light_value--;}
                     if(light_value>loop_count){ON();	c[0]=0xA5;}
                     else {OFF();	c[0]=0xF0;}//

                   transmit();
                    key_pro();
                   if(light_value==1)slow_f=0;
                    ADCON0=0x05; //时钟为f/2,选择通道1,启动转换"00001101"
		          	while(GODONE){;}//等待转换完成
                   	adsens_data=ADRESH;//采用左对齐,忽略低两位数据
                	ADCON0=0x0d;//时钟为f/2选择通道0,启动转换
	           		while(GODONE){;}//等待A/D转换完毕
		      		admic_data=ADRESH;//采用左对齐,忽略低两位数据
		      		if(admic_data>adsens_data){
                             light_value=17;
			      		 }			             
                  }
	       	  else if(!delay_f&&!slow_f)//关灯的时候 加快采样速度,来判断是否真的已经关掉
	               {
		                ADCON0=0x05; //时钟为f/2,选择通道1,启动转换"00001101"
		          	while(GODONE){;}//等待转换完成

                   	adsens_data=ADRESH+8;//采用左对齐,忽略低两位数据
             		CCPR1L=adsens_data/2;              
		       		ADCON0=0x0d;//时钟为f/2选择通道0,启动转换
	           		while(GODONE){;}//等待A/D转换完毕
		      		admic_data=ADRESH;//采用左对齐,忽略低两位数据
//****************软件调节声音的AD转换值**************
                     //if(admic_dat  

		      		if(admic_data>adsens_data){
			       			ON();
			       			delay_f=1;
			        		c[0]=0xA5;//
			      		 }			
		       		else {
			       		delay_f=0;//不延时采样
			      		 OFF();
                   		c[0]=0xF0;//
			   		}//判断输出的大小
		           }
	            //	transmit();////////////////
                 }
         else  if(ctrlmod_count==1)
           {    	transmit();
                for(delay_count=200;delay_count>0;delay_count--)
                {DelayUs(250); 	key_pro(); 
                     }
              ON();c[0]=0xA5;//显示红色色
	            indi_c=1;CCPR1L=100;
             }

         else  /*if(ctrlmod_count>1)*/{
                    indi_c=1;
                    ctr_cnt++;              
  			    	switch(ctrlmod_count)
  			    	{
                    case 0:
                     case 1:
  		  	    	case 2:  mod1(2,2);break;//交叉单闪
  				    case 3: mod1(4,6);flag2=1;break;//交叉三连闪
  				    case 4:mod2();break;//乱闪
  				    case 5: mod3();break;//交叉加同闪
  				    case 6: mod1(6,10);flag2=1;break;//交叉五连闪
  				    case 7: mod4();break;//交叉四连闪再交叉4单闪
  			 	    default:break;
  				    }		
               	transmit();////////////////////////

             	ADCON0=0x0d; //时钟为f/2,选择通道1,启动转换"00001101"//????????
		          	while(GODONE){;}//等待转换完成
                   	adsens_data=ADRESH/8;//采用左对齐,忽略低两位数据
                   	for(;adsens_data>0;adsens_data--){
                     for(delay_count=15;delay_count>0;delay_count--){ 

               
                     	DelayUs(250);
	                 	key_pro(); 
                     }
	               }

                if(flag2){OFF();  
                        indi_c=0;
                        c[0]=0x0f;
                         }
                    transmit();/////////////////////
                   	adsens_data=ADRESH/8;//采用左对齐,忽略低两位数据
                   	for(;adsens_data>0;adsens_data--){  
                     for(delay_count=20;delay_count>0;delay_count--){ 
                        
                     //	transmit();
                     	DelayUs(250);
	                 	key_pro(); 
                     }
	               }
                   
                  		  
  			      
           }

      }   
  else {//电源关
	  OFF(); 
     c[0]=0x07;//电源关 指示灯灭
     indi_c=0;
    }

     if(count==8)transmit();//△1
   //  if(count==38)//△1
    //      {
     //     transmit();//调用发送
	     //count=0;
    //    }
}


//***************连闪模式***************
void mod1(unsigned char i,unsigned char j)
{	
		
	if(ctr_cnt<i)flash_a();
	else if (ctr_cnt<j)flash_b();	
   if(ctr_cnt==j){ctr_cnt=0;flash_b();}
   if(ctr_cnt>j)ctr_cnt=0;
}


//*************乱闪***********
void mod2 (void)
{ 
    if(ctr_cnt<6)flash_a();
    else if(ctr_cnt<11)flash_b();//B5
    else if(ctr_cnt<16)flash_a();//A5
    else if(ctr_cnt<21)flash_b();//B5
    else if(ctr_cnt<26)flash_a();//A5
    else if(ctr_cnt<31)flash_b();//B5
    else if(ctr_cnt<34)flash_a();//A3
    else if(ctr_cnt<37)flash_b();//B3
    else if(ctr_cnt<40)flash_a();//A3
    else if(ctr_cnt<43)flash_b();//B3
    else if(ctr_cnt<46)flash_a();//A3
    else if(ctr_cnt<49)flash_b();//B3
    else if(ctr_cnt<52)flash_a();//A3
    else if(ctr_cnt<55)flash_b();//B3    
    else if(ctr_cnt%2)flash_a();//A
    else flash_b();//B3    
	if(ctr_cnt==72)ctr_cnt=0;
}

//**************先四连闪在单闪*****
void mod3 (void)
{	

	if(ctr_cnt<12&&ctr_cnt%2)flash_a();
	else if(ctr_cnt<12&&(ctr_cnt%2==0))flash_b();
	
	
	else if(ctr_cnt==13){flash_ab();slow_f=0;}
	else if(ctr_cnt==14)flag2=1;
	else if(ctr_cnt==16){flash_ab();flag2=0;}
	else if(ctr_cnt==17)flag2=1;
	else if(ctr_cnt==19){flash_ab();flag2=0;}
	else if(ctr_cnt==20)flag2=1;
	else if(ctr_cnt>21&&ctr_cnt<33&&ctr_cnt%2)flash_b();
	else if(ctr_cnt>21&&ctr_cnt<33&&(ctr_cnt%2==0))flash_a();	
	else if(ctr_cnt==34){flash_ab();flag2=0;}
	else if(ctr_cnt==35)flag2=1;
	else if(ctr_cnt==37){flash_ab();flag2=0;}
	else if(ctr_cnt==38)flag2=1;
	else if(ctr_cnt==40){flash_ab();flag2=0;}
	else if(ctr_cnt==41)flag2=1;
	else if(ctr_cnt==42)ctr_cnt=0;


}

//*********************单闪*******
void mod4(void)
{

	if(ctr_cnt<5)flash_a();
	else if(ctr_cnt<9)flash_b();
	else if(ctr_cnt<13)flash_a();
	else if(ctr_cnt<17)flash_b();
	else if(ctr_cnt<21)flash_a();
	else if(ctr_cnt<25)flash_b();
	else if(ctr_cnt%2)flash_a();
	else {flash_b();}
	if(ctr_cnt==36)ctr_cnt=0;
}


void transmit(void)
{       CLRWDT();
     	t_sign=0;
    	DelayUs(3);
       t_sign=1;//防止因设置的问题而引起的错误
    	t_sign=0;
    	DelayUs(50);//产生中断信号并等待从机处理现场保护
        trims_data=c[0];
    	tmp=8;
    	t_sign=1;//发开始标志
         // DelayUs(1);
       for(;tmp>0;tmp--) {
          if (trims_data&0x0001) {
          t_sign=1;
        t_sign=1;
          t_sign=1;
     	  t_sign=1;
     	  t_sign=1;

          }
          else {
          t_sign=0 ;
         t_sign=0 ;
          t_sign=0 ;
          t_sign=0 ;
          t_sign=0 ;
         }
       
       DelayUs(10);  
          trims_data>>=1;
          }  
         DelayUs(20);

     t_sign=1;
    

}





void servant(void)
{   if(flag3){CCPR1L=pwmdata;
    if(c[0]<0x20&&c[0]>0)indi_c=0; //按键关则关 
    if(add_f){ pwmdata++;
        for(delay_count=20;delay_count>0;delay_count--)DelayUs(250);
        

       if(pwmdata>100)add_f=0;
     }
    else {
           pwmdata--;
        for(delay_count=1;delay_count>0;delay_count--)DelayUs(250);
       if(pwmdata==0)add_f=1;
       
     }
   }
	
}
//按键处理程序**************************
void key_pro(void)
{//SW键处理
    unsigned char i;
	if(!key_sw)
	{   for(i=100;i>0;i--)DelayUs(250);
		if(!key_sw){
			 swmod_f=!swmod_f;
		   OFF(); 
		while(!key_sw);//WAITE
     	}	
	    }
	//控制模式键处理
	if(swmod_f&&!key_mod)
	{   for(i=100;i>0;i--)DelayUs(250);
	
		if(!key_mod) {
			ctrlmod_count++;//=!ctrlmod_f;
			if(ctrlmod_count>7)ctrlmod_count=0;
           ctr_cnt=0;
            OFF(); 
		while(!key_mod);

		}
	}
}


//**********按键处理结束****************	
static void interrupt isr(void)	 	//中断程序只执行一次,用来判断主从模式
{									//出现中断,表明本机应该工作在从机状态
 	t_sign=0;	
	INTE=0;//OFF外部引脚中断
	PEIE=0;//NO允许外部中断
	INTF=0;//清外部中断标志
   GIE=0;
	TRISB=0x01;//设置RB0为输入,其他为输出模式
			// clear the interrupt
	//关闭中断,永远不会在执行
	if(msmod_f)msmod_f=0;			//设置为从机模式	
    
//	DelayUs(10);  

      
        tmp=0x01;
        c[0]=0;
       temp1=8;
	 while(!r_sign);//WAIT
	 	DelayUs(8);
		t_sign=1;
   for(;temp1>0;temp1--)  
 	{  t_sign=r_sign;  
    if (t_sign)     // "1" presented
   c[0] |= tmp;
   tmp=tmp<<1;
  	DelayUs(10); 
	 }
  
	 DelayUs(20);
	 t_sign=1;
	if(c[0]==0xa5){ON(); indi_c=1;flag3=1;}
    else if(c[0]==0x05){flash_a(); CCPR1L=0;flag3=0;}
    else if(c[0]==0x0a){flash_b(); CCPR1L=100;flag3=0;}
    else if(c[0]==0xaa){flash_ab(); CCPR1L=50;flag3=0;}
	else{ OFF();
         if(c[0]<0x20)indi_c=0;//声控关仍然开显示
         else indi_c=1;//判断是声控关还是电源关
        }	
   int_count++;
  if(int_count>100){int_count=0;
    if(add_f){ pwmdata++; 
       if(pwmdata>100){add_f=0;pwmdata=100;}
     }
    else {pwmdata--;
      if(pwmdata==1)add_f=1;
      }
  }
	INTE=1;//开外部引脚中断
	PEIE=1;//允许外部中断
	INTF=0;//清外部中断标志
     GIE=1;
  
}

⌨️ 快捷键说明

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