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

📄 si4700.c

📁 mega8控制的fm程序(SI4700)。
💻 C
字号:
#include <avr/io.h>
#include <util/twi.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define F_CPU 1000000 /* 8MHz processor */ 
/* 设置 TWPS=0 即与分频系数为1 */ 
#define F_TWI 100000 /* 100KHz */ 
#define TWBR_SELECT (((F_CPU/F_TWI)-16)/2)
#define UINT8 uint8_t
#define UINT16 uint16_t
#define UINT32 uint32_t
#define		BIT_SET(a,b)		a|=(1<<b)
#define		BIT_CLR(a,b)  		a&=(~(1<<b))
#define		BIT_INV(a,b)   		a^=(1<<b)
#define		BIT_STATUS(a,b) 	((a&(1<<b))>>b)

#define DURATION_INIT_1 	600ns mininum
#define DURATION_INIT_2	600ns minimum
#define DURATION_INIT_3 	600ns minimum

#define DURATION_START_1	600ns minimum
#define DURATION_START_2	600ns minimum
#define DURATION_START_3	800ns minimum

#define DURATION_STOP_1	800ns minimum
#define DURATION_STOP_2	600ns minimum
#define DURATION_STOP_3	1300ns minimum

#define DURATION_HIGH		900ns minimum
#define DURATION_LOW		1600ns minimum

#define POWER_SETTLING		50~100ms

//#define DELAY(DURATION)		{unsigned short i; for(i = 1; i <= DURATION; i++){}}
#define scl(i)  {if(i) BIT_SET(PORTC,5);else BIT_CLR(PORTC,5);}
#define sda(i)  {if(i) BIT_SET(PORTC,4);else BIT_CLR(PORTC,4);}
#define rst(i)  {if(i) BIT_SET(PORTC,1);else BIT_CLR(PORTC,1);}
#define sda_pin  (BIT_STATUS(PINC,4))
#define READ		0x21
#define WRITE	0x20
UINT8 com_buf;
void ResetSi4700_2w(void)
{
	PORTC=0xff;
	DDRC=0xff;
	sda(0);
	rst(0);
	scl(1);
	//_delay_ms(1);
	rst(1);
	sda(1);
	//_delay_ms(1);
	
}

unsigned char OperationSi4700_2w(unsigned char operation, unsigned char *data, unsigned char numBytes)
{
	unsigned char controlWord,  j, error = 0;
	int i;

/***************************************************

START: make sure here SDIO_DIR =OUT, SCLK = 1,	SDIO = 1

****************************************************/

	scl(1);
	sda(1);
	sda(0);
	scl(0);
	

/***************************************************

WRITE CONTROL DATA: make sure here: SLCK = 0; SDIO = 0

****************************************************/

	if(operation == READ)
		controlWord = 0x21;
	else 
		controlWord = 0x20;
	
	for(i = 7; i>=0; i--)
	{
		sda( (controlWord >> i) & 0x01);
		//_delay_us(2);
		scl(1);
		scl(0);
		//_delay_us(2);
	}

	
/***************************

CHECK ACK for control word

***************************/

	BIT_CLR(DDRC,4);

	//_delay_us(2);
	scl(1);	
	if(sda_pin != 0)
	{
		error = 1;
		goto STOP;
	}
     scl(0);
	//_delay_us(2);

/***************************************

WRITE or READ data

****************************************/


	for(j = 0; j < numBytes; j++, data++)
	{
		if(operation == WRITE)
			BIT_SET(DDRC,4); 
		else
			BIT_CLR(DDRC,4);
		
		for(i = 7; i>=0; i--)
		{
			if(operation == WRITE)
				sda( (*data >> i) & 0x01);
			//_delay_us(2);
			scl(1);
			
                        if(operation == READ)
				*data = (*data << 1) | sda_pin;
			scl(0);
			//_delay_us(2);
		}
			

/******************************

CHECK ACK or SEND ACK=0

*******************************/

		if(operation == WRITE)
			BIT_CLR(DDRC,4);
		else
		{
			BIT_SET(DDRC,4);
			if(j == (numBytes -1))
				sda(1)
			else
				sda(0)
		}
		//_delay_us(2);
		scl(1);
		
		if(operation == WRITE)
			if(sda_pin != 0)
			{
				error = 1;
				goto STOP;
			}
        	scl(0);
		//_delay_us(2);
	}
	

/****************************

STOP: make sure here: SCLK = 0

*****************************/

	STOP:

	BIT_SET(DDRC,4);
	sda(0)
	scl(1)
	sda(1)
	//_delay_us(2);

	return(error);

}


