接上TEA5767模塊后可以接受FM電臺(tái)87500——108000KHZ, 音量調(diào)節(jié)只能靜音或者打開,因?yàn)槟K本身不具有調(diào)節(jié)選項(xiàng);可以手動(dòng)設(shè)置頻率(軟件步進(jìn)精度10KHZ,模塊的角度不清楚)也可以自動(dòng)搜臺(tái),但只能應(yīng)對(duì)強(qiáng)臺(tái)的搜索。OLED我用的是1.3寸的,0.96寸也是兼容的,但貌似1.3寸版本多了兩列像素,所以可能邊緣的顯示0.96會(huì)出點(diǎn)小問題。收音模塊我是用的帶功放的,但最好買單獨(dú)的模塊來做,因?yàn)檫@個(gè)音量不可用程序調(diào)節(jié)!
主要模塊和功能如下:
1、OLED屏:操作界面顯示(選中時(shí)反顯)
2、三個(gè)10K電阻下拉的按鍵:左邊功能選擇減,中間兼“確認(rèn)”和“減”功能,右邊“加”功能
3、DS1302:提供實(shí)時(shí)時(shí)鐘:可修改時(shí)間
4、TEA5767完整帶功放模塊:收音的核心,靜音音量示數(shù)為0其余都表示聲音“開”,配有音頻口用于接入天線(實(shí)測(cè)插一個(gè)耳機(jī)效果最好)
5、STM32F103C6T6單片機(jī):C8T6也可以用,完全兼容;不過程序也就18K左右用C8浪費(fèi)了,SRAM也完全夠了
模塊的接線為:1、OLED: SCL->PA5 SDA->PA7 3.3V電源
2、按鍵:10K電阻下拉,接PA2、3、4,分別對(duì)應(yīng)按鍵1,2,3
3、TEA5767模塊:SCL->PB7 SDA->PB5
4、DS1302模塊: RST->PB10 DAT->PB1 CLK->PB0
制作出來的實(shí)物圖如下:
51hei圖片_20210812235612.jpg (1.2 MB, 下載次數(shù): 81)
下載附件
收音機(jī)整體模塊
2021-8-13 00:00 上傳
收音機(jī)整體模塊
51hei圖片_20210812235638.jpg (1005.44 KB, 下載次數(shù): 88)
下載附件
菜單界面
2021-8-13 00:02 上傳
菜單界面
51hei圖片_20210812235656.jpg (1008.75 KB, 下載次數(shù): 69)
下載附件
手動(dòng)搜臺(tái),步進(jìn)或設(shè)置
2021-8-13 00:04 上傳
手動(dòng)搜臺(tái),步進(jìn)或設(shè)置
51hei圖片_20210813000537.jpg (915.75 KB, 下載次數(shù): 68)
下載附件
收音機(jī)主界面
2021-8-13 00:06 上傳
收音機(jī)主界面
51hei圖片_20210812235643.jpg (991.2 KB, 下載次數(shù): 66)
下載附件
存臺(tái)取臺(tái)
2021-8-13 00:07 上傳
存臺(tái)取臺(tái)
51hei圖片_20210812235709.jpg (1.11 MB, 下載次數(shù): 64)
下載附件
三個(gè)按鍵進(jìn)行操作
2021-8-13 00:25 上傳
三個(gè)按鍵進(jìn)行操作
實(shí)測(cè)多次代碼各項(xiàng)功能都沒有問題可以運(yùn)行,另外程序中有一些功能選項(xiàng)沒有寫實(shí)現(xiàn)代碼,例如“恢復(fù)設(shè)置”,它們不影響最終功能的實(shí)現(xiàn)可以自由寫入需要恢復(fù)的變量;還有鬧鐘功能,只需要按照其他界面的設(shè)計(jì)邏輯寫一些“if else”語句就可以實(shí)現(xiàn),由于沒有蜂鳴器就沒寫了。不過這些都不影響主要的功能的實(shí)現(xiàn),畢竟它只是一個(gè)收音機(jī)...
部分STM32單片機(jī)代碼如下:
#include "delay.h"
#include "sys.h"
#include "stdio.h"
#include "interrupt.h"
#include "stdlib.h"
#include "oled.h"
#include "tea5657.h"
#include "ds1302.h"
#define StartPosition 0x08005000 //存取臺(tái)在flash中的起始位置,程序大概有18KB,不能與程序沖突
u32 Frequence; //頻率全局變量,單位為10KHZ
u16 count=0,result,SystemTime,Channel[41]; //存取40個(gè)臺(tái),可更改
u8 KeyState[3],Menu1, Menu2, ItemSwitch,Menu2_1;
unsigned char countNumber = 0, SetNumber[5], Time[8], TimeBuff[8], Laud, ChannelSet=1,Signal, Brightness = 3; //初始亮度為3(1—5)
unsigned char radio_write_data[5]={0x29,0xc2,0x40,0x12,0x40};
unsigned char radio_read_data[5]; //TEA5767讀出的狀態(tài)
void DrawFirst1(void); //分別為各個(gè)界面的驅(qū)動(dòng)函數(shù)
void DrawFirst2(void);
void DrawFirst3(void);
void DrawFirst4(void);
void DrawFirst5(void);
void DrawFirst6(void);
void DrawFirst7(void);
void SetPicture1_1(void);
void SetPicture2_1(void);
void SetPicture2_2(void);
void SetPicture2_5(void);
void SetPicture2_3(void);
void SetPicture2_6(void);
void ClockTime(void); //定時(shí)讀取DS1302
void InputA_Init(uint16_t a); //輸入配置函數(shù)
uint16_t FLASH_ReadHalfWord(uint32_t address); //到address讀一個(gè)16位數(shù)據(jù)
void FLASH_WriteMoreData(uint32_t startAddress,uint16_t *writeData,uint16_t countToWrite); //address寫入任意長度的16位數(shù)據(jù)
void Updata_Channel(void); //更新電臺(tái)存儲(chǔ),將數(shù)組中的電臺(tái)寫入FLASH中
void Updata_W_Channel(void); //將Flash中的電臺(tái)頻率讀到數(shù)組中
int main(void)
{
delay_init(); //延時(shí)函數(shù)初始化
OLED_Init(); //1.3寸或0.96寸OLED均可以驅(qū)動(dòng)
TIM3_INIT_Config(10); //定時(shí)10ms中斷
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級(jí)分組為組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
// OLED_ColorTurn(0); //0正常顯示,1 反色顯示
// OLED_DisplayTurn(0); //0正常顯示 1 屏幕翻轉(zhuǎn)顯示
Tea_Init(1); //收音機(jī)模塊初始化
DrawFirst1(); //主界面
OLED_Refresh(); //更新顯示
DS1302_init(); //DS1302初始化
InputA_Init(GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4); //按鍵輸入設(shè)置
// Search(Frequence*10); //搜索
while(1)
{
if(KeyState[0]==255){
KeyState[0] = 0;
Menu1++;
if(Menu1>2) Menu1=0; // 三種狀態(tài)中切換:菜單 音量 無
}
DrawFirst1(); //畫出基本界面
switch (Menu1){ //設(shè)定區(qū)域反顯操作
case 1: OLED_ShowChinese(0,2,3,16,0),
OLED_ShowChinese(16,2,4,16,0); break; //菜單
case 2: OLED_ShowChinese(75,2,5,16,0),
OLED_ShowChinese(91,2,6,16,0); break; //音量
default:break;
}
if(Menu1 == 1){ //菜單鍵 為了保持程序可讀性和整潔性,重復(fù)判斷了兩次Menu1的狀態(tài),可以將上面的顯示更新代碼移到if的大括號(hào)中
if(KeyState[1]==255)
SetPicture1_1(); //進(jìn)入菜單界面
}
else if(Menu1 == 2){ //調(diào)節(jié)音量,由于模塊本身不具有音量調(diào)節(jié)功能,故需要自行開發(fā)推薦用PWM來完成,音量大小用全局變量Laud表示,每次調(diào)音量都重新寫入
if(KeyState[1]==255) {Laud++,KeyState[1]=0,Search(Frequence*10);}
else if(KeyState[2]==255) {Laud--,KeyState[2]=0,Search(Frequence*10);} //9:01001 16: 10000 15:01111
if(Laud>19) Laud = 0; //19級(jí)可調(diào)
}
OLED_Refresh(); //更新顯示
}
}
void InputA_Init(uint16_t a){ //按鍵初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = a;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //當(dāng)按鍵沒有按下時(shí),IO口檢測(cè)為高電平,為上拉電阻模式,按下IO口與地連接,為低電平
GPIO_Init(GPIOA ,&GPIO_InitStructure);
}
void Updata_R_Channel(void)
{
u8 i;
for(i=0; i<40; i++)
{
Channel[ i] = FLASH_ReadHalfWord(StartPosition + 2*i);
}
}
void Updata_W_Channel(void)
{
FLASH_WriteMoreData(StartPosition,Channel,40);
}
uint16_t FLASH_ReadHalfWord(uint32_t address)
{
return *(__IO uint16_t*)address;
}
void FLASH_WriteMoreData(uint32_t startAddress,uint16_t *writeData,uint16_t countToWrite)
{
uint32_t offsetAddress=startAddress - 0X08000000; //計(jì)算去掉0X08000000后的實(shí)際偏移地址
uint32_t sectorPosition=offsetAddress/2048; //計(jì)算扇區(qū)地址,對(duì)于STM32F103VET6為0~255
uint32_t sectorStartAddress=sectorPosition*2048+FLASH_BASE; //對(duì)應(yīng)扇區(qū)的首地址
uint16_t dataIndex;
FLASH_Unlock(); //解鎖寫保護(hù)
FLASH_ErasePage(sectorStartAddress);//擦除這個(gè)扇區(qū)
for(dataIndex=0;dataIndex<countToWrite;dataIndex++)
{
FLASH_ProgramHalfWord(startAddress+dataIndex*2,writeData[dataIndex]);
}
FLASH_Lock();//上鎖寫保護(hù)
}
void DrawFirst1(void)
{
OLED_ShowNum(47,28,Time[4],1,16,1);//時(shí)間數(shù)字
OLED_ShowNum(55,28,Time[5],1,16,1);
OLED_ShowString(63,28,":",16,1);
OLED_ShowNum(71,28,Time[0],1,16,1);
OLED_ShowNum(79,28,Time[1],1,16,1);
OLED_ShowNum(90,35,Time[2],1,8,1);
OLED_ShowNum(96,35,Time[3],1,8,1);
OLED_ShowNum(47,48,Frequence/100,3,16,1);//頻率
OLED_ShowNum(80,48,Frequence%100,2,16,1);
OLED_ShowString(72,48,".",16,1);
OLED_ShowString(100,48,"MHZ",16,1);
OLED_ShowChinese(0,2,3,16,1); //菜單
OLED_ShowChinese(16,2,4,16,1);
OLED_ShowChinese(75,2,5,16,1); //音量
OLED_ShowChinese(91,2,6,16,1);
OLED_ShowNum(110,2,Laud,2,16,1);
OLED_ShowChinese(0,28,7,16,1); //時(shí)間
OLED_ShowChinese(16,28,8,16,1);
OLED_ShowString(32,28,":",16,1);
OLED_ShowChinese(0,48,13,16,1); //頻率
OLED_ShowChinese(16,48,19,16,1);
OLED_ShowString(32,48,":",16,1);
OLED_DrawLine(0,21,130,21,1);
}
void DrawFirst2(void)
{
OLED_ShowChinese(0,0-ItemSwitch,14,16,1); //自動(dòng)搜臺(tái)
OLED_ShowChinese(16,0-ItemSwitch,15,16,1);
OLED_ShowChinese(32,0-ItemSwitch,16,16,1);
OLED_ShowChinese(48,0-ItemSwitch,17,16,1);
OLED_ShowChinese(0,16-ItemSwitch,18,16,1); //手動(dòng)搜臺(tái)
OLED_ShowChinese(16,16-ItemSwitch,15,16,1);
OLED_ShowChinese(32,16-ItemSwitch,16,16,1);
OLED_ShowChinese(48,16-ItemSwitch,17,16,1);
OLED_ShowChinese(0,32-ItemSwitch,29,16,1), //存取電臺(tái)
OLED_ShowChinese(16,32-ItemSwitch,33,16,1),
OLED_ShowChinese(32,32-ItemSwitch,28,16,1),
OLED_ShowChinese(48,32-ItemSwitch,17,16,1);
OLED_ShowChinese(0,48-ItemSwitch,22,16,1), //設(shè)置鬧鐘
OLED_ShowChinese(16,48-ItemSwitch,23,16,1),
OLED_ShowChinese(32,48-ItemSwitch,9,16,1),
OLED_ShowChinese(48,48-ItemSwitch,10,16,1);
OLED_ShowChinese(0,64-ItemSwitch,22,16,1), //設(shè)置時(shí)間
OLED_ShowChinese(16,64-ItemSwitch,23,16,1),
OLED_ShowChinese(32,64-ItemSwitch,7,16,1),
OLED_ShowChinese(48,64-ItemSwitch,8,16,1);
OLED_ShowChinese(0,80-ItemSwitch,37,16,1); //設(shè)置亮度
OLED_ShowChinese(16,80-ItemSwitch,38,16,1);
OLED_ShowChinese(32,80-ItemSwitch,39,16,1);
OLED_ShowChinese(48,80-ItemSwitch,40,16,1);
OLED_ShowChinese(0,96-ItemSwitch,31,16,1),//恢復(fù)設(shè)置
OLED_ShowChinese(16,96-ItemSwitch,32,16,1),
OLED_ShowChinese(32,96-ItemSwitch,22,16,1),
OLED_ShowChinese(48,96-ItemSwitch,23,16,1);
OLED_ShowChinese(94,48,20,16,1),//返回
OLED_ShowChinese(110,48,21,16,1);
}
void DrawFirst3(void)
{
OLED_ShowChinese(32,0,22,16,1); //設(shè)置頻率
OLED_ShowChinese(48,0,23,16,1);
OLED_ShowChinese(64,0,13,16,1);
OLED_ShowChinese(80,0,19,16,1);
OLED_ShowChinese(94,48,20,16,1);//返回
OLED_ShowChinese(110,48,21,16,1);
OLED_ShowChinese(0,48,24,16,1); //確認(rèn)
OLED_ShowChinese(16,48,25,16,1);
OLED_ShowChinese(48,48,26,16,1); //步進(jìn)
OLED_ShowChinese(64,48,27,16,1);
OLED_ShowString(48,24,".",8,1); //頻率數(shù)據(jù)
OLED_ShowString(78,24,"MHZ",8,1);
OLED_ShowNum(20,24,SetNumber[0],1,8,1);
OLED_ShowNum(30,24,SetNumber[1],1,8,1);
OLED_ShowNum(40,24,SetNumber[2],1,8,1);
OLED_ShowNum(56,24,SetNumber[3],1,8,1);
OLED_ShowNum(66,24,SetNumber[4],1,8,1);
OLED_ShowNum(110,24,Signal,2,8,1); //信號(hào)強(qiáng)度
}
void DrawFirst4(void)
{
OLED_ShowChinese(32,0,22,16,1); //設(shè)置時(shí)間
OLED_ShowChinese(48,0,23,16,1);
OLED_ShowChinese(64,0,7,16,1);
OLED_ShowChinese(80,0,8,16,1);
OLED_ShowChinese(94,48,20,16,1);//返回
OLED_ShowChinese(110,48,21,16,1);
OLED_ShowChinese(0,48,24,16,1); //確認(rèn)
OLED_ShowChinese(16,48,25,16,1);
OLED_ShowNum(50,26,TimeBuff[0],2,8,1); //時(shí)間
OLED_ShowString(63,26,":",8,1);
OLED_ShowNum(68,26,TimeBuff[1],2,8,1);
}
void DrawFirst5(void)
{
OLED_ShowString(20,0,"Channel:",16,1); //頻道顯示
OLED_ShowNum(84,0,ChannelSet,2,16,1);
OLED_ShowNum(22,25,Channel[ChannelSet]/100,3,16,1);//頻率數(shù)據(jù)
OLED_ShowNum(55,25,Channel[ChannelSet]%100,2,16,1);
OLED_ShowString(47,25,".",16,1);
OLED_ShowString(75,25,"MHZ",16,1);
OLED_ShowChinese(0,48,33,16,1); //取臺(tái)
OLED_ShowChinese(16,48,17,16,1);
OLED_ShowChinese(48,48,29,16,1); //存臺(tái)
OLED_ShowChinese(64,48,17,16,1);
OLED_ShowChinese(94,48,20,16,1); //返回
OLED_ShowChinese(110,48,21,16,1);
}
......限于篇幅余下代碼下載附件......
51hei.png (3.32 KB, 下載次數(shù): 70)
下載附件
2021-8-13 01:30 上傳
代碼工程51hei下載地址:
TEA5767收音機(jī).7z
(630.89 KB, 下載次數(shù): 194)
2021-8-13 00:49 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|