久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學習與研究
當前位置:單片機教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

完整的FM收音機模塊驅(qū)動程序(包含M62429電子調(diào)音程序)

作者:西西   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2014年04月05日   【字體:

/****************wang1jin設(shè)計的FM發(fā)射板程序************************
電路結(jié)構(gòu):STC12C2052+M62429+BH1415+9018+3355+2053
LCD1602顯示,電子音量

完成時間:2007年11月初

程序編寫:sunhm
***************************************************************/

#include "STC89C51RC_RD_PLUS.H"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define nop _nop_();_nop_();_nop_();

uchar code C51BOX2[3] _at_ 0x43;   //仿真器用三字節(jié)空間

sbit CE_1415= P1^4;   //;1415的使能端
sbit CK_1415= P1^5;   //;1415的時鐘
sbit DT_1415= P1^6;   //;1415數(shù)據(jù)口
sbit RS_1602=P3^3;    //各控制腳
sbit RW_1602=P3^4;
sbit EN_1602=P3^5;
sfr  DataPort_1602=0x90;//P1數(shù)據(jù)口
sbit CK_M62429=P3^1;
sbit DATA_M62429=P3^0;

sbit KeyPow  =P1^0;  //按鍵
sbit KeyMenu  =P1^1;
sbit KeyUp   =P1^2;
sbit KeyDown =P1^3;
sbit KeyGnd  =P3^7;

sbit FmPow=P1^7;

uchar code Megs0[]={"Sunhm  QQ8932867"};
uchar code Megs1[]={"  FM Power Off  "};
uchar code Megs2[]={" FM Transmitter "};
uchar code Megs3[]={"    . MHz  -  dB"};

uchar code CG[]={
                 0x02, 0x04, 0x19, 0x15, 0x15, 0x19, 0x04, 0x02, // 喇叭符號
     0x20, 0x1f, 0x11, 0x0a, 0x04, 0x04, 0x04, 0x04, // 天線符號
     };

uchar Vol;   //存放音量值
uint Freq;  //存放頻率值
uchar KeyValue; //鍵值
uchar MenuState;//菜單切換狀態(tài)變量
uchar Account;uchar MenuDelayTime;
bit FlashState; //閃動狀態(tài)變量

/**************************延時變量*****************************/
//#define Delay1 90   //STC12C2052+12M晶振使用
//#define Delay2 380
//#define Delay3 5
//#define Delay4 100

//#define Delay1 35   //STC12C2052+RC使用
//#define Delay2 200
//#define Delay3 2
//#define Delay4 50

#define Delay1 45    //AT89C2051+12M晶振使用
#define Delay2 150
#define Delay3 2
#define Delay4 100


/**********************延時子函數(shù)*******************************/
void uDelay(uchar i)   //us延時子函數(shù),入口參數(shù)每加1約加100us
{
 for(;i>0;i--)
  {uchar j=Delay1;while(--j);}
}

void mDelay(uint Dat)  //ms延時子函數(shù)
{
 uint j;  
 for (;Dat>0;Dat--)
  for (j=Delay2;j>0;j--);
}


/****************以下為EPPROM讀寫相關(guān)函數(shù)*******************************/
/*以下為EPPROM保護,每次操作后更改指令值,使EPPROM免于被誤操作*/
void EPPROM_Protect()
{
  ISP_CONTR=0x00;   //更改指令值,防止出現(xiàn)誤操作
 ISP_CMD=0x00;
 ISP_TRIG=0x00;
 ISP_ADDRH=0x00;
 ISP_ADDRL=0x00;
}

/*以下為讀入指令,入口參數(shù)為要讀的地址(16位),返回內(nèi)容(8位)*/
uchar EEPROM_Read(uint Addr)
{
 ISP_ADDRH=Addr/0x100;  //送地址
 ISP_ADDRL=Addr%0x100;
 ISP_CONTR=0x83;  //控制字節(jié)
 ISP_CMD=0x01;  //讀命令
 ISP_TRIG=0x46;  //觸發(fā)
 ISP_TRIG=0xB9;
 EPPROM_Protect(); //更改相關(guān)數(shù)值,防止誤操作
 return(ISP_DATA);  //返回讀出的值
}
 
/*以下為扇區(qū)擦除指令,入口參數(shù)為扇區(qū)首地址 */
void EEPROM_Erase(uint Addr)
{
 ISP_ADDRH=Addr/0x100;  //待寫入扇區(qū)首地址
 ISP_ADDRL=0x00;
 ISP_CONTR=0x83;
 ISP_CMD=0x03;  //扇區(qū)擦除指令
 ISP_TRIG=0x46;  //觸發(fā),將擦除整個扇區(qū)
 ISP_TRIG=0xB9;
 EPPROM_Protect(); //更改相關(guān)數(shù)值,防止誤操作
}

