[分享]单片机控制的 TEA5767高性能FM 收音机 DIY (含原理图,源代码 ) Post By : 2007-10-10 11:41:57本文用到的收音模块可到: / 参考本帖向大家介绍新型 FM 收音机的设计及制作。
想想当年我们是什么做收音机的。
高放混频,解调,立体声解码,锁相等好几个芯片,线路焊好了,但痛苦才开始。
有设备还好些,没有更苦。
为了找谐振点,不 停的调电容电感,不停的换电容电感••…终于有声音,但始终都没那么好。
现在,痛苦终于过去。
因为有了新一代的芯片 TEA5767。
TEA5767 ,零调整。
线路又极其简单。
一个晶振,一个电感,几个电容完了。
通过 接口送几个字节的数据进去就ok 。
I 弓此主题相关图片如下:电子・CNC 爱好看源动力|二1此主题相关图片如下: 电子・CNC 爱好者■源动力源代码:可以存台的版本。
I2C 磁动力论坛bbs 磁动力论坛bbs.cdle. net// WINAVR GCC// ATmega8// clock: internal 1Mhz#include <avr/io.h>#include <avr/interrupt.h>#include <avr/signal.h>#include <avr/delay.h>#include <avr/eeprom.h>#include '3310LCD_function.c'#define uchar uint8_t#define uint uint16_t#define SLA_W 0b11000000 #define SLA_R 0b11000001uchar senddata[5] ;uchar readdata[5] ;uchar search = 0;uchar search_up = 0;uchar mode = 1;uchar station = 0;uint pll = 0x29da; // 88Mhzuint fre = 8750;//// 延时void delay_ms(uint ms){uint i;for(i=0;i<ms;i++)_delay_loop_2(250);}//I2C 主机模式输出void set5767(void){uchar i = 0;TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // SEND START whileSIGNAL (!(TWCR & (1<<TWINT))); // WAIT FOR START SIG //if ((TWSR & 0xF8) != START) ERROR();TWDR = SLA_W; // send addressTWCR = (1<<TWINT) | (1<<TWEN);while (!(TWCR & (1<<TWINT)));//if ((TWSR & 0xF8) !=MT_SLA_ACK) ERROR();for ( i = 0; i < 5; i++ ){TWDR = senddata;TWCR = (1<<TWINT) | (1<<TWEN); // send datawhile (!(TWCR & (1<<TWINT)));// if ((TWSR & 0xF8) != MT_DATA_ACK) ERROR();}TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //SEND STOP SIGNAL // if ((TWSR & 0xF8) != MT_DATA_ACK) ERROR();}//LCD_write_english_string(60,3,'sOK');}//I2C 主机模式 输入void read5767(void){uchar i = 0;TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // SEND START while (!(TWCR & (1<<TWINT))); // WAIT FOR START SIG //if ((TWSR & 0xF8) != START) ERROR();TWDR = SLA_R; // send addressTWCR = (1<<TWINT) | (1<<TWEN);while (!(TWCR & (1<<TWINT)));for ( i = 0; i < 5; i++ ){TWCR = (1<<TWINT) | (1<<TWEN); // read datawhile (!(TWCR & (1<<TWINT)));readdata = TWDR ;SIGNALTWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //SEND STOP SIGNAL//LCD_write_english_string(10,3,'rOK');}void show_frequency(void){uint32_t nPLL =0; //Decuint32_t frequency = 0; //Khzuchar display_bit[5];uchar tbTmp1=readdata[1];uchar tbTmp2=readdata[0];tbTmp2&=0x3f;nPLL=pll ;//tbTmp2*256+tbTmp1;// calculate searched station frequency if(senddata[2]&0x10)frequency =(unsigned long)(nPLL*82/10-225); elsefrequency =(unsigned long)(nPLL*82/10+225);display_bit[0] = frequency / 100000 ;if ( display_bit[0] == 0 ) display_bit[0] = 0x20; else display_bit[0] += 0x30;display_bit[1] = (frequency / 10000)%10 +0x30;display_bit[2] = (frequency / 1000)%10 +0x30;display_bit[3] = (frequency / 100)%10 +0x30;display_bit[4] = (frequency / 10)%10 +0x30;LCD_write_english_string(0,2,' ' );LCD_write_char(display_bit[0]);LCD_write_char(display_bit[1]);LCD_write_char(display_bit[2]);LCD_write_english_string(30,2,'.' );LCD_write_char(display_bit[3]);LCD_write_char(display_bit[4]);LCD_write_english_string(48,2,' MHz' );}void show_frequency2(void){uchar display_bit[5];display_bit[0] = fre / 10000 ;if ( display_bit[0] == 0 ) display_bit[0] = 0x20;else display_bit[0] += 0x30;display_bit[1] = (fre / 1000)%10 +0x30; display_bit[2] = (fre / 100)%10 +0x30; display_bit[3] = (fre/10) %10 +0x30;display_bit[4] = fre%10+0x30;LCD_write_english_string(0,2,' ' );LCD_write_char(display_bit[0]);LCD_write_char(display_bit[1]);LCD_write_char(display_bit[2]);LCD_write_english_string(30,2,'.' );LCD_write_char(display_bit[3]); LCD_write_char(display_bit[4]);LCD_write_english_string(48,2,' }void show_rx_power(void){uchar temp;temp = (readdata[3]>>4);LCD_write_english_string(60,0,'LCD_write_char((temp/10)%10 LCD_write_char(temp%10 + } void show_rx_power_blank(void) {LCD_write_english_string(60,0,' }void calculate_pll(void){uint32_t temp;temp = fre;MHz' );');+ 0x30 ); 0x30 );');pll = (uint)( ( (temp*10-225)*4000)/32768);void init(void){DDRB = 0XFF;PORTB = 0XFF;DDRD = 0B11100000;PORTD = 0XFF;DDRC = 0B00000000;PORTC = 0Xff; // IO initdelay_nms(250);delay_nms(250);delay_nms(250);delay_nms(250);//TWITWBR = 12;TWCR = (1<<TWEN); //SEND STOP SIGNALOSCCAL=0x9d; // 8M 系统内部时钟校准// 设置MCU 的I/O 口DDRB |= LCD_RST | LCD_DC | LCD_CE | SPI_MOSI| SPI_CLK;SPSR |= (1<<SPI2X); // 设置SPI 时钟倍速SPCR |= (1<<SPE)|(1<<MSTR); // 使能SPI 接口,主机模式,4M 时钟LCD_init(); // 初始化液晶////////////////////////////////////////////////////////////////// int main(void){init();uint x;senddata[0] = pll/256; //load 100MHz pllsenddata[1] = pll%256; // away's low side senddata[2] = 0b00100000;senddata[3] = 0b10010000;senddata[4] = 0b01000000;readdata[0] = senddata[0];readdata[1] = senddata[1];LCD_write_english_string(0,0,'FM STEREO' //LCD_write_english_string(0,5,' stereo' );//LCD_write_english_string(0,2,' 99.1Mhz' ); show_frequency();LCD_write_inverse_string(0,5,' UP ');LCD_write_inverse_string(48,5,' DOWN '); station = eeprom_read_byte(22);injection );fre = eeprom_read_word( station *2); calculate_pll();show_rx_power_blank();senddata[0] = pll/256;senddata[1] = pll%256;set5767();delay_nms(200);//delay_nms(200);read5767();show_frequency2();show_rx_power();LCD_write_english_string(0,4,'CH' );LCD_write_char(station/10 +0x30);LCD_write_char(station%10 +0x30);while(1){start:if ( (PIND&0x0c) == 0x04){delay_nms(50);if ( (PIND&0x0c) == 0x04){LCD_write_english_string(48,5,' DOWN ' );delay_nms(200);x= 0;while(bit_is_clear(PIND, 3))x++;if ( x > 65530 ) //判断是否长按{if ( mode ){mode = 0; // 改变模式LCD_write_english_string(0,4,'SET CH' );LCD_write_char(station/10 +0x30);LCD_write_char(station%10 +0x30);}else{mode = 1; // 改变模式LCD_write_english_string(0,4,'CH' );LCD_write_char(station/10 +0x30);LCD_write_char(station%10 +0x30);LCD_write_english_string(24,4,' ' );eeprom_write_word(station*2,fre);loop_until_bit_is_set(PIND,3);LCD_write_inverse_string(48,5,' DOWN '); goto start;}//LCD_write_english_string(0,4,'KEY1 press' );LCD_write_inverse_string(48,5,' DOWN ');if ( mode ){station --;if ( station < 1 ) station = 10;eeprom_write_byte( 22,station);//*pst = station *2;fre = eeprom_read_word( station *2); calculate_pll(); show_rx_power_blank();senddata[0] = pll/256;senddata[1] = pll%256;set5767();delay_nms(200);delay_nms(200);read5767();show_frequency2();show_rx_power();LCD_write_english_string(0,4,'CH' );LCD_write_char(station/10 +0x30);LCD_write_char(station%10 +0x30);}else{fre -=5;if ( fre <= 8750 ) fre = 10800;calculate_pll();show_rx_power_blank();senddata[0] = pll/256;senddata[1] = pll%256;set5767();delay_nms(200);delay_nms(200);read5767();show_frequency2();show_rx_power();}}if ( (PIND&0x0c) == 0x08){delay_nms(50);if ( (PIND&0x0c) == 0x08){LCD_write_english_string(0,5,'delay_nms(200);UP ');if ( mode ){loop_until_bit_is_set(PIND, LCD_write_inverse_string(0,5,' station ++;if ( station >= 11 ) station 2);UP '); = 1;eeprom_write_byte( 22,station);//*pst = station *2;fre = eeprom_read_word( station *2);calculate_pll();show_rx_power_blank();senddata[0] = pll/256;senddata[1] = pll%256;set5767();delay_nms(200);delay_nms(200);read5767();show_frequency2();show_rx_power();LCD_write_english_string(0,4,'CH' );LCD_write_char(station/10 +0x30);LCD_write_char(station%10 +0x30);}else{fre +=5;if ( fre >= 10800 ) fre = 8750;calculate_pll();show_rx_power_blank();senddata[0] = pll/256;senddata[1] = pll%256;set5767();delay_nms(200);delay_nms(200);read5767(); show_frequency2(); show_rx_power();} }//loop_until_bit_is_set(PIND,LCD_write_inverse_string(0,5,' UP ');2);。