很久沒出新作品給大家了,其實不是不想出,而是開學這段時間太忙,從八月底到九月中旬,一直為新生忙碌著,自己的時間都很少。暑假閑在家里,也因為要體驗“離開互聯(lián)網(wǎng)的日子”而未曾碰觸電腦(最近在整理假期離開網(wǎng)絡生活的文字,希望大家可以了解另一個我)。所以也不曾出教學視頻,覺得很對不住大家。
工作的時候,忙里偷閑,開通了新浪微博和新浪博客,感謝新浪推出的微號功能,讓我的域名得以和QQ號碼一樣。以后工作室的動態(tài)會同步到新浪微博,作品和相關資料下載也會同步到新浪博客,希望大家多多關注!
頻譜原理圖:
新學期新氣象,教學視頻會保持更新,并加快進度,工作室也做好了新的工作計劃,會有更優(yōu)質(zhì)的作品奉獻給大家。
希望喜歡工作室作品的朋友將我們的作品和精神分享,我們堅持創(chuàng)新,堅持開源!
這次的小作品是頻譜顯示,8*16的led顯示點陣配合stc12系列單片機系統(tǒng),就可以自己制作廉價的頻譜顯示了!
原理圖請登錄百度網(wǎng)盤下載。關于原理圖我想說的是,這是原理圖,不是封裝圖,所以大多數(shù)IC是看不到Vcc或者Gnd的,但不代表沒有,希望初學者留意。
這次的程序不是本人編寫,是我?guī)煹艿脑O計,程序是有缺陷的,比如音效的延時,顯示的效果等,有耐心的朋友可以自己修改程序,這次的作品在于分享數(shù)模轉(zhuǎn)換程序和FFT算法,我也希望網(wǎng)友可以將完善的程序分享到網(wǎng)上,大家共同進步!!!
實物照片:
下面是我的焊接工程,不熟悉電路布局的童鞋可以做為參考
點陣正面
點陣背面
系統(tǒng)板正面

系統(tǒng)板背面
成品