UINT32 g_bandl=87500,g_bandh=108000;
UINT8 g_space=100,g_vol_level=0x08;
/**************************************

Si4700_Intialization():
after initialization please make sure(FW/B15):
0x00: 0x1242
0x01: 0x080F/0A0F
0x07: 0x3C04
0x08: 0x0008
0x09: 0x0001

***************************************/
void Si4700_Intialization(void)
{
	unsigned char si4700_initialization[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x18,0x00,0x20,0x81,0x00};
	unsigned char error_ind = 0,reg_data[28]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},i;
	g_vol_level=si4700_initialization[7]&0xf;
	
	if(si4700_initialization[7]&0xc0==0x00){
		g_bandl=87500;
		g_bandh=108000;	
	}
	else if(si4700_initialization[7]&0xc0==0x40){
		g_bandl=76000;
		g_bandh=108000;	
	}
	else if(si4700_initialization[7]&0xc0==0x80){
		g_bandl=76000;
		g_bandh=90000;	
	}
	
	if(si4700_initialization[7]&0x30==0x00){
		g_space=200;	
	}
	else if(si4700_initialization[7]&0x30==0x10){
		g_space=100;	
	}
	else if(si4700_initialization[7]&0x30==0x20){
		g_space=50;	
	}
	
	
	_delay_ms(100);
	ResetSi4700_2w();

	error_ind = OperationSi4700_2w(WRITE, &(si4700_initialization[0]), 12);
	if(error_ind)
		return;

	_delay_ms(100);
/////////////////
	error_ind = OperationSi4700_2w(READ, reg_data, 26);
	if(error_ind)
		return;	
	for(i=0;i<26;i++){
		while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
		UDR=reg_data[i];
	}
//////////	
}

/**************************************

Si4700_Channel_Selection()

***************************************/

void Si4700_Channel_Selection(UINT32 frq)
{
	unsigned short loop_counter = 0;
	
	unsigned char si4700_reg_data[4];	
	unsigned char error_ind = 0;
	unsigned char si4700_channel_start_tune[] = {0x40,0x01,0x80,0xCA};	//107.7MHz
	unsigned char si4700_channel_stop_tune[] = {0x40,0x01,0x00};	
	si4700_channel_start_tune[3]=(frq-g_bandl)/g_space;//channel
	
	//set tune bit
 	error_ind = OperationSi4700_2w(WRITE, &(si4700_channel_start_tune[0]), 4);
	if(error_ind)
		return;

	//wait STC=1
	do
	{	
		error_ind = OperationSi4700_2w(READ, &(si4700_reg_data[0]), 1);
		if(error_ind)
			return;	
		loop_counter++;
	}
	while(((si4700_reg_data[0]&0x40) == 0) && (loop_counter < 0xff));		
	loop_counter = 0;

	//clear tune bit
	error_ind = OperationSi4700_2w(WRITE, &(si4700_channel_stop_tune[0]), 3);
	if(error_ind)
		return;		

	//wait STC=0
	do
	{	
		error_ind = OperationSi4700_2w(READ, &(si4700_reg_data[0]), 1);
		if(error_ind)
			return;	
	loop_counter++;
	}
	while(((si4700_reg_data[0]&0x40) != 0) && (loop_counter < 0xff));		
	loop_counter = 0;

	//read REG0A&0B
	error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 4);	
	if(error_ind)
		return;	
	

}

/*****************************************************************************************************

Si4700_Channel_Seek()
return 0: good, current channel is valid
return 1: I2C error 
return 2: used in SKMODE0, seek fail, no any valid channel, should end seek
return 2: used in SKMODE1, Band Limit, Stop seeking at the upper or lower band limit, should end seek
return 3: AFC rail, current channel is invalid, should seek next one

******************************************************************************************************/
UINT32 Si4700_Channel_Seek_UP(void)

