📄 复件 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 8000000 /* 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 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 READ 0x21
#define WRITE 0x20
UINT8 com_buf;
UINT8 OperationSi4700_2w (UINT8 SLA,UINT8 *dat,UINT8 nSize)
{
DDRC &= ~(1<<PC5 | 1<<PC4);PORTC |= (1<<PC5 | 1<<PC4); // 调整端口设置,设置为上拉输入
TWBR = TWBR_SELECT;// 设置TWI波特率
TWSR&=0XFC;
TWCR = 1<<TWSTA | 1<<TWEN | 1<<TWINT;
while (!(TWCR & (1<<TWINT))); // 发送START信号,等待TWIT=1 //
if ((TWSR&0xf8) != TW_START) return TW_START;// START信号成功发送了吗?不成功返回相应错误信息 //
//while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
//UDR=1;
TWDR = (SLA&0xfe); TWCR = 1<<TWINT | 1<<TWEN; while (!(TWCR & (1<<TWINT))); // 发送命令,等待发送完成 //
if ((TWSR&0xf8) != TW_MT_SLA_ACK) return TW_MT_SLA_ACK;
//while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
//UDR=2;
// 传送字节数!=0 ?//
if (nSize !=0)
{
if (SLA & 0x01) // 1=主控接收器操作
{
do
{
// 若准备接收最后一个字节发送则发NACK,否则发送ACK //
if (nSize ==1) { TWCR = 1<<TWINT | 1<<TWEN; } //准备发送NACK
else { TWCR = 1<<TWINT | 1<<TWEA | 1<<TWEN; } //准备发送ACK
while (!(TWCR & (1<<TWINT))); // 等待接收完成 //
while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
UDR=0x11;
// 数据接收成功? //
if (nSize ==1)
// 最后字节成功接收? 不成功返回相应错误信息 //
{
if ((TWSR&0xf8) != TW_MR_DATA_NACK) return TW_MR_DATA_NACK;
while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
UDR=0x12;
}
else
// 非最后字节成功接收? 不成功返回相应错误信息 //
{
if ((TWSR&0xf8) != TW_MR_DATA_ACK) return TW_MR_DATA_ACK;
while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
UDR=0x13;
}
// 保存接收数据 //
*dat =TWDR; dat++;
}while ( --nSize != 0 ); // 循环发送完
}
else //0=主控发送器操作
{
do
{
// 准备送数据,发送,等待发送完成 //
TWDR = *dat; TWCR = 1<<TWINT | 1<<TWEN; dat++;
while (!(TWCR & (1<<TWINT)));
while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
UDR=0x14;
// 数据发送成功?不成功返回相应错误信息 //
if ((TWSR&0xf8) != TW_MT_DATA_ACK) return TW_MT_DATA_ACK;
while(!(UCSRA & (1<<UDRE)));//等待发送缓冲器为空
UDR=0x15;
}while ( --nSize != 0 ); // 循环发送完
}
}
// 发送STOP信号//
TWCR = 1<<TWINT | 1<<TWSTO | 1<<TWEN;
while ( (TWCR & (1<<TWSTO)) !=0 );
TWCR = 0;
// 调整端口设置,设置为高电平输出 //
DDRC |= 1<<PC5 | 1<<PC4;
// 成功发送完毕,返回0 //
return 0;
}
/*
void ResetSi4700_2w(void)
{
SDIO_DIR = OUT;
SENB = 1;
SDIO = 0;
RST = 0;
SCLK = 1;
DELAY(DURATION_INIT_1);
RST = 1;
DELAY(DURATION_INIT_2);
SDIO = 1;
DELAY(DURATION_INIT_3);
}
*/
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,0x48};
unsigned char error_ind = 0;
g_vol_level=si4700_initialization[7]&0xf;
PORTC&=(~_BV(PC1));//For config to IIC interface.
DDRC|=_BV(PC1);
_delay_ms(10);
//while(1);
PORTC|=_BV(PC1);
_delay_ms(100);
PORTC |= 1<<PC5 | 1<<PC4;
DDRC |= 1<<PC5 | 1<<PC4;
//while(1);
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;
}
//ResetSi4700_2w();
error_ind = OperationSi4700_2w(WRITE, &(si4700_initialization[0]), 10);
if(error_ind)
return;
_delay_ms(100);
}
/**************************************
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++;
}
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) && (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++;
}
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;
ini_uart(207);//4800
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;
while(!(UCSRA & (1<<UDRE)));UDR=(frq>>8);
while(!(UCSRA & (1<<UDRE)));UDR=frq;
break;
case 2:
com_buf=0;
frq=Si4700_Channel_Seek_UP();
frq/=100;
while(!(UCSRA & (1<<UDRE)));UDR=(frq>>8);
while(!(UCSRA & (1<<UDRE)));UDR=frq;
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;
}}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -