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

📄 tv2.txt

📁 51单片机+FI1256高频头=电视接收机源代码
💻 TXT
字号:
/********************************************************************************************
 单片机实验之--控制fi1256搜台并存台
 作者:朱泷,张刘松
 email:iam.shuang@yahoo.com.cn
 西安交通大学  710049
 
 更换晶振请注意时序问题
 请详细阅读fi1256和24c02的产品手册

 精勤求学,敦笃励志,果毅力行,忠恕任事。
*********************************************************************************************/
#include<reg52.h>
#include<stdio.h>
#include<intrins.h>
#define	OP_READ	0xa1		// 器件地址以及读取操作
#define	OP_WRITE 0xa0		// 器件地址以及写入操作
#define	MAX_ADDR 0x7f		// AT24C02最大地址
#define FHIGH 0x05
#define FLOW 0x7c
//晶振 12MHz
//K1键:+	   K2键:-     K3键:存储     K4键:选台、跳出
  


sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
sbit SDA= P2^1;
sbit SCL= P2^0;
sbit P24=P2^4;
sbit P25=P2^5;
sbit P26=P2^6;
sbit P27=P2^7;

unsigned int ADD,DB1,DB2,PB,NDB,address,mode;
unsigned char code dis_code[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};	// 0, 1, 2, 3// 4, 5, 6, 7, 8, 9, off 
    
void I2C_Start()
    {
        /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
    SDA = 1;
	SCL = 1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	SDA = 0;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	SCL = 0;
    }
    void I2C_Stop()
    {
        /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
        SDA=0;
        SCL=1;
        _nop_();
		_nop_();
		_nop_();
		_nop_();
        SDA=1;
        _nop_();
		_nop_();
		_nop_();
		_nop_();
        SCL=0;
        
    }

void delay_ms(int number)          //延时函数
{                                   //晶振  12Mhz
    unsigned char i; 
    unsigned int j;
    for (j=0;j<number;j++)
    {
            for (i=0;i<124;i++);   //12Mhz   (1ms)     
    }
}

unsigned char data_in()
// 从slave读数据到MCU
{
	unsigned char i,read_data;
	for(i = 0; i < 8; i++)
	{
		SCL = 1;
		_nop_();
		_nop_();
		read_data <<= 1;
		read_data |= (unsigned char)SDA;
		SCL = 0;
		_nop_();
		_nop_();
	}
	return(read_data);
}
bit data_out(unsigned char write_data)
// 从MCU写数据到slave
{
	unsigned char i;
	bit ack;
	for(i = 0; i < 8; i++)		// 循环移入8个位
	{
		SDA = (bit)(write_data & 0x80);
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		SCL = 1;
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		SCL = 0;
		write_data <<= 1;
	}
	SDA = 1;			// 读取应答
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	SCL = 1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	ack = SDA;
	SCL = 0;
	return ack;			// 返回应答位
}

void write_byte_eeprom(unsigned char addr, unsigned char write_data)
// 在eeprom指定地址addr处写入数据write_data
{
	I2C_Start();
	data_out(OP_WRITE);
	data_out(addr);
	data_out(write_data);
	I2C_Stop();
	delay_ms(3);		// 写入周期延时
}

void fill_byte(unsigned char fill_data)
// 填充数据fill_data到EEPROM内
{
	unsigned char i;
	for(i = 0; i < MAX_ADDR; i++)
	{
		write_byte_eeprom(i, fill_data);
	}

}

unsigned char read_current()
// 在当前地址读取
{
	unsigned char read_data;
	I2C_Start();
	data_out(OP_READ);
	read_data = data_in();
	I2C_Stop();
	return read_data;
}

unsigned char read_eeprom(unsigned char eeprom_addr)
// 在指定地址读取
{
	I2C_Start();
	data_out(OP_WRITE);
	data_out(eeprom_addr);
	return(read_current());
}

void display()	   //数码管显示频率	 和频道
{int ge,shi,bai,x1,p,pbai,pshi,pge;
 unsigned long freq;
 freq=(DB1*256+DB2)/16-38;
 bai=freq/100;
 shi=(freq-bai*100)/10;
 ge=freq-bai*100-shi*10;
 x1=DB2*10/16-DB2/16*10;  //小数位,不可将freq*10,否则溢出.x1只取决于DB2/16
 p=address/2;
 pbai=p/100;
 pshi=(p-pbai*100)/10;
 pge=p-pbai*100-pshi*10;

 while((K1==1)&&(K2==1)&&(K3==1)&&(K4==1))
    {/*P24=1;
	 P25=1;
	 P26=1;	
	 P27=1;*/	
	 if (bai!=0)
	   {P0=dis_code[bai];		  //频率
        P24=0;
        delay_ms(5);
		P24=1;			  
  		}
     P0=dis_code[shi];		 
     P25=0;
     delay_ms(5);
	 P25=1;
  
     P0=(dis_code[ge]&0x7f);	   //增加小数点
	 P26=0;
     delay_ms(5);
	 P26=1;

	 P0=dis_code[x1];
	 P27=0;
     delay_ms(5);
	 P27=1;

	 P0=0xff;
	 P24=1;
	 P25=1;
	 P26=1;	
	 P27=1;

	 /*if (p!=0)
	 {  P0=dis_code[pbai];			 //频道
        P2=0xfe;
        delay_ms(5);

	    P0=dis_code[pshi];
        P2=0xfd;
        delay_ms(5);

	    P0=dis_code[pge];
        P2=0xfb;
        delay_ms(5);

	    P0=0x8c;
        P2=0xf7;
        delay_ms(5);
	 }	 
	 P2=0xff; */
     }
}

