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

📄 ledctrl.c

📁 用于摄象机同步控制LED闪光灯的代码,LED闪光是已经倍频过的,不会引起人眼视觉上的闪烁感.
💻 C
字号:
#include <reg51.h>
#include <stdio.h>

 
#define osc 12000000

#define SET_MODE_MAP 0x01; //P1口     P1.0   0:固定模式  1:串口跟踪模式
#define SET_MODE_PORT  P1 ;//

#define SYS_MODE_MAP 0x02; //P1口     P1.1   0:PAL制式   1:NTSC制式
#define SYS_MODE_PORT  P1 ;//

#define T_NTSC   16667   //  NTSC制式视频信号的场同步周期:16667us
#define T_PAL    20000   //  PAL制式视频信号的场同步周期:20000us


#define WIDTH_MAP 0x3F ; //P2口   P2.0---P2.5
#define WIDTH_PORT  P2 ;//

#define PHASE_MAP_H 0xC0 ; //P2口   P2.6 P2.7
#define PHASE_H_PORT  P2 ;//

#define PHASE_MAP_L 0xFF ; //P0口   P0.7--P0.0
#define PHASE_L_PORT  P0 ;//

#define PHASE_MAP 0x03FF ; //


#define PHASE_PORT  P0 ;//


sbit CLEAR_SYNC=P1^2;
sbit SET_LAMP=P1^3;
sbit CLEAR_LAMP=P1^4;

unsigned int  TVSYNC;      //场同步信号的周期时间,单位:us
unsigned int Phase_time;
unsigned int Width_time;
unsigned char Set_Mode;
unsigned char MODE;//temp

unsigned char Sys_Mode;
unsigned char Pre_Sys_Mode;

unsigned char UART_DATA_VALID;


unsigned char Pre_Set_Mode;
unsigned int temp_phase;
unsigned int temp_width;

unsigned int port0_Reg;
unsigned int port2_Reg;
unsigned int Pre_Port0_Reg;
unsigned int Pre_Port2_Reg;

unsigned char Vsync_found; //消息   1:场同步中断已发生   0:已知晓并处理完毕
unsigned char Vsync_INT;  //消息   1:场同步中断已发生   0:已知晓并处理完毕
unsigned char Job_Finished;  //消息   1:工作完成   0:工作未完成

unsigned char TH0_Phase;
unsigned char TL0_Phase;
unsigned char TH0_DPhase;
unsigned char TL0_DPhase;
unsigned char TH1_Width;
unsigned char TL1_Width;

void set_T0_Phase(void);    //设置相位定时参数
void set_T1_Width(void);    //设置闪光脉冲宽度参数
void set_T0_DPhase(void);

void SW_set_Phase(void);    //根据开关设置相位及宽度参数
void SW_set_sys_Mode(void); //根据开关设置系统的制式参数

#define SET_T0_P  { TH0 = TH0_Phase;  TL0 = TL0_Phase;}
#define SET_T0_D  { TH0 = TH0_DPhase;  TL0 = TL0_DPhase;}
#define SET_T1_W  { TH1 = TH1_Width;  TL1 = TL1_Width;}


