一個學習單片機的程序及電路
原理圖上畫的是16 x 8的,實物是16 x 12的,另外加的4行LED分別由由P1.6、P1.7、P5.4和P5.5控制。
0.png (63.93 KB, 下載次數: 174)
下載附件
2016-5-1 19:51 上傳
完整的資料下載:
音樂頻譜.zip
(476.95 KB, 下載次數: 282)
2016-5-1 16:04 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
音樂頻譜電路圖:
0.png (133.99 KB, 下載次數: 143)
下載附件
2016-5-1 19:52 上傳
音樂頻譜源程序:
- /*-----------------------------------------------------------------------*/
- /* 單片機音樂頻譜 */
- /* 系統時鐘33MHz */
- /*-----------------------------------------------------------------------*/
- /*-----------------------------宏定義-----------------------------------*/
- #include<stc15f2k60s2.h> //stc15系列1T單片機
- #define ADC_CHANNEL 0x01 //AD轉換通道P1.0
- #define ADC_POWER 0x80 //ADC電源控制位
- #define ADC_SPEED 0x60 //90個時鐘周期
- #define ADC_START 0x08 //ADC啟動控制位
- #define ADC_FLAG 0x10 //ADC完成標志位
- #define SAMPLE_NUM 64 //取64點FFT算法
- #define NUM_2_LOG 6 //2的6次方
- #define FFT_OUT_MIN 1 //FFT運算最小值
- #define LED_C1_8 P2 //LED1~8列
- #define LED_C9_16 P3 //LED9~16列
- #define LED_R1_8 P0 //LED1~8行
- /***************************引腳定義*****************************/
- sbit LED_R1 = P0^0; //LED1~8行
- sbit LED_R2 = P0^1;
- sbit LED_R3 = P0^2;
- sbit LED_R4 = P0^3;
- sbit LED_R5 = P0^4;
- sbit LED_R6 = P0^5;
- sbit LED_R7 = P0^6;
- sbit LED_R8 = P0^7;
- sbit LED_R9 = P1^6; //LED第9行
- sbit LED_R10 = P1^7; //LED第10行
- sbit LED_R11 = P5^4; //LED第11行
- sbit LED_R12 = P5^5; //LED第12行
- sbit SWITCH = P4^5;
- /*----------------------------變量表----------------------------*/
- unsigned char code BIT_RESORT[SAMPLE_NUM] = { 0, 32, 16, 48, 8, 40, 24, 56,4, 36, 20, 52, 12, 44, 28, 60, //比特逆序重排
- 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62,
- 1, 33, 17, 49, 9, 41, 25, 57,5, 37, 21, 53, 13, 45, 29, 61,
- 3, 35, 19, 51, 11, 43, 27, 59,7, 39, 23, 55, 15, 47, 31, 63};
-
- char code SIN_TAB[SAMPLE_NUM] = { 0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 , //正弦表
- 127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,
- 0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
- -127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 };
-
- char code COS_TAB[SAMPLE_NUM] = {127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 , //余弦表
- 0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
- -127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 ,
- 0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 };
- unsigned char LED_NUM[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; //led顯示數目
- unsigned char AMP, AMP_TAB[16]; //頻譜幅值,幅值表
- unsigned char DISP_NUM; //顯示次數
- unsigned char KEEP, KEEP_NUM; //自動增益選擇
- int xdata FFT_REAL[SAMPLE_NUM]; //FFT運算結果實部
- int xdata FFT_IMAGE[SAMPLE_NUM]; //FFT運算結果虛部
- bit SWITCH_ON;
- /**************************************************************
- *名 稱:delay
- *功 能:微秒級延時
- **************************************************************/
- void Delay(unsigned int i)
- {
- while(i--);
- }
- /**************************************************************
- *名 稱:Delay_ms
- *功 能:毫秒級延時
- **************************************************************/
- void Delay_ms(unsigned int x)
- {
- unsigned int i, j;
- for(i = 0; i < x; i++)
- for(j = 0; j < 500; j++);
- }
- /**************************************************************
- *名 稱:IOInit
- *功 能:IO端口初始化
- **************************************************************/
- void IOInit(void)
- {
- P1M0 = 0x00; //高阻輸入
- P1M1 = 0x01;
- P1ASF = 0x01; //設為AD轉換
- }
- /**************************************************************
- *名 稱:Timer0Init
- *功 能:定時器0初始化100us定時
- **************************************************************/
- void TimerInit(void) //100微秒@33.000MHz
- {
- AUXR = 0XC0; //定時器0-1T,定時器1-12T
- TMOD = 0X00; //定時器0/1-方式0-16位自動重裝
- TL0 = 0X16; //定時器0-定時170us-顯示幅值
- TH0 = 0Xea;
- TL1 = 0X1C; //定時器1-定時1ms-檢測開關狀態
- TH1 = 0XF3;
- TR0=1;
- TR1 = 1;
- }
- /**********************************************************
- *名 稱:Display
- *功 能:顯示幅值
- **********************************************************/
- void Display(void)
- {
- DISP_NUM++;
- if(DISP_NUM == 17)
- DISP_NUM = 1;
- LED_R1_8 = 0X00; LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0; //顯示前先關閉
- switch(DISP_NUM) //逐列顯示
- {
- case 1: AMP = AMP_TAB[0]; LED_C1_8 = 0X01; LED_C9_16 = 0x00; break;
- case 2: AMP = AMP_TAB[1]; LED_C1_8 = 0X02; LED_C9_16 = 0x00; break;
- case 3: AMP = AMP_TAB[2]; LED_C1_8 = 0X04; LED_C9_16 = 0x00; break;
- case 4: AMP = AMP_TAB[3]; LED_C1_8 = 0X08; LED_C9_16 = 0x00; break;
- case 5: AMP = AMP_TAB[4]; LED_C1_8 = 0X10; LED_C9_16 = 0x00; break;
- case 6: AMP = AMP_TAB[5]; LED_C1_8 = 0X20; LED_C9_16 = 0x00; break;
- case 7: AMP = AMP_TAB[6]; LED_C1_8 = 0X40; LED_C9_16 = 0x00; break;
- case 8: AMP = AMP_TAB[7]; LED_C1_8 = 0X80; LED_C9_16 = 0x00; break;
- case 9: AMP = AMP_TAB[8]; LED_C1_8 = 0X00; LED_C9_16 = 0x01; break;
- case 10: AMP = AMP_TAB[9]; LED_C1_8 = 0X00; LED_C9_16 = 0x02; break;
- case 11: AMP = AMP_TAB[10]; LED_C1_8 = 0X00; LED_C9_16 = 0x04; break;
- case 12: AMP = AMP_TAB[11]; LED_C1_8 = 0X00; LED_C9_16 = 0x08; break;
- case 13: AMP = AMP_TAB[12]; LED_C1_8 = 0X00; LED_C9_16 = 0x10; break;
- case 14: AMP = AMP_TAB[13]; LED_C1_8 = 0X00; LED_C9_16 = 0x20; break;
- case 15: AMP = AMP_TAB[14]; LED_C1_8 = 0X00; LED_C9_16 = 0x40; break;
- case 16: AMP = AMP_TAB[15]; LED_C1_8 = 0X00; LED_C9_16 = 0x80; break;
- }
- if(AMP <= 8)
- {
- LED_R1_8 = LED_NUM[AMP];
- LED_R9 = 0;
- LED_R10 = 0;
- LED_R11 = 0;
- LED_R12 = 0;
- }
- if(AMP == 9)
- {
- LED_R1_8 = 0XFF;
- LED_R9 = 1;
- LED_R10 = 0;
- LED_R11 = 0;
- LED_R12 = 0;
- }
- if(AMP == 10)
- {
- LED_R1_8 = 0XFF;
- LED_R9 = 1;
- LED_R10 = 1;
- LED_R11 = 0;
- LED_R12 = 0;
- }
- if(AMP == 11)
- {
- LED_R1_8 = 0XFF;
- LED_R9 = 1;
- LED_R10 = 1;
- LED_R11 = 1;
- LED_R12 = 0;
- }
- if(AMP == 12)
- {
- LED_R1_8 = 0XFF;
- LED_R9 = 1;
- LED_R10 = 1;
- LED_R11 = 1;
- LED_R12 = 1;
- }
- // unsigned char i;
- // LED_C1_8 = 0X01; LED_C9_16 = 0X00;
- // for(i = 0; i < 8; i++)
- // {
- // if(LED_NUM[AMP_TAB[i]] <= 8)
- // {
- // LED_R1_8 = LED_NUM[AMP_TAB[i]];
- // LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 9)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 10)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 11)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 12)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 1;
- // }
- // Delay(2000);
- // LED_C1_8 <<= 1;
- // }
- // LED_C1_8 = 0X00; LED_C9_16 = 0X01;
- // for(i = 0; i < 8; i++)
- // {
- // if(LED_NUM[AMP_TAB[i]] <= 8)
- // {
- // LED_R1_8 = LED_NUM[AMP_TAB[i]];
- // LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 9)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 10)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 0; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 11)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 0;
- // }
- // if(LED_NUM[AMP_TAB[i]] == 12)
- // {
- // LED_R1_8 = 0XFF;
- // LED_R9 = 1; LED_R10 = 1; LED_R11 = 1; LED_R12 = 1;
- // }
- // Delay(2000);
- // LED_C9_16 <<= 1;
- // }
- }
- /************************************************
- *名 稱:ReadADC
- *功 能:讀取AD轉換結果
- ************************************************/
- unsigned char ReadADC(void)
- {
- ADC_CONTR = ADC_POWER + ADC_START; //啟動轉換
- Delay(50);
- while(!(ADC_CONTR & ADC_FLAG)); //等待轉換結束
- ADC_CONTR = ADC_POWER;
- return (ADC_RES << 2 + ADC_RESL);
- }
- /************************************************
- *名 稱:sqrt
- *功 能:算平方根
- ************************************************/
- short sqrt( unsigned long M) //不懂啊
- {
- unsigned int N, i;
- unsigned long tmp, ttp;
- if( M == 0 )
- return 0;
-
- N = 0;
-
- tmp = ( M >> 30 );
- M <<= 2;
- if( tmp > 1 )
- {
- N ++;
- tmp -= N;
- }
-
- for( i=15; i>0; i-- )
- {
- N <<= 1;
-
- tmp <<= 2;
- tmp += (M >> 30);
-
- ttp = N;
- ttp = (ttp<<1)+1;
-
- M <<= 2;
- if( tmp >= ttp )
- {
- tmp -= ttp;
- N ++;
- }
- }
-
- return N;
- }
- /************************************************
- *名 稱:FFT
- *功 能:快速傅里葉變換求取頻譜
- ************************************************/
- void FFT(void) //基2時分蝶式算法
- {
- // unsigned char i, j, r, m1, m2, m3, m4, k1, k2; //分別為:級號,蝶群號,運算蝶號,蝶群總數,蝶群長度,運算蝶數,蝶群址,蝶址
- // unsigned char p;
- // unsigned char MAX = 0;
- // short u, v;
- // unsigned long ulReal, ulImage;
- register unsigned char i,bb,j,k,p,MAX;
- register short TR,TI,temp;
- unsigned long ulReal;
- unsigned long ulImage;
- for(i = 0; i < SAMPLE_NUM; i++) //采樣
- {
- FFT_REAL[BIT_RESORT[i]] = ReadADC() << KEEP;
- FFT_IMAGE[i] = 0;
- }
- KEEP_NUM = FFT_REAL[2] >> 4;
- if((7 < KEEP_NUM) && (KEEP_NUM <= 8))
- KEEP = 1;
- else if((4 < KEEP_NUM) && (KEEP_NUM <= 6))
- KEEP = 2;
- else if((2 < KEEP_NUM) && (KEEP_NUM <= 4))
- KEEP = 3;
- else
- KEEP = 5;
- for( i=1; i<=NUM_2_LOG; i++)
- {
- bb=1;
- bb <<= (i-1);
- for( j=0; j<=bb-1; j++)
- {
- p=1;
- p <<= (NUM_2_LOG-i);
- p = p*j;
- for( k=j; k<SAMPLE_NUM; k=k+2*bb)
- {
- TR = FFT_REAL[k]; TI = FFT_IMAGE[k]; temp = FFT_REAL[k+bb];
- FFT_REAL[k] = FFT_REAL[k] + ((FFT_REAL[k+bb]*COS_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
- FFT_IMAGE[k] = FFT_IMAGE[k] - ((FFT_REAL[k+bb]*SIN_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);
- FFT_REAL[k+bb] = TR - ((FFT_REAL[k+bb]*COS_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
- FFT_IMAGE[k+bb] = TI + ((temp*SIN_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);
-
- FFT_REAL[k] >>= 1;
- FFT_IMAGE[k] >>= 1;
- FFT_REAL[k+bb] >>= 1;
- FFT_IMAGE[k+bb] >>= 1;
-
- }
- }
- }
- // for(i = 1; i <= NUM_2_LOG; i++)
- // {
- // m1 = 1 << (i - 1);
- // m2 = m1 << 1;
- // m3 = 1 << (NUM_2_LOG - i);
- // for(j = 0; j < m3; j++)
- // {
- // m4 = j * m2;
- // for(r = 0; r < m1; r++)
- // {
- // p = r * m3;
- // k1 = m4 + r;
- // k2 = k1 + m1;
- // u = (FFT_REAL[k2] * COS_TAB[p]) >> 7 + (FFT_IMAGE[k2] * SIN_TAB[p]) >> 7;
- // v = (FFT_IMAGE[k2] * COS_TAB[p]) >> 7 + (FFT_REAL[k2] * SIN_TAB[p]) >> 7;
- // FFT_REAL[k2] = FFT_REAL[k1] - u;
- // FFT_IMAGE[k2] = FFT_IMAGE[k1] - v;
- // FFT_REAL[k1] = FFT_REAL[k1] + u;
- // FFT_IMAGE[k1] = FFT_IMAGE[k1] + v;
- // FFT_REAL[k1] >>= 1;
- // FFT_IMAGE[k1] >>= 1;
- // FFT_REAL[k2] >>= 1;
- // FFT_IMAGE[k2] >>= 1;
- // }
- // }
- // }
- for(i = 0; i < 16; i++)
- {
- ulReal = FFT_REAL[i + 1];
- ulReal *= ulReal;
- ulImage = FFT_IMAGE[i + 1];
- ulImage *= ulImage;
- AMP_TAB[i] = sqrt(ulImage + ulReal);
- if(AMP_TAB[i] < FFT_OUT_MIN)
- AMP_TAB[i] = 0;
- else
- AMP_TAB[i] -= FFT_OUT_MIN;
- if(AMP_TAB[i] > MAX)
- MAX = AMP_TAB[i];
- }
- if(MAX > 12)
- {
- MAX /= 12;
- for(i = 0; i < 16; i++)
- AMP_TAB[i] /= MAX;
- }
- }
- /**********************************************************
- *名 稱:Display_zzz
- *功 能;顯示動畫
- **********************************************************/
- void Display_zzz(void)
- {
- //逐行掃描-4幀
- unsigned char code TAB_LED[4][24] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0xe0, 0x01, 0x40, 0x00, 0x80, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x07, 0x00, 0x02, 0x00, 0x07, 0x00, 0xe0, 0x01, 0x40, 0x00, 0x80, 0x00, 0xe0, 0x01, 0x00, 0xf8, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0xf8}};
- unsigned char i, j;
- P0 = 0x00; LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;
- for(i = 0; i < 4; i++)
- {
- for(j = 0; j < 100; j++)
- {
- LED_C1_8 = TAB_LED[i][2 * 0];
- LED_C9_16 = TAB_LED[i][2 * 0 + 1];
- LED_R1 = 1;
- Delay_ms(2);
- LED_R1 = 0;
-
- LED_C1_8 = TAB_LED[i][2 * 1];
- LED_C9_16 = TAB_LED[i][2 * 1 + 1];
- LED_R2 = 1;
- Delay_ms(2);
- LED_R2 = 0;
- LED_C1_8 = TAB_LED[i][2 * 2];
- LED_C9_16 = TAB_LED[i][2 * 2 + 1];
- LED_R3 = 1;
- Delay_ms(2);
- LED_R3 = 0;
-
- LED_C1_8 = TAB_LED[i][2 * 3];
- LED_C9_16 = TAB_LED[i][2 * 3 + 1];
- LED_R4= 1;
- Delay_ms(2);
- LED_R4 = 0;
- LED_C1_8 = TAB_LED[i][2 * 4];
- LED_C9_16 = TAB_LED[i][2 * 4 + 1];
- LED_R5 = 1;
- Delay_ms(2);
- LED_R5 = 0;
- LED_C1_8 = TAB_LED[i][2 * 5];
- LED_C9_16 = TAB_LED[i][2 * 5 + 1];
- LED_R6 = 1;
- Delay_ms(2);
- LED_R6 = 0;
- LED_C1_8 = TAB_LED[i][2 * 6];
- LED_C9_16 = TAB_LED[i][2 * 6 + 1];
- LED_R7 = 1;
- Delay_ms(2);
- LED_R7 = 0;
- LED_C1_8 = TAB_LED[i][2 * 7];
- LED_C9_16 = TAB_LED[i][2 * 7 + 1];
- LED_R8 = 1;
- Delay_ms(2);
- LED_R8 = 0;
- LED_C1_8 = TAB_LED[i][8 * 2];
- LED_C9_16 = TAB_LED[i][8 * 2 + 1];
- LED_R9 = 1;
- Delay_ms(2);
- LED_R9 = 0;
-
- LED_C1_8 = TAB_LED[i][9 * 2];
- LED_C9_16 = TAB_LED[i][9 *2 + 1];
- LED_R10 = 1;
- Delay_ms(2);
- LED_R10 = 0;
-
- LED_C1_8 = TAB_LED[i][10 *2];
- LED_C9_16 = TAB_LED[i][10 * 2 + 1];
- LED_R11 = 1;
- Delay_ms(2);
- LED_R11 = 0;
- LED_C1_8 = TAB_LED[i][11 * 2];
- LED_C9_16 = TAB_LED[i][11 * 2 + 1];
- LED_R12 = 1;
- Delay_ms(2);
- LED_R12 = 0;
- }
- }
- }
- /************************************************
- *名 稱:main
- *功 能:主函數
- ************************************************/
- void main()
- {
- IOInit(); //初始化
- TimerInit();
- DISP_NUM = 0;
- KEEP = 0;
- KEEP_NUM = 0;
- EA = 1; //開中斷
- ET1 = 1;
- while(1)
- {
- if(SWITCH_ON == 0)
- {
- ET0 = 0;
- Display_zzz();
- }
- if(SWITCH_ON == 1)
- {
- ET0 = 1;
- FFT();
- }
- }
- }
- /************************************************
- *名 稱:Timer0Interrupt
- *功 能:定時器0中斷服務程序-顯示
- ************************************************/
- void Timer0Interrupt() interrupt 1
- {
- Display();
- Delay(300);
- }
- /************************************************
- *名 稱:Timer1Interrupt
- *功 能:定時器1中斷服務程序-檢測開關狀態
- ************************************************/
- void Timer1Interrupt() interrupt 3
- {
- if(SWITCH == 1)
- SWITCH_ON = 1;
- if(SWITCH == 0)
- SWITCH_ON = 0;
- }
復制代碼
|