/*以下為寫入指令,入口參數(shù)為寫入的地址(16位)和內(nèi)容(8位),每次要寫入的位置*/
void EEPROM_Write(uint Addr,uchar Data)
{
 ISP_DATA=Data; //待寫入值
 ISP_ADDRH=Addr/0x100;  //待寫入扇區(qū)首地址
 ISP_ADDRL=Addr%0x100;
 ISP_CONTR=0x83;
 ISP_CMD=0x02;  //寫入指令
 ISP_TRIG=0x46;  //觸發(fā),數(shù)據(jù)寫入
 ISP_TRIG=0xB9;
 EPPROM_Protect(); //更改相關(guān)數(shù)值,防止誤操作
}

/**********************數(shù)據(jù)存儲與讀取******************************/
void DatSave()
{
 EEPROM_Erase(0x1000);
 EEPROM_Write(0x1000,Vol);
 EEPROM_Write(0x1001,Freq/0x100);
 EEPROM_Write(0x1002,Freq%0x100);
}
void DatLoad()
{
 Vol=EEPROM_Read(0x1000);
 Freq=EEPROM_Read(0x1001)*0x100+EEPROM_Read(0x1002);
 if(Vol>83){Vol=10;DatSave();}
 if ((Freq>1080)||(Freq<870))  //判斷頻率值是否有錯
  {
  Freq=908;   //如果錯誤,設(shè)置為默認90.8M
  DatSave();
  }
}

/**************************M62429 發(fā)送用子函數(shù)**********************/
void VolSet(uchar Volume)
{
 uint Dat;uchar i;
 Volume=87-Volume;  //得到要送到芯片的實際數(shù)
 Dat=0x600|(Volume&0xfc)|((Volume&0x03)<<7);  //音量合并成控制數(shù)據(jù),詳看DATASHEET
 
 for (i=0;i<10;i++)        //發(fā)送10位數(shù)據(jù),共11位,最后1位另外發(fā)
  {
   DATA_M62429=Dat&0x01;
   CK_M62429=1;   
   nop;
   DATA_M62429=0;  
   CK_M62429=0;    
   Dat>>=1;      
  }
 DATA_M62429=1; 
 CK_M62429=1;nop;CK_M62429=0;

}
/*************************1415 發(fā)送子函數(shù)*********************/

void PLLSend(uint Dat)    //數(shù)據(jù)發(fā)送到BH1415
{
 uchar i;
 Dat+=0x4800;
 CE_1415=1;    //打開片選準備發(fā)送
 for(i=16;i>0;i--)
 {
  DT_1415=Dat&1;
  CK_1415=1; 
  Dat>>=1;   
  CK_1415=0;   
 }
 CE_1415=0;DT_1415=0;CK_1415=0;
}

/**********************1602 4線使用程序***********************/
void En1602(uchar Dat)   //使能子函數(shù)
{
  KeyGnd=1;    //釋放鍵盤線
 uDelay(15);
 DataPort_1602&=0xf0; //數(shù)據(jù)送出,ASCII碼
 DataPort_1602|=Dat>>4;
 RS_1602=0;    //控制發(fā)出
 RW_1602=0;
 EN_1602=1;EN_1602=0;

  DataPort_1602&=0xf0;
 DataPort_1602|=Dat&0x0f;
 RS_1602=0;  
 RW_1602=0;
 EN_1602=1;EN_1602=0;
   KeyGnd=0;
}
 
void WrCharTo1602(uchar Dat) //寫字節(jié)子函數(shù)
{
  KeyGnd=1;
 uDelay(15);
 DataPort_1602&=0xf0;  //數(shù)據(jù)送出,ASCII碼
 DataPort_1602|=Dat>>4;
 RS_1602=1;     //控制發(fā)出
 RW_1602=0;
 EN_1602=1;EN_1602=0;

  DataPort_1602&=0xf0;
 DataPort_1602|=Dat&0x0f;
 RS_1602=1;  
 RW_1602=0;
 EN_1602=1;EN_1602=0;
 KeyGnd=0;
}

void WrStringTo1602(uchar x,uchar *p)  //寫字符串子函數(shù)。入品:x行(0或1),數(shù)組
{
 En1602(0x80+(x<<6)); 
 while(*p)
 {
  WrCharTo1602(*p);p++;
 }
}