在這里要說的是,焊接并不算復雜,無非就是點陣的焊接耗時耗力,要是有點焊接功夫,小半天也足夠了,焊接的時候千萬不要弄斷管腳,彎折的管腳做跳線最好不過(圖3)。系統(tǒng)板的布局我建議大家緊湊一些,我自己焊接的時候是考慮到這板子以后可能加個時間顯示什么的,所以預留了一些空間,這樣以后再做點陣顯示的時候就方便多了
源程序:
- #include<stc12c5a.h>
- #include<intrins.h>
- //#include"basic.h"
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- #define ADC_FLAG (1<<4) /*ADC_中斷標志*/
- /*放大128倍后的sin整數(shù)表(128)*/
- code char SIN_TAB[128]={0,6,12,18,24,30,36,42,48,54,59,65,70,75,80,85,89,94,98,102,
- 105,108,112,114,117,119,121,123,124,125,126,126,126,126,126,
- 125,124,123,121,119,117,114,112,108,105,102,98,94,89,85,80,75,
- 70,65,59,54,48,42,36,30,24,18,12,6,0,-6,-12,-18,-24,-30,-36,-42,
- -48,-54,-59,-65,-70,-75,-80,-85,-89,-94,-98,-102,-105,-108,-112,
- -114,-117,-119,-121,-123,-124,-125,-126,-126,-126,-126,-126,-125,
- -124,-123,-121,-119,-117,-114,-112,-108,-105,-102,-98,-94,-89,-85,
- -80,-75,-70,-65,-59,-54,-48,-42,-36,-30,-24,-18,-12,-6
- };
- /*放大128倍后的cos整數(shù)表(128)*/
- code char COS_TAB[128]={127,126,126,125,124,123,121,119,117,114,112,108,105,102,98,94,
- 89,85,80,75,70,65,59,54,48,42,36,30,24,18,12,6,0,-6,-12,-18,-24,
- -30,-36,-42,-48,-54,-59,-65,-70,-75,-80,-85,-89,-94,-98,-102,
- -105,-108,-112,-114,-117,-119,-121,-123,-124,-125,-126,-126,-126,
- -126,-126,-125,-124,-123,-121,-119,-117,-114,-112,-108,-105,-102,
- -98,-94,-89,-85,-80,-75,-70,-65,-59,-54,-48,-42,-36,-30,-24,-18,
- -12,-6,0,6,12,18,24,30,36,42,48,54,59,65,70,75,80,85,89,94,98,102,
- 105,108,112,114,117,119,121,123,124,125,126,126
- };
- /*采樣存儲序列表*/
- code char LIST_TAB[128] = {0,64,32,96,16,80,48,112,8,72,40,104,24,88,56,120,4,68,36,100,20,84,52,116,
- 12,76,44,108,28,92,60,124,2,66,34,98,18,82,50,114,10,74,42,106,26,90,58,
- 122,6,70,38,102,22,86,54,118,14,78,46,110,30,94,62,126,1,65,33,97,17,81,49,
- 113,9,73,41,105,25,89,57,121,5,69,37,101,21,85,53,117,13,77,45,109,29,93,61,
- 125,3,67,35,99,19,83,51,115,11,75,43,107,27,91,59,123,7,71,39,103,23,87,55,
- 119,15,79,47,111,31,95,63,127
- };
- /*分級量化表*/
- uint8 QTY_TAB[] = {0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
- uint8 ADC_Count=0;
- uint8 i,j,k,b,p,anum;
- uint16 xdata Fft_Real[128];
- uint16 xdata Fft_Image[128]; // fft的虛部
- uint8 xdata LED_TAB[16]; //記錄紅色柱狀
- /********************************************************************
- * 名稱 : FFT
- * 功能 : 碟型運算轉(zhuǎn)換
- * 輸入 : 無
- * 輸出 : 讀出的值
- ***********************************************************************/
- void FFT()//基2fft
- {
- uint16 Temp_Real,Temp_Imag,temp; // 中間臨時變量
- uint16 TEMP1 = 0,max=0;
- for( i=1; i<=7; i++) /* for(1) */
- {
- b=1;
- b <<=(i-1); //碟式運算,用于計算隔多少行計算例如 第一極 1和2行計算
- for( j=0; j<=b-1; j++) /* for (2) */
- {
- p=1;
- p <<= (7-i);
- p = p*j;
- for( k=j; k<128; k=k+2*b) /* for (3) */
- {
- Temp_Real=Fft_Real[k];
- Temp_Imag=Fft_Image[k];
- temp=Fft_Real[k+b];
- Fft_Real[k]=Fft_Real[k]+((Fft_Real[k+b]*COS_TAB[p])>>7)+((Fft_Image[k+b]*SIN_TAB[p])>>7);
- Fft_Image[k]=Fft_Image[k]-((Fft_Real[k+b]*SIN_TAB[p])>>7)+((Fft_Image[k+b]*COS_TAB[p])>>7);
- Fft_Real[k+b]=Temp_Real-((Fft_Real[k+b]*COS_TAB[p])>>7)-((Fft_Image[k+b]*SIN_TAB[p])>>7);
- Fft_Image[k+b]=Temp_Imag+((temp*SIN_TAB[p])>>7)-((Fft_Image[k+b]*COS_TAB[p])>>7); // 移位.防止溢出. 結(jié)果已經(jīng)是本值的 1/64
- Fft_Real[k] >>= 1;
- Fft_Image[k] >>= 1;
- Fft_Real[k+b] >>= 1;
- Fft_Image[k+b] >>= 1;
- }
- }
- }
-
- for(j=0;j<16;j++)//16分頻
- {
- TEMP1=((((Fft_Real[j+1]* Fft_Real[j+1]))+((Fft_Image[j+1]*Fft_Image[j+1])))>>1);//求各頻段幅值
- if(TEMP1<1)TEMP1=0;
- LED_TAB[j]=TEMP1;
- if(LED_TAB[j]>max)max=LED_TAB[j];
- }
- if(max > 16)//分級量化
- {
- max/=16;
- for(j=0;j<16;j++)LED_TAB[j]/=max;
- }
- }
- /********************************************************************
- * 名稱 : GPIO_init
- * 功能 : GPIO初始化
- * 輸入 : 無
- * 輸出 : 讀出的值
- ***********************************************************************/
- void GPIO_init()
- {
- P0M0 = 1; P0M1 = 0; P0 = 0XFF; /*列*/
- P2M0 = 1; P2M1 = 0; P2 = 0XFF;
- P3M0 = 1; P3M1 = 0; P3 = 0XFF; /*行*/
- }
- /********************************************************************
- * 名稱 : timer_Init
- * 功能 : 內(nèi)部寄存器初始化
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void timer_Init()
- {
- TMOD = 0X12;
- TH0 = 0xb0;
- TL0 = 0xb0;
- ET0 = 1; //定時器0 打開
- TR0 = 0; //關閉定時器
- TH1 = 0xfd;
- TL1 = 0Xa8;
- ET1 = 1;
- TR1 = 1;
- EA = 1;
- }
- /********************************************************************
- * 名稱 : adc_Init
- * 功能 : 內(nèi)部寄存器初始化
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void adc_Init()
- {
- ADC_CONTR = 0x80; //ADC電源打開
- _nop_();_nop_();_nop_();_nop_();
- P1ASF = 0x01; //0000,0001, 將 P1.0 置成模擬口
- AUXR1 &=0xFB; //1111,1011, 令 ADRJ=0
- ADC_RES = 0x00; //清零寄存器
- ADC_RESL = 0x00;
- EADC = 1; //AD中斷打開
- EA = 1; //總中斷打開
- }
- /********************************************************************
- * 名稱 : main
- * 功能 : 主程序
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void main()
- {
- uint8 i = 0;
- GPIO_init();
- timer_Init();
- adc_Init();
- while(1)
- {
- ADC_Count = 0;
- EADC = 1;
- TR0 = 1;
- while(ADC_Count < 128); //滿足128點
- for(i=0; i<128; i++) //清除虛部
- {
- Fft_Image[i] = 0;
- }
- FFT(); //FFT運算并轉(zhuǎn)換為各頻段幅值
- }
- }
- /********************************************************************
- * 名稱 : ADC_Finish
- * 功能 : ADC轉(zhuǎn)換完成中斷服務
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void ADC_Finish() interrupt 5
- {
- Fft_Real[LIST_TAB[ADC_Count]] = (int)(((ADC_RES)<<1)+(ADC_RESL>>1)*2)>>3; /*按LIST_TAB表順序,進行存儲采樣值*/
- if(ADC_Count <= 127)
- {
- ADC_Count++; /*自動增量控制*/
- ADC_CONTR &= !ADC_FLAG;
- }
- else
- {
- EADC = 0;
- TR0 = 0;
- }
- }
- /********************************************************************
- * 名稱 : interrupt_timer1
- * 功能 : 顯示屏幕刷新中斷服務
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void interrupt_timer1() interrupt 3
- {
- static uint8 rec = 0;
- TH1 = 0xfd;
- TL1 = 0Xa8;
- switch(rec) //往點陣屏填充一列的數(shù)據(jù)
- {
- case 0: P0 = QTY_TAB[LED_TAB[0]]; P2 = 0;break;
- case 1: P0 = QTY_TAB[LED_TAB[1]]; P2 = 1;break;
- case 2: P0 = QTY_TAB[LED_TAB[2]]; P2 = 2;break;
- case 3: P0 = QTY_TAB[LED_TAB[3]]; P2 = 3;break;
- case 4: P0 = QTY_TAB[LED_TAB[4]]; P2 = 4;break;
- case 5: P0 = QTY_TAB[LED_TAB[5]]; P2 = 5;break;
- case 6: P0 = QTY_TAB[LED_TAB[6]]; P2 = 6;break;
- case 7: P0 = QTY_TAB[LED_TAB[7]]; P2 = 7;break;
- case 8: P0 = QTY_TAB[LED_TAB[8]]; P2 = 8;break;
- case 9: P0 = QTY_TAB[LED_TAB[9]]; P2 = 9;break;
- case 10: P0 = QTY_TAB[LED_TAB[10]]; P2 = 10;break;
- case 11: P0 = QTY_TAB[LED_TAB[11]]; P2 = 11;break;
- case 12: P0 = QTY_TAB[LED_TAB[12]]; P2 = 12;break;
- case 13: P0 = QTY_TAB[LED_TAB[13]]; P2 = 13;break;
- case 14: P0 = QTY_TAB[LED_TAB[14]]; P2 = 14;break;
- case 15: P0 = QTY_TAB[LED_TAB[15]]; P2 = 15;break;
- default:break;
- }
- rec++;
- if(rec > 15)
- {
- rec = 0;
- }
- }
- /********************************************************************
- * 名稱 : Ad_Control
- * 功能 : 控制采樣率
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void Ad_Control() interrupt 1
- {
- ADC_CONTR = 0xe8; //開始AD采集
- _nop_();_nop_();_nop_();_nop_();
- }
復制代碼
|