Cómo utilizar el microcontrolador 51 para realizar la visualización del espectro de señales de audio (que se muestran en la pantalla LCD)
Es algo difícil hacer FFT con 51. Puede utilizar la máquina 51 mejorada (RAM) como programa de referencia: #includelt;
#define uchar unsigned char;
#define uint unsigned int
#define canal 0x01 //Establece el canal AD en P1.1
//-------- ----- --------------------------------------------- ----- ------bit SDA_R=P1^2;
bit SDA_R_TOP=P1^3
bit SDA_G=P1^4;
bit SDA_G_TOP =P1^5
bit STCP=P1^6;
bit SHCP=P1^7; ----- --------------------------------------------- ----- ----------
//-------------------- ------ -------------------------------------------- ------ -------------------------------------------- ---
//Ampliar 128 veces La tabla de enteros sin (128) después de , 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};//Después de ampliar 128 veces la tabla de enteros cos (128)
código 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};//Lista de secuencias de almacenamiento de muestreo
código 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, p>
p>
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
};
uchar COUNT=0, COUNT1=0, ADC_Count=0, LINE=15, G, T;
uchar i, j, k, b, p
int Temp_Real,Tem
p_Imag, temp; // Variable temporal intermedia
uint TEMP1;
int xdata Fft_Real[128]
int xdata Fft_Image[128]; parte imaginaria
uchar xdata LED_TAB2[64]; //Registra si el flotador necesita pausar
uchar xdata LED_TAB[64] //Registra la columna roja
uchar xdata LED_TAB1[64]; //Registrar puntos flotantes
void Delay(uint a)
{
while(a--);
}void FFT()
{ //uchar X;
for( i=1; ilt;=7; i ) /* for(1) */
{
b=1;
b lt; = (i-1); ¿Cuántas filas se calculan? Por ejemplo, se calculan las filas 1 y 2 del primer polo, y el segundo nivel
for(j=0; jlt;=b-1; j) /* for (2). ) */
{
p=1;
p lt; p*j;
p>for( k=j; klt; 128; k=k 2*b) /* para (3) base dos fft */
{
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])gt; gt ;7) ((Fft_Image[k b]*SIN_TAB[p])gt;gt;7);
Fft_Image[k] = Fft_Image[k] - ((Fft_Real [k b]*SIN_TAB[p] )gt;gt;7) ((Fft_Image[k b]*COS_TAB[p])gt;gt;7);
Fft_Real[k b] = Temp_Real - (( Fft_Real[k b]*COS_TAB[p ])gt;gt;7) - ((Fft_Image[k b]*SIN_TAB[p])gt;gt;7);
Fft_Image[k b] = Temp_Imag ((temp*SIN_TAB[p])gt;gt;7) - ((Fft_Image[k b]*COS_TAB[p])gt;gt;7
// Shift. Evita el desbordamiento. El resultado ya es 1/64 del valor original
Fft_Real[k] gt; 1 ;
Fft_Real[k b] gt;
Fft_Image[k b] gt;
}
}
// X=((((Fft_Real[1]* Fft_Real[1])) ((Fft_Image[1]*Fft_Image[1]) ) )gt; gt; 7);
Fft_Real[0]=Fft_Image[0]=0; //Eliminar el componente DC
// Fft_Real[63]=Fft_Image[ 63] =0;
for(j=0;jlt;64;j )
{
TEMP1=((((Fft_Real[j]* Fft_Real[ j])) ((Fft_Image[j]*Fft_Image[j])))gt;gt;1);//Encuentra la potencia
if(TEMP1gt;1)TEMP1--;
else TEMP1=0;
if(TEMP1gt;31)TEMP1=31;
if(TEMP1gt;(LED_TAB[j]))LED_TAB[j] =TEMP1;
if(TEMP1gt; (LED_TAB1[j]))
{ LED_TAB1[j]=TEMP1
LED_TAB2[j]=18; //Velocidad de cuadro de aviso=12
}
}
}void Init()
{
//- ----------------------------------------------- --- --------------------------------
P1ASF = 0x02; //0000, 0010, P1.1 se configurará como puerto analógico
AUXR1 amp;=0xFB; //1111, 1011, configure ADRJ=0
EADC=1; activado
ADC_CONTR = ADC_POWER | ADC_SPEEDHH | ADC_START |
//1110 1001 1 Encienda la fuente de alimentación de conversión A/D (ADC_POWER); 11 velocidades son 70 ciclos;
//0 indicador de interrupción borrado; 1 inicio de adc (el canal 001AD está abierto); aquí está P1.1);
//---------------------------------- ----------- --------------------------------------- -----------
P2M0=1
P0M0=1
TMOD=0X12; > TH0=0x30; // Frecuencia de muestreo de aproximadamente 20K (requiere que la banda de frecuencia completa esté por encima de 40K. Pero la mayor parte de la frecuencia de audio está por debajo de 10k, así que elijo el muestreo de 20K, que es más hermoso)
TL0=0x30;
TH1=0xEE;
TL1=0XC0
ET0=1 //Activar temporizador 0
TR0=0; //Apagar temporizador
ET1=1;
TR1=1
PT1=0; PT0=1;
IPH=PADCH;
IP=PADC; //Nivel de prioridad de interrupción
EA=1 //Interrupción total activada
p>
}
anular ADC_Finish() interrupción 5
{ ADC_CONTR amp;= !ADC_FLAG
Fft_Real[LIST_TAB[ADC_Count]]=( int)((ADC_RES)lt;lt;1) (ADC_RESLgt;gt;1)-256;/ /-512 //Almacenamiento de valores de muestreo en el orden de la tabla LIST_TAB,
// ADC_CONTR = ADC_POWER | ADC_SPEEDHH| ADC_START | // Para recolectar voltajes negativos, se utiliza la recolección de compensación. El voltaje se incrementa a 1/2 vcc, así que resta 256
if(ADC_Countlt;=127)ADC_Count;
else {EADC=0;TR0=0;}
p>
} void LED_Display() interrupción 3 // Interrumpe para mostrar una línea a la vez. . .
{
TH1=0xF3;
TL1=0X00;
para (G=0; Glt; 64; G) / /Rellene una línea de datos en la pantalla de matriz de puntos
{
if(LED_TAB[G]lt;=LINE 16)SDA_R_TOP=1;
else SDA_R_TOP= 0;
si(LED_TAB[G]lt;=LINE)SDA_R=1;
si no SDA_R=0; =1 ;SDA_G=0;}
más si(LED_TAB1[G]==(LINE 16)){SDA_G_TOP=0;}
más SDA_G=SDA_G_TOP =1 ;
SHCP=1;
}
STCP=0; 15- LÍNEA;
if(LINEgt;0)LINE--;
else LINE=15;
////////// // ///////////////
if(LED_TAB[COUNT]gt; 0)LED_TAB[COUNT]-- //Disminución de columna,
CONTAR ;
if(LED_TAB[COUNT]gt;0)LED_TAB[COUNT]--;
CONTAR ;
si(LED_TAB[COUNT ]gt; 0)LED_TAB[COUNT]--;
COUNT;
if(LED_TAB[COUNT]gt; 0)LED_TAB[COUNT]--;
COUNT ;
if(LED_TAB[COUNT]gt; 0)LED_TAB[COUNT]--; //Columna decreciente,
COUNT;
if (LED_TAB[ COUNT]gt;0)LED_TAB[COUNT]--;
COUNT ;
if(LED_TAB[COUNT]gt;0)LED_TAB[COUNT]--;
CONTAR;
if(LED_TAB[COUNT]gt;0)LED_TAB[COUNT]--;
CONTAR;
si( COUNTgt;= 64)COUNT=0; //Los objetos flotantes están disminuyendo
if(LED_TAB2[COUNT1]==0) //Determina si se necesita una pausa
{ p>
if (LED_TAB1[COUNT1]gt; LED_TAB[COUNT1])LED_TAB1[COUNT1]--;//Disminuye si es mayor que la columna (mantén el flotador por encima de la columna)
}
más LED_TAB2[COUNT1]--;
COUNT1 ;
if(LED_TAB2[COUNT1]==0)
{
if(LED_TAB1[COUNT1]gt;LED_TAB[COUNT1])LED_TAB1[COUNT1 ]--;
}
else LED_TAB2[COUNT1]--;
COUNT1
if(LED_TAB2[COUNT1]= =0) //Determinar si se necesita una pausa
{
if(LED_TAB1[COUNT1]gt; LED_TAB[COUNT1])LED_TAB1[COUNT1]--;//Disminuir si es mayor que la forma de la columna (Mantenga el flotador encima de la columna)
}
else LED_TAB2[COUNT1]--
COUNT1; >
if( LED_TAB2[COUNT1]==0)
{
if(LED_TAB1[COUNT1]gt; LED_TAB[COUNT1])LED_TAB1[COUNT1]--; /p>
}
else LED_TAB2[COUNT1]--;
COUNT1;
if(COUNT1gt;=64)COUNT1=0;
}void Ad_Control() interrupción 1 //Controla la frecuencia de muestreo
{
ADC_CONTR = ADC_POWER | ADC_SPEEDHH| //Iniciar adquisición de AD
}
//=================================== ======== =========================================== ======== ===================
// ************** ***** principal() **********************************
// ======== =========================================== ======== =========================================== ======== === void main()
{
Init()
while(1)
<; p> {ADC_Count=0
TR0=1;
EADC=1 //Habilitar la interrupción del temporizador 0 y habilitar ADC
while(ADC_Countlt; 128);
FFT();
//Operación FFT. y convertido a valor de potencia. . .
// TR1=1
}
}