void Init1602(void)   //初始化子函數(shù)
{
  En1602(0x28);   //4位點陣方式
 mDelay(100);
 En1602(0x28); 
 mDelay(100);
 En1602(0x28); 
 mDelay(100);
 En1602(0x28); 
 mDelay(100);
 En1602(0x0c);   //開顯示
 mDelay(100);
 En1602(0x01);   //清屏
}

void WrCG1602(uchar *p)     //自定義字符子函數(shù)
{     
 En1602(0x40); 
 while(*p)
 {WrCharTo1602(*p);p++;mDelay(1);}
}

/****************************顯示子函數(shù)*************************/
void DispFreq(bit state) //頻率值拆分顯示。入口參數(shù):1為有顯示,0為沒
{
 uint Dat=Freq;
 if(state) //正常顯示
  {
  En1602(0xc5);
  WrCharTo1602(Dat%10+0x30);
  Dat/=10;
 
  En1602(0xc3);
  WrCharTo1602(Dat%10+0x30);
  Dat/=10;
 
  En1602(0xc2);
  WrCharTo1602(Dat%10+0x30);
 
  En1602(0xc1);
  if(Dat/10) WrCharTo1602(0x31);
  else WrCharTo1602(0x20);
  }
 else     //無顯示
  {
  En1602(0xc1);
  WrCharTo1602(0x20);WrCharTo1602(0x20);WrCharTo1602(0x20);
  En1602(0xc5);WrCharTo1602(0x20);
  }
}

void DispVol(bit State)    //聲音值拆分顯示。入口參數(shù):1為有顯示,0為沒
{
 if(State)
  {
  En1602(0xcc);
  if(Vol/10) WrCharTo1602(Vol/10+0x30);
  else WrCharTo1602(0x20);
  WrCharTo1602(Vol%10+0x30);
  }
 else
  {
  En1602(0xcc);WrCharTo1602(0x20);WrCharTo1602(0x20);
  }
}
 
void FmOn()    //發(fā)射部分工作屏幕顯示內(nèi)容初始化
{
 FmPow=0;
 WrStringTo1602(0,Megs2);
 WrStringTo1602(1,Megs3);
 En1602(0xc0);WrCharTo1602(1);
 En1602(0xca);WrCharTo1602(0);
 VolSet(Vol);
 mDelay(50);
 DispFreq(1);
 DispVol(1);
 PLLSend(Freq);
}

void FmOff() //發(fā)射部分不工作屏幕顯示內(nèi)容初始化
{
 FmPow=1;
 WrStringTo1602(0,Megs1);
 WrStringTo1602(1,Megs0);
}

void DispFlash()      //閃動顯示處理
{
 if(!MenuState)return;  
 if(MenuState==1) DispFreq(FlashState);
 if(MenuState==2) DispVol(FlashState);
 if(MenuDelayTime>Delay4)
  {MenuState=0;DispFreq(1);DispVol(1);}
}

/************************按鍵讀取及處理子函數(shù)**************************/
void KeyRead()   //讀鍵值子函數(shù)。返回值:1、2、3、31、4、41。(31、41為長按)
{
 uchar i=250;
 KeyGnd=0;
 KeyPow=1;KeyMenu=1;KeyUp=1;KeyDown=1;
 if(KeyPow&KeyMenu&KeyUp&KeyDown) {KeyValue=0;return;}
 MenuDelayTime=0;  //清延時計數(shù)器
 mDelay(10); 
   if(!KeyPow)
    {
    while(!KeyPow); //等待鍵釋放
    KeyValue=1;
    return;
    }
   if(!KeyMenu)
    {
    while(!KeyMenu);//等待鍵釋放
    KeyValue=2;
    return;
    }
   if(!KeyUp)
    {
    if(KeyValue) return; //短按
    while(i)
     {
     if(KeyUp)
      {KeyValue=3;return;}
     mDelay(3);i--;
     }     //短按
    KeyValue=31;  //長按
    return;
    }
   if(!KeyDown)
    {
    if(KeyValue) return;//短按
    while(i)
     {
     if(KeyDown)
      {KeyValue=4;return;}
     mDelay(3);i--;
     }     //短按
    KeyValue=41;     //長按
    return;
    }

}

