En realitat es tracta d'un micròfon i un petit amplificador muntat en una placa, com aquest que permet ajustar l'amplificació del senyal.
[AF]El sensor es connecta amb tres fils: els d'alimentació (positiu, VCC, i negatiu, GND) i el de senyal que connectarem a una entrada analògica.
El sensor ens dona una lectura proporcional al senyal de so, que és una ona. Atès que les entrades analògiques només admeten tensions positives, el sensor suma la meitat de la tensió d'alimentació al senyal de sortida. Això vol dir que en silenci llegirem un valor de 511 i quan hi ha so tindrem valors que oscil·laran al voltant d'aquest nombre. En el nostre cas connectarem el sensor a l'entrada AN8 (pota RC6). En la figura, tenim un exemple d'una ona de so que té la mitjana al voltant de 511 (com és esperable), un valor màxim de l'ordre de 780 i un valor mínim de l'ordre de 230.

Farem un programa de prova que ens permeti llegir 32 valors del sensor durant un temps de 20 ms. Els valors llegits els mostrarem a una pantalla LCD. Si dividim els 20 ms en 32 parts ens surt que cal llegir un valor cada 625 μs. Per comptar el temps farem servir el Timer 0. Ens interessa posar-li un factor de configuració que tingui el màxim nombre d'iteracions possible (per tenir la màxima precisió) però que sigui inferior a 256. La presselecció que candrà posar-hi serà la diferència entre 256 i el nombre d'iteracions. Veiem algun cas:
| Bits | Escala | Període | Iteracions | Preselecció |
| 111 | 1/256 | 256 μs | 2 | 254 |
| ... | ... | ... | ... | ... |
| 010 | 1/8 | 8 μs | 78 | 178 |
| 001 | 1/4 | 4 μs | 156 | 100 |
| 000 | 1/2 | 2 μs | 313 | --- |
Ens quedem amb el penúltim valor. El temporitzador partirà d'un valor de 100 i s'anirà incrementant cada 4 μs. Quan arribi a zero hauran passat 624 μs. Cada cop que el temporitzador acabi de comptar el reiniciarem, llegirem l'entrada analògica i guardarem el resultat a la memòria. Llegirem 32 valors de dos bytes cada un; en total 64 bytes. Quan l'usuari premi el polsador, escriurem els 32 valors llegits a la pantalla. Inicialment els quatre primers a la primera línia (quatre caràcters per valor) i els quatre següents a la segona; amb això en tindrem 8. Quan premem el polsador n'escriurem 8 més i així fins que al quart cop ja els haurem escrit tots.
El programa principal i les subfuncions BCD5 i Separa fan servir adreçament indirecte sobre adreces diferents. Per evitar conflictes cal guardar els contingut de FSR a una variable (Indir) a l'entrar a la funció i recuperar-lo al moment de sortir.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Lectura:.64 ; Lectures Comptador ; Comptador d'iteracions programa principal Compta ; Comptador d'iteracions funció Linia Compt ; Comptador d'iteracions subfuncions BCD5 i Separa Temp ; Variable temporal Indir ; Variable temporal per guardar FSR Valor:2 ; Valor d'entrada (16 bits) Resul:5 ; Valor de sortida Caracter ; Caràcter o codi a enviar Retard1 ; Variables per als cicles de retard Retard2 endc
org 0 Inici bsf STATUS,RP0 ; Tria el banc 1 movlw b'10000001' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 001 - Factor d'escala de 4 ; I resistències de pull-up desactivades (valor per defecte) movwf OPTION_REG ; Ho guarda al registre de configuració del Timer0 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada clrf TRISB ; Tot el port B és de sortida movlw b'01000000' ; Posa RC6 (AN8) com a entrada movwf TRISC ; La resta del port C és de sortida movlw b'00010000' ; Posa el conversor a 1/8 de la freqüència movwf ADCON1 ; Copia W a la configuració del conversor A/D bsf TXSTA,BRGH ; Configuració de velocitat bcf BAUDCTL,BRG16 ; Paràmetre de velocitat de 8 bits movlw .25 ; Velocitat de 9600 baud movwf SPBRG ; Paràmetre de velocitat bcf TXSTA,SYNC ; Comunicació asíncrona bcf TXSTA,TX9 ; Comunicació de 8 bits bcf STATUS,RP0 ; Tria el banc 0 bsf RCSTA,SPEN ; Activa comunicació sèrie bsf STATUS,RP0 ; Tria el banc 1 bsf TXSTA,TXEN ; Activa comunicació bcf STATUS,RP0 ; Tria el banc 0 bsf STATUS,RP1 ; Tria el banc 2 movlw b'00000001' movwf ANSEL ; Configura port AN0 com entrada analògica movlw b'00000001' movwf ANSELH ; Configura port AN8 com entrada analògica bcf STATUS,RP1 ; Tria el banc 0 clrf PORTB ; Desactiva les sortides del port B clrf PORTC ; Desactiva les sortides del port C movlw 'P' ; Lletra movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw 'r' ; Lletra movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw 'e' ; Lletra movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw 'm' ; Lletra movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw b'10100001' ; activa el conversor A/D connectat a AN8 movwf ADCON0 ; amb el resultat justificat per la dreta clrw ; Dos bucles de 0,2 s call Retard ; Crida a la funció Retard, el paràmetre està a W call Retard ; Per assegurar la desconnexió del programador movlw .100 ; Presselecció de 100, que són 156 iteracions ; (amb un factor 4 dona 624) movwf TMR0 ; Ho posa com a preselecció del temporitzador bcf INTCON,T0IF ; Desactivem el bit de final de temporització movlw .32 ; Volem 32 iteracions (32 lectures) movwf Comptador ; Comptador d'iteracions movlw Lectura ; Agafa l'adreça de la memòria de lectures movwf FSR ; Adreçament indirecte Bucle movlw .100 ; Presselecció de 100, que són 156 iteracions ; (amb un factor 4 dona 624) btfss INTCON,T0IF ; Mira si Timer0 ha arribat a zero ; Si hi ha arribat, no fa la instrucció següent goto $-1 ; Si no hi ha arribat, repeteix la instrucció movwf TMR0 ; Posa el 100 com a preselecció del temporitzador bcf INTCON,T0IF ; Si ha arribat, desactivem el bit nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon, en total 5 bsf ADCON0,GO ; Inicia la conversió btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat goto $-1 ; repetim la línia fins que deixi de ser 1 bsf STATUS,RP0 ; Tria el banc 1 movf ADRESL,w ; Llegim byte inferior del resultat bcf STATUS,RP0 ; Tria el banc 0 movwf INDF ; El guardem incf FSR,f ; Incrementem punter movf ADRESH,w ; Llegim byte superior del resultat movwf INDF ; El guardem incf FSR,f ; Incrementem punter decfsz Comptador,f ; Decrementem el comptador goto Bucle ; Repetim-ho... ; Acabada la lectura, anem a mostrar els resultats movlw .4 ; A cada pantalla hi caben 1/4 dels resultats movwf Comptador ; Comptador d'iteracions (quatre pantalles de 8 valors) movlw Lectura ; Agafa l'adreça de la memòria de lectures movwf FSR ; Adreçament indirecte Bucle4 btfsc PORTA,3 ; Mira el polsador goto $-1 ; Espera a que estigui premut clrw ; Bucle de 0,2 s call Retard ; Crida a la funció Retard, el paràmetre està a W btfss PORTA,3 ; Mira el polsador goto $-1 ; Espera a que no estigui premut clrw ; Bucle de 0,2 s call Retard ; Crida a la funció Retard, el paràmetre està a W movlw .254 ; Control de la posició del cursor movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw .1 ; Esborra la pantalla movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia call Linia ; Escriu els de la primera línia (4 valors) movlw .254 ; Control de la posició del cursor movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw .64 ; Filera 2 columna 1 iorlw b'10000000' ; Posa el bit de posicionat a 1 movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia call Linia ; Escriu els de la segona línia (4 valors més) decfsz Comptador,f ; Decrementem el comptador goto Bucle4 ; Repetim-ho... goto $
; ; funcions d'escriptura a la pantalla ; Linia ; Escriu una línia de la pantalla (la primera adreça a W) movlw .4 ; Volem 4 iteracions (4 lectures) movwf Compta ; Comptador d'iteracions BucleLin movf INDF,w ; Byte inferior movwf Valor ; Variable per a convertir a BCD incf FSR,f ; Incrementem punter movf INDF,w ; Byte superior movwf Valor+1 ; Variable per a convertir a BCD incf FSR,f ; Incrementem punter call BCD5 ; Ho convertim a BCD call Separa ; Ho separem en 5 bytes movf Resul+3,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Resul+2,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Resul+1,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Resul,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia decfsz Compta,f ; Decrementa el comptador goto BucleLin ; Si no és zero, seguim return ; ; Enviem caràcters a visualitzar ; EnviaL movf Caracter,f ; Agafa el caràcter movwf TXREG ; L'envia nop nop ; Espera 2 us btfss PIR1,TXIF ; El registre TXREG ha quedat lliure? goto $-1 ; No, doncs esperem return ; Tornem al lloc des d'on hem vingut ; ; Bucles de retard ; Retard ; Funció Retard, W conté ; el nombre de cicles de 771 us que cal fer movwf Retard2 ; Ho copia a la variable Retard2 BucRet decfsz Retard1,f ; Decrementa la variable 1 ; si dona zero, no es fa la instrucció següent goto BucRet ; Salta, excepte si el resultat ha estat zero decfsz Retard2,f ; Decrementa la variable 2 goto BucRet ; Salta, excepte si el resultat ha estat zero return ; Tornem al lloc des d'on hem vingut ; ; funcions de conversió a BCD ; BCD5 ; Converteix a BCD movf FSR,w ; Llegim el valor de FSR movwf Indir ; I el guardem bcf STATUS,C ; Posa a zero C per entrar zeros a les rotacions movlw .16 ; Nombre d'iteracions movwf Compt ; Comptador d'iteracions clrf Resul+2 ; Desenes de miler clrf Resul+1 ; Unitats de miler i centenes clrf Resul ; Desenes i unitats BucleBCD rlf Valor,f ; Girem bits a l'esquerra a valor rlf Valor+1,f ; Cap a valor+1 rlf Resul,f ; I cap als resultats rlf Resul+1,f rlf Resul+2,f decfsz Compt,f ; Decrementa Compt goto ajust ; Si no és zero, ajustem el resultat movf Indir,w ; Recuperem el valor de FSR movwf FSR ; I el guardem al seu lloc retlw 0 ; Si és zero ja estem; tornem un 0 a W ajust ; funció d'ajust dels resultats movlw Resul ; Agafem l'adreça del byte de menys pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a la dreta movlw Resul+1 ; Agafem l'adreça del byte del mig movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte del mig movlw Resul+2 ; Agafem l'adreça del byte de més pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a l'esquerra goto BucleBCD ; Torna a repetir el bucle (fins a 16 cops) ajustBCD ; funció d'ajust d'un byte, primer el nibble ; de la dreta, després l'altre movlw 0x03 ; Agafa el valor 03h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,3 ; És més gran que 07h (s'ha activat el bit 3)? movwf INDF ; Si és cert, sobreposa el resultat movlw 0x30 ; Agafa el valor 30h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,7 ; És més gran que 70h (s'ha activat el bit 7)? movwf INDF ; Si és cert, sobreposa el resultat retlw 0 ; Retorna amb un zero a W ; ; funcions de conversió a ASCII ; Separa ; Separa els digits i els converteix a ASCII movf FSR,w ; Llegim el valor de FSR movwf Indir ; I el guardem movf Resul+2,w ; Agafa les desenes de miler movwf Resul+4 ; Les posa al seu lloc swapf Resul+1,w ; Llegeix les unitats de miler i les centenes i les ; guarda, permutades, a w andlw 0x0F ; Es queda amb les unitats de miler movwf Resul+3 ; Les posa al seu lloc movf Resul+1,w ; Llegeix les unitats de miler i les centenes i ; les guarda a w andlw 0x0F ; Es queda amb les centenes movwf Resul+2 ; Les posa al seu lloc swapf Resul,w ; Llegeix les desenes i les unitats i les ; guarda, permutades, a w andlw 0x0F ; Es queda amb les desenes movwf Resul+1 ; Les posa al seu lloc movf Resul,w ; Llegeix les desenes i les unitats i les guarda a w andlw 0x0F ; Es queda amb les unitats movwf Resul ; Les posa al seu lloc movlw .5 ; Cal fer-ho 5 cops movwf Compt ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte movlw '0' ; Carrega el codi ASCII del número 0 ; Sumant-li la xifra tindrem el codi ASCII Bucle1 addwf INDF,f ; Ho afegeix al dígit decf FSR,f ; Decrementa FSR decfsz Compt,f ; Decrementa el comptador goto Bucle1 ; Si no és zero, repetim movlw .4 ; Cal fer-ho 4 cops movwf Compt ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte Bucle2 movf INDF,w ; Llegeix el dígit xorlw '0' ; Compara amb 0 btfss STATUS,Z ; Si Z està activat eren iguals goto Final ; Si no eren iguals, ja estem movlw ' ' ; Carrega un espai en blanc movwf INDF ; Substitueix el 0 per l'espai decf FSR,f ; Decrementa FSR decfsz Compt,f ; Decrementa el comptador goto Bucle2 ; Si no és zero, repetim Final movf Indir,w ; Recuperem el valor de FSR movwf FSR ; I el guardem al seu lloc retlw 0 ; Retorna amb un 0 a W end

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.