📄 tv2.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 + -