void KeyProc()    //鍵值處理子函數(shù)
{
 switch(KeyValue)
 {
 case 1:  //KeyPow處理
  if(FmPow)  //根據(jù)當前電源狀態(tài)切換至另一狀態(tài)
   {FmOn();}
  else
   {MenuState=0;FmOff();}
  KeyValue=0;
  break;
 case 2:  //KeyMenu處理
  if(FmPow)break; //關(guān)機狀態(tài)下不處理這個按鍵
  MenuState++;
  DispFreq(1);DispVol(1);
  if(MenuState==3)MenuState=0;
  KeyValue=0;
  break;
 case 3:  //KeyUp處理
  if(FmPow)break; //關(guān)機狀態(tài)下不處理這個按鍵
  if(MenuState==1)
   {
   Freq++;
   if(Freq>1080)Freq=875;  //頻率加1
   DispFreq(1);PLLSend(Freq);
   }
  if(MenuState==2)
   {
   if(Vol)Vol--;
   DispVol(1);VolSet(Vol);
   }
  KeyValue=0;DatSave();
  break;
 case 4:  //KeyDown處理
  if(FmPow)break; //關(guān)機狀態(tài)下不處理這個按鍵
  if(MenuState==1)
   {
   Freq--;
   if(Freq<875)Freq=1080;
   DispFreq(1);PLLSend(Freq);
   }
  if(MenuState==2)
   {
   if(Vol<83)Vol++;    //音量減
   DispVol(1); VolSet(Vol);
   }
  KeyValue=0;DatSave();
  break;
 case 31: //KeyUp長按處理
  if(FmPow)break;
  if(MenuState==1)
   {
   Freq+=10;
   if(Freq>1080)Freq=875;
   DispFreq(1);PLLSend(Freq);
   }
  if(MenuState==2)
   {
   if(Vol>4)Vol-=5;
   else Vol=0;
   DispVol(1);VolSet(Vol);
   }
  mDelay(600);
  DatSave();
  break;
 case 41: //KeyDown長按處理
  if(FmPow)break;
  if(MenuState==1)
   {
   Freq-=10;
   if(Freq<875)Freq=1080;
   DispFreq(1);PLLSend(Freq);
   }
  if(MenuState==2)
   {
   Vol+=5;
   if(Vol>83)Vol=83;
   DispVol(1);VolSet(Vol);
   }
  mDelay(600);DatSave();
  break;
 }
}  

/*******************計數(shù)器中斷處理子函數(shù)*************************/
void Timer0() interrupt 1   //計時中斷子函數(shù),50ms中斷一次
{

 Account++;       //中斷一次加1
 MenuDelayTime++;
 if(Account>Delay3) 
  {
  Account=0;
  FlashState=~FlashState;
  }
}

/****************************主函數(shù)*******************************/
void main()
{
 mDelay(1000);       //開機延時,等待設(shè)備穩(wěn)定
 Init1602();
 mDelay(10);
 WrCG1602(CG);
 CE_1415=0;CK_1415=0,DT_1415=0;
 CK_M62429=0;DATA_M62429=0;
 DatLoad();

 TH0=0x3c;         //設(shè)定中斷初始值
 TL0=0xb0;
 TMOD=0x01;
 EA=1;
 TR0=1;
 ET0=1;
 
 FmOff();      //顯示關(guān)閉畫面

 while(1)  {KeyRead();DispFlash();KeyProc();};
    
}

關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 亚洲国产成人精品久久 | 日本三级网址 | 中文字幕精品一区二区三区精品 | 国产激情自拍视频 | 中文字幕第一页在线 | 51ⅴ精品国产91久久久久久 | 久久日韩粉嫩一区二区三区 | 国产亚洲一区二区三区在线观看 | 黄色免费在线观看网站 | 中文字幕 在线观看 | 国产欧美一区二区三区国产幕精品 | av在线电影网 | 国产成人99久久亚洲综合精品 | 国产精品久久久久久亚洲调教 | 美女黄频 | 久久久亚洲精品视频 | 久久青视频 | 日本一区二区三区四区 | 性做久久久久久免费观看欧美 | 国产一区二区三区 | 精品国产欧美日韩不卡在线观看 | 免费一区二区三区 | 亚洲精品视频在线观看视频 | 成人一区二区视频 | 一区二区三区精品在线 | 91亚洲国产 | 日韩成人高清在线 | 国产精品久久久久久婷婷天堂 | 精品国产一区二区三区性色 | 日日干夜夜操 | 欧美在线观看一区 | 日韩精品一区二区三区中文在线 | 成人影视网址 | 国产一区二区在线免费 | 欧美日韩成人 | 曰批视频在线观看 | 国产粉嫩尤物极品99综合精品 | 日韩影院在线观看 | 91精品久久久久久久久久入口 | 91精品国产综合久久婷婷香蕉 | 久久中文视频 |