void write_byte_fi1256()
// fi1256写操作
{	I2C_Start();//I2C总线开始
     
    data_out(ADD);
    data_out(DB1);
    data_out(DB2);
    data_out(0x8E);
    
	NDB=(DB1*256+DB2)/16;
    NDB=NDB-38;
    
    if(NDB>0 && NDB<160) PB=0XA0;	//频段计算	VHF-L
    if(NDB>168 && NDB<466) PB=0X90;	//			VHF-H
    if(NDB>470 && NDB<863) PB=0X30; //			UHF
    
    data_out(PB);  //频段控制
    I2C_Stop(); //I2C总线停止
	delay_ms(100);		// 写入周期
    display();
}





void search()	//	搜台、存台子程序
{   DB1=FHIGH; 
    DB2=FLOW; 
	address=0;	
	fill_byte(0xff);
 while(1)
    {
        K1=1;
        K2=1;
		K3=1;
		K4=1;
        if(K1==0) 
            {
            DB2+=2; 
            if(DB2>255) 
			{DB2=0;DB1++;}
            }		 //不延时,长按可连续调台
		
        if(K2==0) 
            {
            DB2-=2;
            if(DB2==0) {DB2=255;DB1--;}
            }
		if(DB1==0x38)
		    {DB1=FHIGH; DB2=FLOW;}
        if((DB1==FHIGH)&&(DB2<FLOW))
            {DB1=0x37;  DB2=0xff;}	   
        if (K3==0)
	         {write_byte_eeprom(address,DB1);
	            address++;
	       	  write_byte_eeprom(address,DB2);
		        address++;
		      delay_ms(1000);	//存台  确保按一次键,只写一次
	         }   							 
	    write_byte_fi1256();
	    if (address==(MAX_ADDR-1))
		   address=0;
	    if (K4==0)
	        { delay_ms(500);	
	             write_byte_eeprom(MAX_ADDR,address);  //将频道数存入最大地址处 
                 mode=2;
				 break;	  
	        }	 //存台结束
    }
}

void watch_tv()	  //看节目子程序
{ unsigned char chmax;
  unsigned int t;
    address=0;
	DB1=0;
	DB2=0;	  
	chmax=read_eeprom(MAX_ADDR);
	if (chmax==0)
	     {t=100;
		      while(t!=0)
                 {
	             P0=0xc0;
                 P24=0;
                 delay_ms(5);
				 P24=1;			  
  		         
    			 P0=0xc6;		 
    			 P25=0;
    			 delay_ms(5);
				 P25=1;
  
    			 P0=0x89;	   
				 P26=0;
   				 delay_ms(5);
				 P26=1;
		   		 t--;
		          }
			mode=1; 
		 }  
   if (mode==2)
	 {   DB1=read_eeprom(address);
	     address++;
		 delay_ms(500);
		 DB2=read_eeprom(address);
		 address++;
		 delay_ms(500);
		 write_byte_fi1256();	
	  while(1)
	     {
  	     if (K1==0)
	         { DB1=read_eeprom(address);
	           address++;
		       delay_ms(500);
		       DB2=read_eeprom(address);
		       address++;
		       delay_ms(500);
		       write_byte_fi1256();	        	   
		       if (address==chmax)
		               address=0;
	          }
	     if (K2==0)
	         { if (address<=2)
		             address=chmax+2;
		        address-=4;		   //退回到最后一个频道
	            DB1=read_eeprom(address);
		        address++;
		        delay_ms(500);
		        DB2=read_eeprom(address);
		        address++;
	        	delay_ms(500);
		        write_byte_fi1256();
		 
		      }
	     if (K3==0)
		    {delay_ms(500);
		       mode=1;
		       break;	
		     }
	  	 }
	 }
 }	


/***********************************主程序*********************************/
void main()
{	//start-ADD(C2,PIN15悬空)-ACK-DB1(频率1)-ACK-DB2(频率2)-ACK-CB(控制)-ACK-PB(波段)-ACK-STOP
    ADD=0XC2; //地址
    DB1=FHIGH; //分频1,可变	
    DB2=FLOW; //分频2,可变	f_picture=f_osc-f_pif=f_osc-38    MHz 
	                        //f_osc=(DB1*256+DB2)/16
	address=0;     //24c02 存台地址
	mode=0;
	//fill_byte(0xff);		// 24c02 全部填充0xff
     while(1)
    {
        K1=1;
        K2=1;
		K3=1;
		K4=1;
        if(K3==0)
		   mode=1;   
		if(K4==0)
		   mode=2;
	    if(mode==1)   
		   {delay_ms(1000);
		    search();
			}
		if(mode==2)	
			{delay_ms(1000);
		    watch_tv();
		    }   	    
  	}
	
	
}







⌨️ 快捷键说明

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