void main()
{
  P0 = 0xFF;//关闭所有P0口输出
  P1 = 0xFF;//关闭所有P1口输出
  P2 = 0xFF;//关闭所有P2口输出
  P3 = 0xFF;//关闭所有P3口输出
  
  Vsync_found = 0;//未发现同步
  Job_Finished = 0;

  CLEAR_SYNC = 0 ;//wait for Vsync  
  CLEAR_SYNC = 1 ;

  SET_LAMP   = 1 ;
  CLEAR_LAMP = 0 ;//Lamp OFF
  CLEAR_LAMP = 1 ;

  MODE = SET_MODE_PORT;//读取设置模式
  MODE &= SET_MODE_MAP;//
  Set_Mode = MODE & 0x01 ;//获得设置模式

  //根据外部开关设置的状态设置视频制式
  SW_set_sys_Mode();

  port0_Reg = PHASE_PORT;//读取相位端口
  port2_Reg = WIDTH_PORT;//读取宽度端口
  SW_set_Phase(); //上电默认状态变化,设置相应参数
  

  UART_DATA_VALID = 0;//串口设置数据无效

  ET0=1;  //定时器/计数器0允许中断
  ET1=1;  //定时器/计数器1允许中断

  EX0=1;  //启动外部中断0开始工作
  EX1=1;  //启动外部中断1开始工作

  TR0=0;         //关闭定时器/计数器0开始工作  上电复位默认不打开,等待场同步中断打开定时器
  TR1=0;         //关闭定时器/计数器1开始工作
  TMOD = 0X11;   //内部的GATE控制
  { SET_T1_W }   //  { TH1 = TH1_Width;  TL1 = TL1_Width;}
  { SET_T0_P }   //  { TH0 = TH0_Phase;  TL0 = TL0_Phase;}
		 
  Vsync_INT = 0;
  //等第一个视频中断信号出现后,会自动打开定时器/计数器0
  IT0 = 1;//外部中断1边沿触发中断
  IT1 = 1;//外部中断0边沿触发中断
  PX1 = 1;//外部中断1处于高优先级
  PX0 = 0;//外部中断0处于低优先级
  PT0 = 0;//定时器0中断处于低优先级
  PT1 = 0;//定时器1中断处于低优先级
  EA=1;//总中断允许

  while(1)
  {
    if(Vsync_found==1)
	{//当同步信号出现时,才改变各种参数,等待以后使用
	  Vsync_found = 0;//清除标志

      port0_Reg = PHASE_PORT;//读取当前值
      port2_Reg = WIDTH_PORT;//读取当前值

      MODE = SET_MODE_PORT;//读取设置模式
      MODE &= SET_MODE_MAP;//
      Set_Mode = MODE & 0x01 ;//获得设置模式
	  if(Set_Mode != Pre_Set_Mode)  SW_set_Phase(); //若状态变化,设置相应参数

      MODE = SYS_MODE_PORT;//读取视频信号制式
      MODE &= SYS_MODE_MAP;//
      Sys_Mode = (MODE >> 1) & 0x01;//获得视频信号制式
	  if(Sys_Mode != Pre_Sys_Mode)  SW_set_sys_Mode(); //若制式变化,设置相应制式参数

      if(Set_Mode == 1)
	  {//当闪光参数由外部控制时,需要检测参数的变化
        if( (Pre_Port0_Reg != port0_Reg)||(Pre_Port2_Reg != port2_Reg) )
	    {//端口数据变化
		  SW_set_Phase(); //若参数变化,设置相应参数
		}
      }
    }
  }//while(1) 等待中断
}

//设置相位定时参数
void set_T0_Phase(void)
{
  if( Phase_time >= (TVSYNC/2) )
  {//相位大于TVSYNC/2
    TH0_Phase = ( (65535- Phase_time+(TVSYNC/2) ) >> 8); //倍频后的相位
    TL0_Phase = ( (65535- Phase_time+(TVSYNC/2) ) & 0xFF);
  }
  else
  {//相位小于TVSYNC/2
    TH0_Phase = ( (65535- Phase_time ) >> 8); //倍频后的相位
    TL0_Phase = ( (65535- Phase_time ) & 0xFF);
  }
}

//设置倍频相位定时参数
void set_T0_DPhase(void)
{
  TH0_DPhase = ( (65535 - (TVSYNC/2) + Width_time  ) >> 8); //倍频后的第二个脉冲的相位
  TL0_DPhase = ( (65535 - (TVSYNC/2) + Width_time  ) & 0xFF);
}

//设置闪光脉冲宽度参数
void set_T1_Width(void)
{
  TH1_Width = ((65535- Width_time) >> 8); //脉冲宽度
  TL1_Width = ((65535- Width_time) & 0xFF);		 
}



//根据外部开关设置的状态设置视频制式
void SW_set_sys_Mode(void)
{
  MODE = SYS_MODE_PORT;//读取视频信号制式
  MODE &= SYS_MODE_MAP;//
  Sys_Mode = (MODE >> 1) & 0x01;//获得视频信号制式

  if(Sys_Mode==0) TVSYNC = T_PAL;  //PAL制式的周期时间
  else TVSYNC = T_NTSC;            //NTSC制式的周期时间

  Pre_Sys_Mode = Sys_Mode;

  set_T0_Phase();    //设置相位定时参数
  set_T1_Width();    //设置闪光脉冲宽度参数
  set_T0_DPhase();
}

