mikezhong, 我的地盘. https://passport2.21ic.com/?299497 [收藏] [复制] [RSS]

日志

带红外接收功能的4路音源切换器(电路图+源程序)

已有 3401 次阅读2007-2-6 18:25 |个人分类:MCU|系统分类:单片机| 红外遥控 sc9148a, 单片机

带红外接收功能的4路音源切换器(电路图+源程序)

 

因为我们公司是做音响的,因此经常会需要多台音响进行比对试听,看不同的音箱之间听感有什么不同,因此制作了这一个4路音源切换器.程序中有按键处理,有遥控接收解码,CD4052模拟开关控制,我想对于初学者还是有参考价值的.(和很多人一样,我一开始在处理遥控接收解码时,首先第一步就是在网上寻找例程,可是寻找的结果有点让我失望,有些根本没有价值,有些又太烦琐,搞不懂程序编写者的意图.因此决定自已看sc9148的datasheet,理解后再写遥控接收程序,当我写起来时才发现其实并不是想像中的那么难.愿和大家一起成长)

 

--------功能如下:

 

一.功能介绍:主要用于4种音箱听音对比使用,也可作为多路转接。


1.  一路音源输入,分4路切换输出,同时只有一路输出。


2.  4个按键分别控制4路切换输出。LED分别用于指示对应按键输出的通道。


3.  遥控控制功能,共5个键,其中4个按键为通道选择切换开关,另一个为遥控锁定,以防止音箱遥控相互控制。


 


二.使用说明。


 1.装置上按钮CH1CH2CH3CH4分别对应4路输出CH1CH2CH3CH4及对应的CH1CH2CH3CH4 LED指示,按下对应的按钮,则同一通道LED会点亮,其它通道输出及指示将关闭,同时只能有一路输出。


 


 2.遥控按键 “键码4”, “键码7, “键码8”, “ 键码12 分别对应装置上的按钮CH1CH2CH3CH4通道选择功能。 (遥控发射IC为SC9148A)


 


 3.由于采用了音箱遥控器,在遥控音箱的同时,音源切换装置也会被控制,为避免影响切换装置正常工作,增加了遥控器锁定功能,当需要锁定音源装置,在约1.5秒内连续按下 “MUTE”键三次,装置上遥控锁定LED点亮,此时使用遥控器遥控音箱时,将不会对音源切换装置产生影响(同时装置的通道选择遥控功能不起作用),再次在约1.5秒内连续按下 “MUTE”键三次,取消此功能,遥控锁定LED熄灭。此时,可以进行遥控切换功能。(遥控功能锁定时,切换装置上按钮正常有作用)

 

--------电路图:怎么传不上来?知道的,请告诉我一下.

 

--------程序:(在BLOG中,看到有点乱,你可以copy到你自已的电脑看.)

 

/******************************************************
音箱测试演示用音源切换装置
12M晶振,
定时器计时一次1us.
这个可以了。
main_remote_1.c 可用。
The first version: v1.0 2007.1.15

V1.1:
Adding remote hold function.
Deleted "mute" function.
Date : 2007.1.29
******************************************************/
#include "STC12C2052AD.h"
#include "intrins.h"

sbit  P3_3=P3^3;
sbit  P3_0=P3^0;
sbit  P1_7=P1^7;

#define  channel_0  0xf7
#define  channel_1  0xfb
#define  channel_2  0xfd
#define  channel_3  0xfe
#define  mute       0x55 //不同于上三个的任意值
#define  REMOTE_IN  P3_3

#define  IR_TREBLE  0x0d04
#define  IR_2_1     0x0c81
#define  IR_5_1     0x0c90
#define  IR_AC3     0X0ca0
#define  IR_MUTE    0x0c88

 

#define  LED_channel_0   CH_0_LED=0;CH_1_LED=1;CH_2_LED=1;CH_3_LED=1;
#define  LED_channel_1   CH_0_LED=1;CH_1_LED=0;CH_2_LED=1;CH_3_LED=1;
#define  LED_channel_2   CH_0_LED=1;CH_1_LED=1;CH_2_LED=0;CH_3_LED=1;
#define  LED_channel_3   CH_0_LED=1;CH_1_LED=1;CH_2_LED=1;CH_3_LED=0;