{
	unsigned short loop_counter = 0;
	unsigned char si4700_reg_data[32];
	unsigned char error_ind = 0, seek_error = 0;
	unsigned char si4700_channel_seek_start[] = {0x41};
	unsigned char si4700_channel_seek_stop[] = {0x40};
	UINT32 frq;
	//set seek bit
 	error_ind = OperationSi4700_2w(WRITE,&(si4700_channel_seek_start[0]), 1);
	if(error_ind)
		return 1;

	//wait STC=1
	do
	{	
		error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 1);
		if(error_ind)
			return 1;	
		loop_counter++;
		_delay_ms(5);
	}
	while(((si4700_reg_data[0]&0x40) == 0) && (loop_counter < 0xfff));	//for loop_counter, when seek, the loop time must > 2s		
	loop_counter = 0;

	//if you use SKMODE = 0, you can check Seek Fail here
	//if you use SKMODE = 1, you can check Band Limit here
	if((si4700_reg_data[0]&0x20) != 0)
		seek_error = 2;
		
	//you can check AFC Rail here
	else if((si4700_reg_data[0]&0x10) != 0)
		seek_error = 3;

	//clear seek bit
	error_ind = OperationSi4700_2w(WRITE,&(si4700_channel_seek_stop[0]), 1);
	if(error_ind)
		return 1;	

	//wait STC=0
	do
	{	
		error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 1);
		if(error_ind)
			return 1;	
		loop_counter++;
		_delay_ms(5);
	}
	while(((si4700_reg_data[0]&0x40) != 0) && (loop_counter < 0xff));		
	loop_counter = 0;

	//you can read REG0A&0B for channel number or RSSI here
	error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 4);	
	if(error_ind)
		return 1;	
	frq=(((UINT32)si4700_reg_data[2]<<8)|(UINT32)si4700_reg_data[3])&0x03ff;
	return frq*g_space+g_bandl;
	//return seek_error;
	
}


/*****************************************************************************************************

Si4700_Channel_Seek()
return 0: good, current channel is valid
return 1: I2C error 
return 2: used in SKMODE0, seek fail, no any valid channel, should end seek
return 2: used in SKMODE1, Band Limit, Stop seeking at the upper or lower band limit, should end seek
return 3: AFC rail, current channel is invalid, should seek next one

******************************************************************************************************/
UINT32 Si4700_Channel_Seek_DOWN(void)

{
	unsigned short loop_counter = 0;
	unsigned char si4700_reg_data[32];
	unsigned char error_ind = 0, seek_error = 0;
	unsigned char si4700_channel_seek_start[] = {0x43};
	unsigned char si4700_channel_seek_stop[] = {0x40};
	UINT32 frq;
	//set seek bit
 	error_ind = OperationSi4700_2w(WRITE,&(si4700_channel_seek_start[0]), 1);
	if(error_ind)
		return 1;

	//wait STC=1
	do
	{	
		error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 1);
		if(error_ind)
			return 1;	
		loop_counter++;
		_delay_ms(5);
		//if(loop_counter==1000)UDR=si4700_reg_data[0];
	}
	while((si4700_reg_data[0]&0x40) == 0);	//for loop_counter, when seek, the loop time must > 2s		
	//while(((si4700_reg_data[0]&0x40) == 0) && (loop_counter < 0xfff));	//for loop_counter, when seek, the loop time must > 2s		
	loop_counter = 0;

	//if you use SKMODE = 0, you can check Seek Fail here
	//if you use SKMODE = 1, you can check Band Limit here
	if((si4700_reg_data[0]&0x20) != 0)
		seek_error = 2;
		
	//you can check AFC Rail here
	else if((si4700_reg_data[0]&0x10) != 0)
		seek_error = 3;

	//clear seek bit
	error_ind = OperationSi4700_2w(WRITE,&(si4700_channel_seek_stop[0]), 1);
	if(error_ind)
		return 1;	

	//wait STC=0
	do
	{	
		error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 1);
		if(error_ind)
			return 1;	
		loop_counter++;
	}
	while((si4700_reg_data[0]&0x40) != 0);
	//while(((si4700_reg_data[0]&0x40) != 0) && (loop_counter < 0xff));	
	loop_counter = 0;

	//you can read REG0A&0B for channel number or RSSI here
	error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 4);	
	if(error_ind)
		return 1;	
	frq=(((UINT32)si4700_reg_data[2]<<8)|(UINT32)si4700_reg_data[3])&0x03ff;
	return frq*g_space+g_bandl;
	//return seek_error;
	
}
void Si4700_mute_en(void){
	unsigned char si4700_mute_data[1]={0x00};
	OperationSi4700_2w(WRITE,si4700_mute_data, 1);	
}

