Examen Final Procesadores Digitales de
Señales Problema 1Problema 1Problema 1Problema 1
Proyectar un sistema de control de temperatura de un líquido si tenemos un sensor de temperatura que entrega un voltaje de 0 – 8 voltios que equivale de 0 – 150 °C, y se controla el actuador con una señal de PWM. La temperatura se debe medir con la entrada analógica ADC5, generar el tiempo de muestreo con el timer 4 y el PWM con el timer 1. El controlador del sistema hacer con la entrada digital B3 y con B4 activar
un led de encendido. (8 puntos)
Solución:
• Diagrama de flujo de funcionamiento del sistema:
• Seleccione las entradas y salidas necesarias del DSP y hacer el diagrama de conexión de los dispositivos electrónicos.
Señales de la planta:
Item Descripción Código Tipo DSP
1 Señal On/Off SON/OFF Digital/Entrada GPIOB3 2 Indicador de encendido LON/OFF Digital/Salida GPIOB4 3 Señal de la salida de la planta y Analógico/Entrada ADCIN5 4 Señal de Control u PWM/Salida T1PWM_T1CMP
Diseño Electrónico de la planta:
• Diagrama de flujo del programa con las señales de DSP.
INICIO
Iniciar Timer 1
Iniciar Timer 4
Configurar Registros
Habilitar
interrupciones
SON/OFF=1
Si
No
SON/OFF=0
Detener Timer 1
Detener Timer4
Interrupcion Timer 4
Leer Señal «y» ADCIN 5
Calcular Señal de error
Error = ref- y
Guardar error anterior
errorant=Error
Calcular derivada e integral del error
Derror=(Error-errorant)/T
Ierror=Ierror+T*(Error+errorant)/2
Calcular señal de control
U=Kp*Error+Kd*Derror+Ki*Ierror
Saturar la señal de error a un maximo
del registro de periodo del timer 1
Generar PWM con :
T1CMP=U
FIN
• Programa para el DSP en C.
#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"
unsigned int Ref;
unsigned int y;
int e=0; // Error
int eant=0; // Error Anterior
float de=0; // Derivada del error
float ie=0; // Integral del error
const T=0.0005 // Tiempo de muestreo = 500 uS
const kp=10;
const ki=8;
const kd=3;
void iniciar_timer1();
void iniciar_timer4();
void iniciar_conversor_AD();
interrupt void interrupcion_timer4_muestreo();
void main()
{
DINT;
DRTM; InitSysCtrl();
InitPieCtrl();
IER = 0x0000; // Deshabilitamos interrupciones
IFR = 0x0000; // Ponemos todos los flag a 0
InitPieVectTable(); // Inicia la tabla de interrupciones
EALLOW;
PieVectTable.T4PINT = &interrupcion_timer4_muestreo; ////////////////////////////CONFIGURACION DE PUERTOS////////////////////////////
GpioMuxRegs.GPBMUX.bit.PWM10_GPIOAB3 = 0; // GPIOA0 como I/O
GpioMuxRegs.GPBMUX.bit.PWM11_GPIOAB4= 0; // GPIOA1 como I/O
GpioMuxRegs.GPAMUX.bit.T1PWM_GPIOA6 = 1; // GPIOA6 como PWM
GpioMuxRegs.GPBDIR.bit.GPIOB3 = 0; // GPIOB3 como Entrada
GpioMuxRegs.GPBDIR.bit.GPIOB4 = 1; // GPIOB4 como Salida ////////////////////////////////////////////////////////////////////////////////
EDIS;
PieCtrlRegs.PIEIER5.all = M_INT1; // Habilitamos las interrupciones T5PINT IER = IER | M_INT5;
EINT;
ERTM;
while(1){ while(GpioDataRegs.GPADAT.bit.GPIOA0==0){
GpioDataRegs.GPADAT.bit.GPIOA1=0; // Led de encendido está apagado
}
iniciar_timer1();
iniciar_timer2();
iniciar_conversor_AD();
while(GpioDataRegs.GPADAT.bit.GPIOA0==1){ // mientras que el switch permanece encendido GpioDataRegs.GPADAT.bit.GpioA1=1; // Led de encendido esta prendido
}
EvaRegs.T1CON.bit.TMODE=0; // Si se apaga el switch de encendido
EvbRegs.T4CON.bit.TMODE=0; // Detenemos los timers (Modo hold)
}
/////////////CONFIGURACION DE REGISTROS PARA INICIAR LOS TIMER//////////////////
// TIMER 1: GENERAR PWM
// TIMER 4: TEMPORIZADOR PARA LA CONVERSION ANALOGA DIGITAL
// FUNCION PARA INICIAR TIMER 1:
void iniciar_timer1(){
EvaRegs.T1PR = 0xFFFF; // Se configura el registro de periodo 10Khz
EvaRegs.T1CMPR = 0xFFFF; // Iniciamos con una comparacion
EvaRegs.T1CNT = 0x0000; // Se reinicia el contador a 0 EvaRegs.T1CON.all = 0x9702; //(75MHz/4)
asm(" nop");
asm(" nop");
EvaRegs.T1CON.all = 0x9742;
EvaRegs.EXTCONA.all = 0x0001;
} // FUNCION PARA INICIAR TIMER 4:
void iniciar_timer4(){
EvbRegs.T4PR = 0xFFFF; // Registro de periodo para configurar el tiempo de muestreo
EvbRegs.EVBIMRB.bit.T4PINT = 1; // Se habilita la interrupción del Timer4 por periodo
EvbRegs.EVBIFRB.bit.T4PINT = 1; // Se resetea el flag de la interrupcion Timer4 por periodo
EvbRegs.T4CNT = 0x0000; // Se reinicia el contador a 0
EvbRegs.T4CON.all = 0x9702; //(75MHz/4)
asm(" nop"); asm(" nop");
EvbRegs.T4CON.all = 0x9742;
EvbRegs.GPTCONB.all = 0x007A;
EvbRegs.GPTCONB.bit.T4TOADC = 2; // El flag de la interrupcion por periodo T4PER inicia la conversion ADC
EvbRegs.GPTCONB.bit.T4PIN =2; // Tipo activo alto
}
//////////////CONFIGURACION DE REGISTROS PARA INICIAR CONVERSION AD/////////////
void iniciar_conversor_AD()
{
AdcRegs.ADCTRL1.bit.RESET = 1; // Se reinicia el ADC (recomendable)
asm(" nop");
asm(" nop");
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // Preescalador para el tiempo de toma de datos del ADC
AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; // Divisor del reloj del ADC AdcRegs.ADCTRL3.bit.ADCBGRFDN = 3; // Habilitamos el circuito interno de bandgap y referencia AdcRegs.ADCTRL3.bit.ADCEXTREF = 0; // Referencia Interna 0-3.3V
DSP28x_usDelay(((((long double) 5000L * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L); // Tiempo de espera mientras
se habilita
AdcRegs.ADCTRL3.bit.ADCPWDN = 1; // Encendemos toda la circuiteria interna del conversor AD
DSP28x_usDelay(((((long double) 5000L * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L); // Tiempo de espera antes de la
primera conversion
AdcRegs.ADCTRL1.bit.RESET = 1; // Se vuelve a reiniciar el conversor AD
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // Modo cascada
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x5; // Primero convertir ADC5
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 1; // Maximo 2 conversiones simultaneas (Solo se convertira una vez)
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Configura para que vuelva a realizar las conversiones una vez que termine con
todas las del secuenciador
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // Se inicia la conversion analoga digital (En el secuenciador 1)
}
/////////////////////INTERRUPCION TIMER4 PERIODO (MUESTREO)/////////////////////////// interrupt void interrupcion_timer4_muestreo()
{
y = AdcRegs.ADCRESULT0>>4; //obteniendo la salida de la planta
eant=e; // guardando señal de error anterior
e = Ref - y; // Calculando la señal del error
de = (e – ea)/T; // Calculando derivada del error
ie = ie+T*(e+ea)/2; // Calculando integral del error u= kp*e+kd*de+ki*ie; // Calculando la señal de control
if(u>EvaRegs.T1PR) u=EvaRegs.T1PR // Saturador en caso de que la señal sea mayor al registro de periodo
EvaRegs.T1CMPR = u; // Registro de comparación igual a la señal de control
EvbRegs.EVBIMRB.bit.T4PINT = 1; // Se habilita la interrupcion EvbRegs.EVBIFRB.bit.T4PINT = 1; // Se resetea el flag de la interrupcion PieCtrlRegs.PIEACK.all = PIEACK_GROUP5;
}
Problema Problema Problema Problema 2222
Hacer un programa que genere PWMs dobles con los PWM 7, 8, 9, 10, 11, 12 con una zona muerta de 12.
(4 puntos)
Solución:
#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"
void iniciar_timer3();
void main()
{
DINT;
DRTM;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000; // Deshabilitamos interrupciones IFR = 0x0000; // Ponemos todos los flag a 0
InitPieVectTable(); // Inicia la tabla de interrupciones
EALLOW; ////////////////////////////CONFIGURACION DE PUERTOS////////////////////////////
GpioMuxRegs.GPBMUX.bit.PWM7_GPIOB0=1; // Pines de las 6 llaves de PWM7-12
GpioMuxRegs.GPBMUX.bit.PWM8_GPIOB1 =1;
GpioMuxRegs.GPBMUX.bit.PWM9_GPIOB2 =1;
GpioMuxRegs.GPBMUX.bit.PWM10_GPIOB3 =1;
GpioMuxRegs.GPBMUX.bit.PWM11_GPIOB4 =1;
GpioMuxRegs.GPBMUX.bit.PWM12_GPIOB5 =1;
//////////////////////////////////////////////////////////////////////////////// EDIS;
iniciar_timer3(); // Iniciamos timer 1 para generar PWM
EINT;
ERTM;
}
/////////////CONFIGURACION DE REGISTROS PARA INICIAR LOS TIMER////////////////// // TIMER 3: GENERAR PWM Dobles
// FUNCION PARA INICIAR TIMER 3:
void iniciar_timer3(){
EvbRegs.T3PR = 0xFFFF; // Se configura el registro de periodo 10Khz
EvbRegs.CMPR4=0x8080;
EvbRegs.CMPR5=0x0880;
EvbRegs.CMPR6=0x0080; EvbRegs.T3CNT = 0x0000; // Se reinicia el contador a 0 EvbRegs.T3CON.all = 0x9702; //(75MHz/4)
asm(" nop");
asm(" nop");
EvbRegs.T3CON.all = 0x9742;
EvbRegs.EXTCONB.all = 0x0000;
EvbRegs.COMCONB.bit.CENABLE=1; //Habilita la comparacion
EvbRegs.COMCONB.bit.SVENABLE=2; //Habilita el modo vector de PWM EvbRegs.COMCONB.bit.ACTRLD=2;
EvbRegs.COMCONB.bit.FCOMPOE=1; //Habilitar el modo Full compare
EvbRegs.COMCONB.bit.FCMP4OE=1; //Habilitar los full compare
EvbRegs.COMCONB.bit.FCMP5OE=1;
EvbRegs.COMCONB.bit.FCMP6OE=1;
EvbRegs.ACTRB.bit.CMP7ACT=1; //Activo Bajo EvbRegs.ACTRB.bit.CMP8ACT=2; //Activo Alto
EvbRegs.ACTRB.bit.CMP9ACT=2;
EvbRegs.ACTRB.bit.CMP10ACT=1;
EvbRegs.ACTRB.bit.CMP11ACT=1;
EvbRegs.ACTRB.bit.CMP12ACT=2;
EvbRegs.DBTCONB.bit.DBT=12; // Periodo de los timers de banda muerta de 4 bits
EvbRegs.DBTCONB.bit.EDBT1=1; // Habilitar timer de banda muerta 1 (PWM 7 y 8 de la unidad de comparación 1) EvbRegs.DBTCONB.bit.EDBT2=1; // Habilitar timer de banda muerta 2 (PWM 9 y 10 de la unidad de comparación 2) EvbRegs.DBTCONB.bit.EDBT3=1; // Habilitar timer de banda muerta 3 (PWM 11 y 12 de la unidad de comparación 3)
EvbRegs.DBTCONB.bit.DBTPS=5; // Preescalador 1/32 de los timer de banda muerta
}
Problema Problema Problema Problema 3333
Hacer el programa para configurar el ADC para que convierta en modo continuo las entradas ADC2, ADC5,
ADC8, ADC12, ADC3 en el orden indicado. (4 puntos)
Solución:
#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"
void iniciar_ADC() ;
void main()
{
DINT;
DRTM;
InitSysCtrl();
InitPieCtrl(); IER = 0x0000; // Deshabilitamos interrupciones
IFR = 0x0000; // Ponemos todos los flag a 0 InitPieVectTable();
EALLOW;
EDIS;
iniciar_ADC(); // Iniciamos el módulo ADC
EINT; ERTM;
}
void iniciar_ADC()
{
AdcRegs.ADCTRL1.bit.RESET = 1; // Se reinicia el ADC (recomendable)
asm(" nop");
asm(" nop");
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // Preescalador para el tiempo de toma de datos del ADC AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; // Divisor del reloj del ADC
AdcRegs.ADCTRL3.bit.ADCBGRFDN = 3; // Habilitamos el circuito interno de bandgap y referencia
AdcRegs.ADCTRL3.bit.ADCEXTREF = 0; // Referencia Interna 0-3.3V
DSP28x_usDelay(((((long double) 5000L * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L); // Tiempo de espera mientras
se habilita
AdcRegs.ADCTRL3.bit.ADCPWDN = 1; // Encendemos toda la circuiteria interna del conversor AD
DSP28x_usDelay(((((long double) 5000L * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L); // Tiempo de espera antes de la
primera conversion
AdcRegs.ADCTRL1.bit.RESET = 1; // Se vuelve a reiniciar el conversor AD AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // Modo cascada
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x2; // Primero convertir ADC2
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x5; // luego convertir ADC5
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x8; // luego convertir ADC8
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0xC; // luego convertir ADC12
// Solo 4 conversiones por registro por eso a la siguiente se cambia al registro ADCCHELSEQ2
AdcRegs.ADCCHSELSEQ2.bit.CONV00 = 0x3; // finalmente convertir ADC3
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 4; // Maximo 5 conversiones simultaneas (Solo se convertira una vez)
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Configura para que vuelva a realizar las conversiones una vez que termine con
todas las del secuenciador
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // Se inicia la conversion analoga digital (En el secuenciador 1)
}
Problema Problema Problema Problema 4444
Hacer un programa para atender una interrupción de la función de comparación simple del timer 3, definir
la función de atención de interrupción. (4 puntos)
Solución:
#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"
void iniciar_timer3();
interrupt void interrupcion_timer3_comparacion();
void main()
{ DINT;
DRTM;
InitSysCtrl();
InitPieCtrl();
IER = 0x0000; // Deshabilitamos interrupciones IFR = 0x0000; // Ponemos todos los flag a 0
InitPieVectTable(); // Inicia la tabla de interrupciones EALLOW;
PieVectTable.T3CINT = &interrupcion_timer3_comparacion;
////////////////////////////CONFIGURACION DE PUERTOS////////////////////////////
////////////////////////////////////////////////////////////////////////////////
EDIS;
PieCtrlRegs.PIEIER4.all = M_INT5; // Habilitamos las interrupciones T3CINT
IER = IER | M_INT4; iniciar_timer3(); // Iniciamos timer 3
EINT;
ERTM;
}
void iniciar_timer3(){
EvbRegs.T3PR = 0xFFFF; // Se configura el registro de periodo 10Khz
EvbRegs.T3CMPR= 0x7FFF; // Se inicia el registro de comparación
EvbRegs.EVBIMRA.bit.T3CINT= 1; EvbRegs.EVBIFRA.bit.T3CINT=1;
EvbRegs.T3CNT = 0x0000; // Se reinicia el contador a 0
EvbRegs.T3CON.all = 0x9702; //(75MHz/4)
asm(" nop");
asm(" nop");
EvbRegs.T3CON.all = 0x9742;
EvbRegs.GPTCONB.all = 0x007A;
EvbRegs.GPTCONB.bit.T3PIN =2; // Tipo activo alto }
// FUNCION PARA INICIAR TIMER 3:
interrupt void interrupcion_timer3_comparacion()
{
// AQUÍ SE ATIENDE LA INTERRUPCION
EvbRegs.EVBIMRA.bit.T3CINT = 1; // Se habilita la interrupcion
EvbRegs.EVBIFRA.bit.T3CINT = 1; // Se resetea el flag de la interrupcion
PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; }