sbit CH_0_LED=P1^4;
sbit CH_1_LED=P1^5;
sbit CH_2_LED=P1^6;
sbit CH_3_LED=P1^7;
sbit CD4052_B=P3^4;
sbit CD4052_A=P3^5;
sbit CD4052_INH=P3^2;

unsigned char key_old,key_temp;
unsigned int key_delay=0;
bit key_ok,remote_ok,mute_ok;


unsigned char remote_temp,P1_state,P3_state;

unsigned char INT1_times,remote_time;
unsigned int remote_value_buff,remote_value,remote_value_first_buff;
bit remote_ok,INT1_ISR_flag,resend,remote_end_ok,hold_ok,within_3_second;
unsigned char remote_hold;
unsigned int hold_count;

void T1_T0_INT1_initial(void);
void Port_initial(void);
void key_scan(void);
void key_action(void);
void delay_10us(unsigned int t);
void remote_action(void);

void timer1_ISR(void) interrupt 3
{
   
    TH1=0XFc;     //1000US
    TL1=0x18;    

 if (INT1_ISR_flag==1)
 {
       remote_time++; //遥控器定时时间,如果在第一个外部中断有下降沿,则开始计时,22MS后结束。
 }
 if (remote_time >=80)//80ms
 {
    INT1_times=0;
    INT1_ISR_flag=0;
    remote_value_first_buff=0;
    remote_value=0;
    remote_time=0;
    resend=0;
 }
 if (remote_hold)
 {
      hold_count++;
   if (hold_count>=1500 /*&& remote_hold>3*/)
     {
    if (remote_hold>2)
    {
     hold_ok=!hold_ok;
     if (hold_ok==1)
     { P3_0=0;} //指示锁死遥控。
     else P3_0=1;
     hold_count=0;
     remote_hold=0;
    }// P1_0=!P1_0; //For testing.
    else {hold_count=0;
         remote_hold=0;}
  }

 }
 else
 {
   hold_count=0;
   within_3_second=0;
   //hold_ok=0;
 }
}
/********************For remote control***********************/
void timer0_ISR(void) interrupt 1 //800us
{
    unsigned char bit_value;
 bit_value=REMOTE_IN;
 if (resend)
 {
      if (bit_value==1)
    { remote_value= remote_value<<1;}
   if (bit_value==0)
    {remote_value=(remote_value<<1)+0x0001;}
      if (INT1_times>=24)
    {
     if (remote_value_first_buff==remote_value)
      {
        remote_value_buff=remote_value;
              resend=0;
              remote_ok=1; // 遥控有效
         }
  }
  }
  else
  {
        if (bit_value==1)
       { remote_value= remote_value<<1;}
     if (bit_value==0)
       {remote_value=(remote_value<<1)+0x0001;}
        if (INT1_times>=12)
       {
         resend=1;
   remote_value_first_buff=remote_value;//第一次接收完毕. 置标志。
   remote_value=0;
       }
  }
    TR0=0;
}
/************************************************************/
void INT1_ISR(void) interrupt 2
{
  TH0=0Xfc;  //800us
  TL0=0Xe0;
  TR0=1;// TR0=1; //Start timer0 for testing pulse level,800us each timer0 interrupt
  INT1_times++;
  if (INT1_times==1)
   {INT1_ISR_flag=1;}
}

/*===================================================*/
void main(void)
{
   Port_initial();
   T1_T0_INT1_initial();
   LED_channel_3;
   EA=1;
   ET1=1;
   ET0=1;
   TR1=1;     //Start Timer1
   EX1=1;
   TR0=0;
   CD4052_INH=0;
   P1_state=(P1|0X0F); //保存LED的状态
   P3_state=(P3|0xcf);
   hold_count=0;
  
   while (1)
   { 
      key_scan();
      key_action();
      remote_action();
   //delay_10us(1); //1ms 100
   }
}