//根据外部开关设置的状态设置闪光脉冲的相位和宽度以及倍频需要的参数
void SW_set_phase(void)
{
  unsigned int TempInt;
  //计算宽度
  TempInt = 0;
  temp_width = WIDTH_PORT;
  temp_width &= WIDTH_MAP;//WIDTH_MAP 0x3F P2.0 --- P2.5

  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.0=1
  else TempInt = TempInt << 1;                        //P2.0=0
  temp_width  >>= 1;
  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.1=1
  else TempInt = TempInt << 1;                        //P2.1=0
  temp_width  >>= 1;
  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.2=1
  else TempInt = TempInt << 1;                        //P2.2=0
  temp_width  >>= 1;
  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.3=1
  else TempInt = TempInt << 1;                        //P2.3=0
  temp_width  >>= 1;
  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.4=1
  else TempInt = TempInt << 1;                        //P2.4=0
  temp_width  >>= 1;
  if (temp_width & 0x01) TempInt = (TempInt<<1) + 1;  //P2.5=1
  else TempInt = TempInt << 1;                        //P2.5=0
  
  temp_width = TempInt * 150;       // 最大值  63*150 uS    定时步长150微秒

  //计算相位
  TempInt = 0;
  temp_phase = PHASE_H_PORT;//P2口   P2.6 P2.7
  temp_phase &= PHASE_MAP_H;//PHASE_MAP_H 0xC0
  if (temp_phase & 0x40) TempInt = (TempInt<<1) + 1;  //P2.6=1
  else TempInt = TempInt << 1;                        //P2.6=0
  temp_phase  >>= 1;
  if (temp_phase & 0x40) TempInt = (TempInt<<1) + 1;  //P2.7=1
  else TempInt = TempInt << 1;                        //P2.7=0

  temp_phase = PHASE_L_PORT;
  temp_phase &= PHASE_MAP;//D7...D0
  temp_phase += TempInt*256;//将D9 D8考虑进来
  if(temp_phase >999) temp_phase = 0;  //最大设置999
  temp_phase *= 20;  // 最大值  999*20 uS    定时步长20微秒
      
  Phase_time = temp_phase;  // 新设置的相位
  Width_time = temp_width;  // 新设置的宽度
  
  Pre_Set_Mode = Set_Mode; //修改当前状态完成
  Pre_Port0_Reg = port0_Reg;//修改当前状态参数
  Pre_Port2_Reg = port2_Reg;//修改当前状态参数

  set_T0_Phase();    //设置相位定时参数
  set_T1_Width();    //设置闪光脉冲宽度参数
  set_T0_DPhase();

}


void int0_int(void) interrupt 0
{
}
void int1_int(void) interrupt 2
{// 场同步中断    打开定时器0

  Vsync_INT = 1;    //同步中断
  Vsync_found = 1;  //发现同步
  { SET_T0_P }      //  { TH0 = TH0_Phase;  TL0 = TL0_Phase;}
  TR0=1;            //打开T0定时器
}

void timer0_int(void) interrupt 1 
{//定时器0的中断  打开定时器1,关闭定时器0

//定时器0用于对脉冲相位定时
    SET_LAMP   = 0 ;//打开光源,闪光开始
    SET_LAMP   = 1 ;

    TR0=0;           //关闭T0定时器
    { SET_T1_W }     //  { TH1 = TH1_Width;  TL1 = TL1_Width;}
    TR1=1;           //打开定时器1,开始光脉冲宽度定时

    if(Vsync_INT==1) 
	{
      Job_Finished = 0;  //第一个光脉冲
      { SET_T0_D }
	} //  { TH0 = TH0_DPhase;  TL0 = TL0_DPhase;}
	else 
	{
      Job_Finished = 1; //第二个光脉冲
	  { SET_T0_P }
	}              //  { TH0 = TH0_Phase;  TL0 = TL0_Phase;}

}
							
void timer1_int(void) interrupt 3
{//定时器1的中断  打开定时器0,关闭定时器1

//定时器1用于对脉冲宽度定时

  CLEAR_LAMP = 0 ;     //关闭光源,闪光结束
  CLEAR_LAMP = 1 ;     //关闭光源,闪光结束

  if(Vsync_INT==1)
  { //相位定时结束
    Vsync_INT = 0;
    CLEAR_SYNC = 0 ;   //清除场同步 
    CLEAR_SYNC = 1 ;   //等待下一个同步脉冲
  }
  TR1 = 0;             //关闭定时器1
  if (Job_Finished == 0) TR0 = 1; //工作未完成,打开T0定时器

}


void uart_int(void) interrupt 4
{
}

void timer2_int(void) interrupt 5
{
}



⌨️ 快捷键说明

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