void Si4700_mute_dis(void){
	unsigned char si4700_mute_data[1]={0x40};
	OperationSi4700_2w(WRITE,si4700_mute_data, 1);	
}

void Si4700_vol_up(void){
	unsigned char si4700_vol_data[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x1f};
	g_vol_level++;
	if(g_vol_level<0||g_vol_level>15)
		g_vol_level=15;
	else{
		si4700_vol_data[7]=g_vol_level|0x10;
		OperationSi4700_2w(WRITE,si4700_vol_data, 8);
	}
		
}

void Si4700_vol_down(void){
	unsigned char si4700_vol_data[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x1f};
	g_vol_level--;
	if(g_vol_level<0||g_vol_level>15)
		g_vol_level=0;
	else{
		si4700_vol_data[7]=g_vol_level|0x10;
		OperationSi4700_2w(WRITE,si4700_vol_data, 8);
	}
		
}
void ini_uart(uint16_t m_baud)//m_baud=207时,bode=4800 f=8M //12,9600,1//25,4800,1
{
	UBRRH = (uint8_t)(m_baud>>8);
	UBRRL = (uint8_t)m_baud;
	UCSRA = (1<<U2X);
	/* 设置帧格式: 8 个数据位, 1 个停止位*/
	UCSRC = (1<<URSEL)|(3<<UCSZ0);
	/* 接收器与发送器终端使能,接收器与发送器使能*/
	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);//|(1<<TXCIE);
	/*禁用终端
	cli();*/
}

SIGNAL(SIG_UART_RECV){
	com_buf=UDR;
	while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
	UDR=com_buf;
}
int main(){
	//UINT8 txt[14],i;
	UINT32 frq;
	UINT8 reg[2];
	UINT16 i;
	ini_uart(12);//9600/1M
	sei();
	UDR=0xaa;
	//wdt_enable(WDTO_2S);
	Si4700_Intialization();
	
	while(1){
	//wdt_reset();
	switch (com_buf) {
		case 1:
			com_buf=0;
			frq=Si4700_Channel_Seek_DOWN();
			frq/=100;
			i=((frq/1000)<<12)|(((frq/100)%10)<<8)|(((frq/10)%10)<<4)|((frq/1)%10);
			while(!(UCSRA & (1<<UDRE)));UDR=i>>8;
			while(!(UCSRA & (1<<UDRE)));UDR=i;
		break;
		case 2:
			com_buf=0;
			frq=Si4700_Channel_Seek_UP();
			frq/=100;
			i=((frq/1000)<<12)|(((frq/100)%10)<<8)|(((frq/10)%10)<<4)|((frq/1)%10);
			while(!(UCSRA & (1<<UDRE)));UDR=i>>8;
			while(!(UCSRA & (1<<UDRE)));UDR=i;
		break;
		case 3:
			com_buf=0;
			Si4700_mute_en();
		break;
		case 4:
			com_buf=0;
			Si4700_mute_dis();
		break;
		case 5:
			com_buf=0;
			Si4700_vol_up();
		break;
		
		case 6:
			com_buf=0;
			Si4700_vol_down();
		break;
		case 7:
			com_buf=0;
			Si4700_Channel_Selection(104000);
		break;
		
		case 8:
			com_buf=0;
			OperationSi4700_2w(READ,reg, 2);
			while(!(UCSRA & (1<<UDRE)));UDR=reg[1];
		break;
		
		case 9:
			com_buf=0;
			reg[0]=0x60;
			OperationSi4700_2w(WRITE,reg, 1);//mono
		break;
		
		case 10:
			com_buf=0;
			reg[0]=0x40;
			OperationSi4700_2w(WRITE,reg, 1);//strero
		break;		
	}}
}





⌨️ 快捷键说明

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