/***********************************************************
 Timer1 was used for bianma switch control ,each 1000us interrupt,
 Timer0 was used for remote control ,each 800us interrupt,
***********************************************************/
void T1_T0_INT1_initial(void)
{
   TMOD=0X11; //Timer1 mode1. 16bit timer.
   TCON=0x04; //enable timer1 interrupt.TF1=1;TR1=0;Enable INT1 fall-edge interrupt.
   TH1=0XFc;  //1000us-->0xfc18
   TL1=0x18; 
   TH0=0Xfc;  //800us-->0xfce0,12MHz Crystal
   TL0=0Xe0; //18.342 800us
}

/************************************************************
  PORT端口初始化
***********************************************************/
void Port_initial(void)
{
 
  P1M0=0X00;//全部为标准I/O口
  P1M1=0X00;
  P3M0=0x00; //P3。3设为输入。
  P3M1=0x00;
  P1=0XFF;
  P3=0Xff;
}
/***********************************************************
key_scan();
***********************************************************/
void key_scan(void)
{
 
  if ((P1|0xf0)!=0xff) //有键
   {
        key_temp=P1|0xf0;
  if (key_temp==key_old)
    {
      key_delay++;
    }
  else key_old=key_temp;
   }
  else
   {
      if (key_delay >=60)
  {
     key_ok=1;
     key_delay=0;
    // return key_temp;//返回键值
  }
 
   }
 
}

/***********************************************************
key_action();
***********************************************************/
void key_action(void)
{
   unsigned char temp;
   if (key_ok)   { temp=key_temp; goto action;}
   if (remote_end_ok==1 && hold_ok==0)
   { remote_end_ok=0;temp=remote_temp; }
   else {temp=0;remote_end_ok=0;}
  
action: switch (temp)
        {
          case channel_0:
           LED_channel_0;//执行按键功能1
                          CD4052_A=0;
              CD4052_B=0;
           P1_state=(P1|0X0F); //保存LED的状态
              P3_state=(P3|0xcf);
              key_ok=0;
              temp=0;
        break;
       case channel_1:
                       LED_channel_1;//执行按键功能2
                          CD4052_A=1;
              CD4052_B=0;
           P1_state=(P1|0X0F); //保存LED的状态
              P3_state=(P3|0xcf);
              key_ok=0;
              temp=0;
           break;
       case channel_2:    LED_channel_2;//执行按键功能3
                          CD4052_A=0;
              CD4052_B=1;
              P1_state=(P1|0X0F); //保存LED的状态
              P3_state=(P3|0xcf);
                             key_ok=0;
              temp=0;
           break;
       case channel_3:    LED_channel_3;//执行按键功能4
                          CD4052_A=1;
              CD4052_B=1;
              P1_state=(P1|0X0F); //保存LED的状态
              P3_state=(P3|0xcf);
              key_ok=0;
              temp=0;
           break;
    case mute:
               remote_end_ok=0;
      temp=0;
      break;
       default:   remote_end_ok=0;
      temp=0;
      break;
       }
 
}
/*********************************************************
  remote_action。
*********************************************************/
void remote_action(void)
{
    if (remote_ok)
 {
    remote_ok=0;
    remote_end_ok=1;
       switch (remote_value_buff)
    {
      case IR_TREBLE: remote_temp=channel_3;  break; //channel_3;
   case IR_2_1:    remote_temp=channel_0;  break; //channel_0;
   case IR_5_1:    remote_temp=channel_1;  break; //channel_1;
   case IR_AC3:    remote_temp=channel_2;  break; //channel_2;
   case IR_MUTE:   remote_temp=mute;
                   remote_hold++; //每次按键有效,则remote_hold 加1
                         break; 
   default: remote_value_buff=0;break;
    }

 }
 
}

 

路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (3 个评论)

回复 游客 2007-2-22 21:17
好!可惜电路原理图没贴上。
回复 hehe 2007-6-2 10:59
电路图能否发给我看看啊? 谢谢阿! ggzzoo@tom.com
回复 d026530 2007-9-3 15:26
电路图能否发给我看看啊? 谢谢阿! d026530@126.com