Continúo con respecto del PWM.
Según las definiciones anteriores, la frecuencia mínima es 261 Hz y la máxima es 3136 Hz, esto implicaría un periodo máximo de la señal PWM de 3.831 ms y mínimo de 318.88 microsegundos respectivamente.
Por lo tanto, el periodo del PWM debería ser mayor a esos 3.8 ms, por ejemplo el periodo podría ser 7ms.
Jugando con los parámetros del temporizador 3, con un escalamiento de 8, es decir con 6 Mhz, y con PR3 igual a 42000, conseguiría 7ms.
(42000/6MHz = 7 ms)
Ahora bien, si deseamos un periodo de 318.88 us, PR3 = f* T = 6MHz * 318.88 us = 1913.26, el cual es un valor que el PR3 puede poseer.
La ecuación para calcular el periodo de la señal PWM es:
Donde T
PB es el periodo de la frecuencia del reloj del bus de periféricos, es decir 1/48MHz.
TMR Prescaler Value, es el valor del pre escalamiento que es 8, es decir que T
PB * TMR Prescaler Value = 1/6MHz.
Con esto hice una tabla en Excel para conseguir los valores de PR2 para cada frecuencia auditiva:
Y lo pego en el archivo cabecera de la tarea appbuzzer: (obviamente sin decimales)
Una canción esta definida como una serie de notas musicales, y cada nota tiene un tiempo de duración.
Por lo que creo una estructura de datos de la siguiente manera:
typedef struct
{
unsigned int FrecuenciaNota;
unsigned int Tiempo;
}NotasMusicales;
Donde FrecuenciaNota es el valor del PR del temporizador, y Tiempo es la duración de la nota musical, por lo tanto creo un arreglo con 12 notas musicales así:
NotasMusicales Musica[0x0C];
Esto lo creo en el archivo en C de la tarea del buzzer.
En el estado inicial de la tarea, lo que hago, es inicializar el arreglo 'musica' con los valores de PR3 y retardos para generar la música inicial
Recuerde que 1 ms está dado por:
También, en el estado inicial de la tarea (que la renombré) deshabilito todo lo relacionado con la configuración del PWM, de lo contrario, es psoible que el buzzer haga sonidos antes de empezar a ejecutarse la tarea, e inicio o arranco al temporizador 3:
Necesito un puntero, para ir obteneindo cada valor del arreglo denominado Musica, el cual será parte de la esctructura de datos de la tarea:
Y lo inicializo en la el código en C de la tarea:
También, necesito una variable para generar retardos asincrónicos, y la escribo en la estructura de datos:
Para cambiar el valor del PR3, creo una función así:
void actualizarFrecuenciaPWM(unsigned int frecuencia)
{
TMR3_PeriodSet(frecuencia); //es similar a PR3 = frecuencia;
OCMP1_CompareSecondaryValueSet(frecuencia >> 1); // ancho de pulso en 50%
}
Donde también intento que la relación de trabajo del PWM sea del % al escribir en el registro OC1RS, la mitad del valor de PR3.
En la inicialización de la tarea, capturo un valor del temporizador central o Core Timer, y genero la primera nota con el PWM mediante la función actualizarFrecuenciaPWM
En el estado inicial, espero el tiempo que dura cada nota mediante un retardo asincrónico así:
Cuando el retardo ha finalizado, se hace lo siguiente:
Se captura un nuevo valor de temporizador central para el próximo retardo.
Incremento en 1, el puntero del arreglo denominado Musica.
Si el puntero está aún dentro del tamaño del arreglo musica, verifico que la siguiente sea
mute o silencio, si es así, apago el PWM para generar un silencio.
Si no es
mute actualizo el valor del PR3 con el valor de la siguiente nota.
Si el puntero es mayor que el tamaño del arreglo, la melodía ha finalizado , apago el PWM y salto a un estado denominado reposo, donde esperará la tarea hasta cuando se desee generar una señal acústica.
Esa señal acústica, será generada en un nuevo estado, pero eso será más adelante, por ahora sólo deseo crear esta parte del código.
Mañana, voy a probar con el hardware si este código funciona.