久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
單片機音樂閃燈(類似于音樂頻譜)制作問題
[打印本頁]
作者:
c20160526
時間:
2017-11-9 08:05
標題:
單片機音樂閃燈(類似于音樂頻譜)制作問題
我想用51單片機做一個類似于音樂頻譜,
音樂頻譜有些是8*8,12*12規格的,達到要求點亮每一級上面的LED,但點亮后的LED就只是點亮,而不是隨音樂閃動,
我是想達到要求點亮每一級上面的LED,并且LED隨音樂閃動,效果應該和舞廳效果差不多吧,
下面是論壇上面的源代碼,哪位可以幫我改改不?謝謝
#include<reg52.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 SWITCH = P2^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;
}
}
/************************************************
*名 稱: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 = 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;
}
}
/************************************************
*名 稱: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;
}
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;
}
復制代碼
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
一级少妇女片
|
黑人巨大精品欧美一区二区一视频
|
亚洲人成人一区二区在线观看
|
日韩一级电影免费观看
|
美女天堂在线
|
亚洲黄色网址视频
|
99福利视频
|
日韩欧美在线免费
|
中文字幕一区在线观看视频
|
超碰精品在线观看
|
亚洲一区二区三区视频
|
一级毛片视频免费观看
|
国产精品亚洲精品
|
久久久无码精品亚洲日韩按摩
|
欧洲av在线
|
999久久久久久久久6666
|
www.久久精品视频
|
日韩中文字幕一区二区
|
一级毛片在线播放
|
国产精品毛片一区二区在线看
|
色男人的天堂
|
在线免费观看a级片
|
日韩一级黄色毛片
|
中文字幕国产一区
|
中文字幕高清免费日韩视频在线
|
国产一级片av
|
久久综合久久自在自线精品自
|
精品成人免费一区二区在线播放
|
中文字幕免费中文
|
在线观看国产视频
|
国产成人免费一区二区60岁
|
成人欧美一区二区三区在线观看
|
亚洲成人高清
|
av看看
|
欧美综合在线观看
|
亚洲女人天堂成人av在线
|
日韩一区二区成人
|
中文字幕亚洲精品
|
国产精品久久久久久久久久久久冷
|
欧美精品一区二区三区在线播放
|
免费精品久久久久久中文字幕
|