最近研究si47xx系列芯片
发现比较复杂,可能是因为功能比较多,参考网上的程序 发现比较乱,不过总算移植到stm32上了。这几天再仔细看下手册,优化一下程序。pcb基本完成了,中间改了好几个地方。有机会作个板子。 网上的一段简版代码
/****************************************************** START condition: SCLK: -----------|______ SDIO:-----|_____________ 1 | 2 | 3 STOP condition: SCLK: ____|-------------- SDIO:____________|------- 1 | 2 | 3 DATA: SCLK:_______________|---|________|----|_______ SDIO:___________|------------|____________|---- |<======= >| RESET: SENB:__|--------------------------------------------- SDIO:_________________________________________|------ RST: ___________|------------------------------------ SCLK:__|--------------------------------------------- | 1 | 2 | 3 ********************************************************/ #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 1 #define WRITE 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); } 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 ****************************************************/ SCLK = 1; SDIO = 1; DELAY(DURATION_START_1); SDIO = 0; DELAY(DURATION_START_2); SCLK = 0; DELAY(DURATION_START_3); /*************************************************** WRITE CONTROL DATA: make sure here: SLCK = 0; SDIO = 0 ****************************************************/ if(operation == READ) controlWord = 0x21; else controlWord = 0x20; for(i = 7; i>=0; i--) { SDIO = (controlWord >> i) & 0x01; DELAY(DURATION_LOW/2); SCLK = 1; DELAY(DURATION_HIGH); SCLK = 0; DELAY(DURATION_LOW/2); } /*************************** CHECK ACK for control word ***************************/ SDIO_DIR = IN; DELAY(DURATION_LOW/2); SCLK = 1; DELAY(DURATION_HIGH); if(SDIO != 0) { error = 1; goto STOP; } SCLK = 0; DELAY(DURATION_LOW/2); /*************************************** WRITE or READ data ****************************************/ for(j = 0; j < numBytes; j++, data++) { if(operation == WRITE) SDIO_DIR = OUT; else <input type="image" src=""> SDIO_DIR = IN; for(i = 7; i>=0; i--) { if(operation == WRITE) SDIO = (*data >> i) & 0x01; DELAY(DURATION_LOW/2); SCLK = 1; DELAY(DURATION_HIGH); if(operation == READ) *data = (*data << 1) | SDIO; SCLK = 0; DELAY(DURATION_LOW/2); } /****************************** CHECK ACK or SEND ACK=0 *******************************/ if(operation == WRITE) SDIO_DIR = IN; else { SDIO_DIR = OUT; if(j == (numBytes -1)) SDIO = 1; else SDIO = 0; } DELAY(DURATION_LOW/2); SCLK = 1; DELAY(DURATION_HIGH); if(operation == WRITE) if(SDIO != 0) { error = 1; goto STOP; } SCLK = 0; DELAY(DURATION_LOW/2); } /**************************** STOP: make sure here: SCLK = 0 *****************************/ STOP: SDIO_DIR = OUT; SDIO = 0; DELAY(DURATION_STOP_1); SCLK = 1; DELAY(DURATION_STOP_2); SDIO = 1; DELAY(DURATION_STOP_3); return(error); } /************************************** Si4700_Intialization(): after initialization please make sure: 0x00: 0x1242 0x01: 0x0800/0850 0x07: 0x3c04 0x08: 0x00ff 0x09: 0x0001 ***************************************/ void Si4700_Intialization(void) { unsigned char si4700_initialization[] = {0x40,0x01,0x00,0x00,0xC0,0x04,0x0f,0x1f}; unsigned char error_ind = 0; ResetSi4700_2w(); error_ind = OperationSi4700_2w(WRITE, &(si4700_initialization[0]), 8); if(error_ind) return; DELAY(POWER_SETTLING); } /************************************** Si4700_Channel_Selection() ***************************************/ void Si4700_Channel_Selection(void) { unsigned short loop_counter = 0; unsigned char si4700_reg_data[32]; 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}; //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 < 0xffff)); 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 < 0xffff)); loop_counter = 0; //read REG0A&0B error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 4); if(error_ind) return; } /************************************** Si4700_Channel_Seek() return 1: I2C error return 2: seek fail ***************************************/ unsigned char Si4700_Channel_Seek(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}; //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 < 0xffff)); loop_counter = 0; //check whether SF=1 if((si4700_reg_data[0]&0x20) != 0) seek_error = 2; //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 < 0xffff)); loop_counter = 0; //read REG0A&0B error_ind = OperationSi4700_2w(READ,&(si4700_reg_data[0]), 4); if(error_ind) return 1; return seek_error; }