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

📄 fm_mcu51.c

📁 s32440 sd card 驱动程序
💻 C
字号:
/*********************************************************************************Description:the code is for the FM module of TEA5767  and the controler is AT89LV52Language: C51Tools:uVision3 3.23Author:ENWAVersion: V1.0Date: 09/30/2008ALL RIGHT RESERVED ,ONLY FOR COMMUNICATE ,DON'T USE IN COMMERCE .***********************************************************************************/#include <AT89X52.h>	`  #include <intrins.h>#define uchar unsigned char#define uint unsigned int#define DELAY5US _nop_();_nop_();_nop_();_nop_();_nop_();uchar idata adress_write;    // 写TEA5767地址uchar idata adress_read;	//读TEA5767址uchar idata sbuf[5];   		// 数据发送缓冲区uchar idata rbuf[5];   		// 数据接收缓冲区uchar idata ampint[5];uchar bdata I2C_byte1;		//发送的五字节TEA5767可位寻址的设置值uchar bdata I2C_byte2;uchar bdata I2C_byte3;uchar bdata I2C_byte4;uchar bdata I2C_byte5;uchar   byte1;  uchar   byte2;uchar   byte3;uchar   byte4;uchar   byte5;uchar bdata  rec_byte1;		//接收的五字节TEA5767可位寻址的状态数据uchar bdata  rec_byte2;uchar bdata  rec_byte3;uchar bdata  rec_byte4;uchar bdata  rec_byte5;uchar idata ADDRESS_SEND;    //TEA5767发送地址uchar idata ADDRESS_RECEIVE; //TEA5767接收地址uchar idata ADDRESS_AMP;uchar idata numbyte;uchar idata numbyte_AMP;unsigned long int  FM_FREQ;unsigned short int FM_PLL;/*发送到TEA5767的5个字节设置数据中位的定义*/sbit MUTE =I2C_byte1^7;	 sbit SM = I2C_byte1^6;uchar bdata PLL_HIGH;uchar bdata PLL_LOW;sbit SUD=I2C_byte3^7;sbit SSL1=I2C_byte3^6;sbit SSL0=I2C_byte3^5;sbit HLSI=I2C_byte3^4;sbit MS=I2C_byte3^3;sbit MR=I2C_byte3^2;sbit ML=I2C_byte3^1;sbit SWP1=I2C_byte3^0;sbit SWP2=I2C_byte4^7;sbit STBY=I2C_byte4^6;sbit BL=I2C_byte4^5;sbit XTAL=I2C_byte4^4;sbit SMUTE=I2C_byte4^3;sbit HCC=I2C_byte4^2;sbit SNC=I2C_byte4^1;sbit SI=I2C_byte4^0;sbit PLLREF=I2C_byte5^7;sbit DTC=I2C_byte5^6;sbit SDA=P1^0;sbit SCL=P1^1;bit   bdata NACK;    		// 错误标志位bit   bdata nackFlag;   	// 非应答标志位/*接收I2C5个字节设置数据中位的定义*/sbit RF=rec_byte1^7;sbit BLF=rec_byte1^6;sbit STEREO=rec_byte3^7;uchar idata IF;uchar idata LEVEL;uchar idata CI;uchar temp1;uchar temp2;/*  函数预定义 	 */void sendnbyte(uchar idata *sla, uchar n);//与sendbyte函数构成I2C 数据发送函数void sendbyte(uchar idata *ch);		   void I2C_start(void);	//I2C 传输开始void stop(void);		//I2C传输结束void delay1ms(void);	//延迟1msvoid delay100ms(void);	//延迟100msvoid delay600ms(void);  //延迟600msvoid search_up(void);   //接收频率向上加void search_down(void); //接收频率向下减void autosearch(void);	//自动频率搜索void init(void);	    //TEA5767初始化void key_scan(void);	//键扫描void ask(void);			//问答讯号void n_ask(void);	    //非应答讯号void checkack(void);   //检查应答讯号void recnbyte(uchar idata *sla, uchar n); //与recbyte一起构成接收I2C数据函数void recbyte(uchar idata *ch);void setByte1Byte2(void);  //设置第一第二字节频率void AUTO_search_up(void); //自动频率搜索void volume_up(void);void volume_down(void);void AMP_sendnbyte(uchar idata *sla,uchar numbyte_AMP);void main(void){  	numbyte = 5;	numbyte_AMP=5;    ADDRESS_SEND = 0xC0;		  // TEA5767写地址	ADDRESS_RECEIVE=0XC1;		 //TEA5767读地址	ADDRESS_AMP=0X8E;	init(); 		     //  初始化TEA5767	while(1){          	key_scan();			 //键扫描	 }}void init(void){   uchar idata sbuf[5]={0XF0,0X2C,0XD0,0X10,0X40};  //FM模块预设值  uchar idata rbuf[5]={0X00,0X00,0X00,0X00,0X00};  uchar idata ampint[5]={0X27,0X40,0X42,0X46,0XC3};  FM_PLL=0X302C;  FM_FREQ=100800000; //开机预设频率   PLL_HIGH=0;  PLL_LOW=0;    delay100ms();   delay100ms();   P1=0XFF;   P2=0XFF;   I2C_byte1=0XF0;  //FM模块预设值   I2C_byte2=0X2C;   I2C_byte3=0XD0;   I2C_byte4=0X10;   I2C_byte5=0X40;   byte1=0X27;     byte2=0X40;   byte3=0X42;   byte4=0X46;   byte5=0XC3;   sendnbyte(&ADDRESS_SEND,numbyte);   delay100ms();   AMP_sendnbyte(&ADDRESS_AMP,numbyte_AMP);}void I2C_start(void)   //在SCL为高时,SDA由高变低即为I2C传输开始{   SDA=1;   SCL=1;   DELAY5US;   SDA=0;   DELAY5US;   SCL=0;}void stop(void)	 //在SCL为高时,SDA由低变高即为I2C传输结束{	SDA=0;	SCL=1;	DELAY5US;	SDA=1;	DELAY5US;	SCL=0;}void ack(void){	SDA=0;	SCL=1;	DELAY5US;	SDA=1;	SCL=0;}void n_ack(void){	SDA=1;	SCL=1;	DELAY5US;	SDA=0;	SCL=0;}/* 应答位检查子函数 */void checkack(void){ 	SDA = 1;    		// 应答位检查(将p1.0设置成输入,必须先向端口写1)	SCL = 1;	F0 = 0;		DELAY5US;//	SDA=0;	if(SDA == 1)    	// 若SDA=1表明非应答,置位非应答标志F0		F0 = 1;	SCL = 0;}/* 发送一个字节数据子函数 */void sendbyte(uchar idata *ch){ 	uchar idata n = 8;  	uchar idata temp;	temp = *ch;	while(n--)	{ 		if((temp&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1		{			SDA = 1;    // 传送位1			SCL = 1;			DELAY5US;		    SCL = 0; 			SDA = 0;		   		}		else		{  			SDA = 0;    // 否则传送位0			SCL = 1;			DELAY5US;			SCL = 0;  		}		temp = temp<<1;    // 数据左移一位	}}/* 发送n字节数据子程序 */void sendnbyte(uchar idata *sla, uchar n){          	uchar idata *p;	    sbuf[0]=I2C_byte1;    sbuf[1]=I2C_byte2;    sbuf[2]=I2C_byte3;    sbuf[3]=I2C_byte4;	I2C_start();			// 发送启动信号	sendbyte(sla);    		// 发送从器件地址字节	checkack();    			// 检查应答位    if(F0 == 1)	{ 		NACK = 1;		return;    		// 若非应答表明器件错误置错误标志位NACK	}	p = &sbuf[0];	while(n--)	{ 		sendbyte(p);		checkack();    	// 检查应答位		if (F0 == 1)		{			NACK=1;			return;    	// 若非应答表明器件错误置错误标志位NACK		}		p++;	}	stop();    			// 全部发完则停止}/* 接收5字节数据子程序 */void recnbyte(uchar idata *sla, uchar n){ 	uchar idata *p;	I2C_start();		// 发送启动信号	sendbyte(sla);		// 发送TEA5767地址字节	checkack();			// 检查应答位	if(F0 == 1)	{		NACK = 1;		return;	}	p = rbuf;			// 接收字节存放在rbuf中	while(n--)	{ 		recbyte (p);		ack();    		// 收到一个字节后发送一个应答位		p++;	}	n_ack();    		// 收到最后一个字节后发送一个非应答位   rec_byte1=rbuf[0];   rec_byte2=rbuf[1];   rec_byte3=rbuf[2];   rec_byte4=rbuf[3];   rec_byte5=rbuf[4];   stop();}  /* 接收字节处理子程序 */void recbyte(uchar idata *ch){	uchar idata n=8;    // 从SDA线上读取一位数据字节,共8位	uchar idata temp = 0;	while(n--)	{		SDA = 1;		SCL = 1;		temp = temp<<1;    // 左移一位		if(SDA == 1)			temp = temp|0x01;    // 若接收到的位为1,则数据的最后一位置1		else 			temp = temp&0xfe;    // 否则数据的最后一位置0		SCL=0;	}	*ch = temp;}void delay1ms(void)	          	//延迟1ms{	uchar i;	for(i=1000;i>0;i--){}}void delay100ms()				//延迟100ms{	uchar i;	for(i=100;i>0;i--){delay1ms();}}void delay600ms(){   uchar i;   for(i=600;i>0;i--){delay1ms();}}void delay10ms()				//延迟10ms{     uchar i,j;	 for(i=1000;i>0;i--)	 {for(j=100;j>0;j--){}}}void key_scan(void){  uchar idata i;  //P2=0X17;  if((P2&0X1F)!=0X1F)	  {	    	delay10ms();//	P2=0X17;	if((P2&0X1F)!=0X1F)	{  i=P2;	   switch(i&0X1F)	   {	   case 0X1E:	              {				   search_up();	  //频率向上				   delay600ms();				 				   } break;	   case 0X1D:	              {				  search_down();  //频率向下				  delay600ms();							  }break;	   case 0X1B:	              {				  autosearch();	  //自动搜索				  delay600ms();				  }break;		case 0X17:	              {				  volume_up();	//音量加				 delay600ms();				  }break;		case 0X0F:	              {				  volume_down();  //音量减				   delay600ms();				  }break;  	   default: 	          break;	   	   	    }       	 }   }}/*向上搜索*/	void search_up(void){      MUTE=1;			//静音   SUD=1;	        //搜索标志位设为向上   if(FM_FREQ>108000000){FM_FREQ=87500000;} //	判断频率是否到顶   FM_FREQ=FM_FREQ+100000;			//频率加100K   FM_PLL=(unsigned short)((4000*(FM_FREQ/1000+100+225))/32768);	//计算PLL值   setByte1Byte2();	//设置I2C第一第二字节PLL	值}/*向下搜索*/void search_down(void){       MUTE=1;	//静音     SUD=0;//搜索标志位设为向下   if(FM_FREQ<87500000){FM_FREQ=108000000;}  //	判断频率是否到底   FM_FREQ=FM_FREQ-100000;				 //频率减100K   FM_PLL=(unsigned short)((4000*(FM_FREQ/1000-100+225))/32768); 	//计算PLL值   setByte1Byte2();		//设置I2C第一第二字节PLL	值}/*第一第二字节PLL值设定*/void setByte1Byte2(void){   PLL_HIGH=(uchar)((FM_PLL >> 8)&0X3f);	 //PLL高字节值   I2C_byte1=(I2C_byte1&0XC0)|PLL_HIGH;		 //I2C第一字节值   PLL_LOW=(uchar)FM_PLL;					 //PLL低字节值   I2C_byte2= PLL_LOW;						 //I2C第二字节值   sendnbyte(&ADDRESS_SEND,numbyte);	     //I2C数据发送   MUTE=0;								     delay100ms();						  //延时100ms   sendnbyte(&ADDRESS_SEND,numbyte);	  //I2C	数据发送   DELAY5US;}/*自动搜索*/void AUTO_search_up(void){      MUTE=1;				//静音    SUD=1;				//搜索标志位设为向上   if(FM_FREQ>108000000){FM_FREQ=87500000;}  //如果频率到顶则返回到87.5M开始   FM_FREQ=FM_FREQ+100000;					 //频率加100K   FM_PLL=(unsigned short)((4000*(FM_FREQ/1000+100+225))/32768);  //计算PLL值   setByte1Byte2();		//设置第一第二字节I2C数据}void autosearch(void){    FM_PLL=(unsigned short)((4000*(FM_FREQ/1000+100+225))/32768);  //计算PLL值    PLL_HIGH=(uchar)((FM_PLL >> 8)&0X3f); //PLL高字节值    PLL_LOW=(uchar)FM_PLL;	   //PLL低字节值    temp1=PLL_HIGH;			   //temp 用于判断是否搜索了一圈	temp2=PLL_LOW;	    AUTO_search_up();			//向上搜索	delay10ms();    recnbyte(&ADDRESS_RECEIVE,numbyte);	  //接收TEA5767的状态数据    while (!(RF))						  //当无电台搜到时进入继续搜索    {       	  AUTO_search_up();				  //向上搜索	  delay10ms();	  recnbyte(&ADDRESS_RECEIVE,numbyte);	 //接收TEA5767的状态数据	  if((RF)==1)	  { 	    	LEVEL = I2C_byte4&F0;				//当接收到电台信号时获取电台电平	   	if ((LEVEL>=7)&(IF>35)&(IF<39))		//当电台电平大于7并且中频计数器数值在35	到39间时退出自动搜索		{	    		    		return;		}	    	else if((PLL_HIGH==temp1)&(PLL_LOW==temp2)==1){break;}   ////           }     }  }	/* 发送n字节数据子程序 */void AMP_sendnbyte(uchar idata *sla, uchar n){          	uchar idata *p;    ampint[0]=byte1;	    ampint[1]=byte2;		    ampint[2]=byte3;			    ampint[3]=byte4;				    ampint[4]=byte5;		I2C_start();			// 发送启动信号	sendbyte(sla);    		// 发送从器件地址字节	checkack();    			// 检查应答位    if(F0 == 1)	{ 		NACK = 1;		return;    		// 若非应答表明器件错误置错误标志位NACK	}	p=&ampint[0];	while(n--)	{ 		sendbyte(p);		checkack();    	// 检查应答位		if (F0 == 1)		{			NACK=1;			return;    	// 若非应答表明器件错误置错误标志位NACK		}		p++;																		  	}	stop();    			// 全部发完则停止}/*音量增加*/ void volume_down() {         if(byte1==0X30)   //判断是否是最小音量	 {return;}         //已是最小音量则返回	  byte1=byte1+1;  //音量小1级	  AMP_sendnbyte(&ADDRESS_AMP,numbyte_AMP); //通过I2C传送音量值}/*音量减小*/void volume_up() {         if(byte1==0X00)	//判断是否是最大音量	 {return;}       	//已是最大音量则返回	  byte1=byte1-1;	  //音量大1级      AMP_sendnbyte(&ADDRESS_AMP,numbyte_AMP); //通过I2C传送音量值}

⌨️ 快捷键说明

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