TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: wofer en 18 de Septiembre de 2004, 15:55:00
-
Tengo un programilla de un robot el cual utiliza los 3 timers,la interrupcion usart y la analogica.El problema ke me surge eske cuando escribo el codigo de la interrupcion usart y lo compilo y se lo grabo al pic,al ponerlo en marxa,el timer0 se ve ke se ralentiza ya ke dentro de esta int. utilizo un led para señalizarlo y este se apaga y se enciende con una frecuencia de 1 segundo,cuando deberia hacerlo cada 200ms.Sin embargo,cuando no le pongo el codigo de la int_rda si ke funciona bien.Y digo "cuando pongo el codigo" porke lo normal seria ke funcionara mal al ejecutar la int. pero eske aunke desabilite la int_rda,me lo hace igual...¿?¿como puede ser ke por culpa de un codigo ke ni sikiera llega a ejecutar me funcione mal el programa????
-
Nada,ke no consigo hacerlo funcionar.¿Es posible ke halla ke seguir alguna estructura o no deba pasar de un maximo de memoria o alguna cosa por el estilo?...no se!Por lo ke visto en programas hechos por otra gente,suelen colocar las interrupciones antes del main,yo lo hago al reves,aunke no creo ke tenga nada ke ver,por si acaso lo he provado pero tampoco funciona.
Se me habia ocurrido ke podria estar el pic cascado,pero eske el mismo programa en basic si ke funciona a la perfeccion!!....ya no se ni ke pensar!
¿Alguna idea o alguna prueba ke pueda hacer???
Saludos!!
-
Porqué no pones el código? quizá viéndolo alguién te pueda hechar una mano.
Un saludo
-
las interrupciones se deben usar solo para realizar tareas muy especificas (esa es su idea
...). tu problema tiene toda la pinta de que dentro de una de esas interrupciones estas ejecutando un chorizo (je,je nombre por el que se designa un conjunto complejo de instrucciones
)
estoy con Pocher, cuelga el codigo y veras como llueven los comentarios.
saludossss
-
Ok!Voy a ver si lo apaño un poko para ke sea legible para la gente del foro y en cuanto lo tenga lo pongo.
Saludos!!
-
Despues de varias pruebas acabo de encontrar el fallo,pero no soy capaz de digereir porke falla.Esta señalizado en el final de la #INT_RDA:
#include <16f876.h>
#device adc=10 // Conversión con 10 bits
#use delay(clock=8000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
#fuses HS,NOWDT,NOPROTECT
#priority rtcc,rda,ad,timer1,timer2
#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#byte RCREG = 0x1A
#byte RCSTA = 0x18
#bit RCSTA_1 = RCSTA.1
#bit RCSTA_2 = RCSTA.2
#bit RCSTA_4 = RCSTA.4
/////////////////////////////////////////////////////////////////////////
///// VARIABLES ////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
#bit LED_ROJO = PORTC.5
#bit IMPACTO_IZKIERDA = PORTB.6
#bit IMPACTO_TRASERO = PORTC.3
#bit IMPACTO_FRONTAL = PORTC.4
#bit IMPACTO_DERECHA = PORTB.5
#bit SERVOMOTOR = PORTC.2
#bit MOTOR_MOTRIZ_AVANCE = PORTB.4
#bit MOTOR_MOTRIZ_RETROCESO = PORTB.3
int MARCAS;
#bit M_0 = MARCAS.0
#bit M_1 = MARCAS.1
#bit M_2 = MARCAS.2
#bit M_3 = MARCAS.3
#bit M_4 = MARCAS.4
#bit m_5 = MARCAS.5
#bit M_6 = MARCAS.6
#bit M_7 = MARCAS.7
int MARCAS_2;
#bit MS_5 = MARCAS_2.0
#bit MS_10 = MARCAS_2.1
#bit ADELANTE = MARCAS_2.2
#bit ATRAS = MARCAS_2.3
#bit OBS_FR_IZ_AUX = MARCAS_2.4
#bit OBS_FR_DE_AUX = MARCAS_2.5
#bit OBS_FR_T = MARCAS_2.6
#bit SET_IZKIERDA = MARCAS_2.7
int MARCAS2;
#bit SET_GIRO_DE = MARCAS2.0
#bit SET_GIRO_IZ = MARCAS2.1
#bit M2_2 = MARCAS2.2
#bit VEL_REDU = MARCAS2.3
#bit OBS_TOTAL = MARCAS2.4
#bit OBS_FRON_DE = MARCAS2.5
#bit OBS_FRON_IZ = MARCAS2.6
#bit CONF_ADELANTE = MARCAS2.7
int FILTROS;
#bit FILTRADO_DERECHA = FILTROS.0
#bit FILTRADO_IZKIERDA = FILTROS.1
#bit FILTRADO_FRONTAL = FILTROS.2
#bit FILTRADO_TRASERO = FILTROS.3
#bit OBSTACULO_DERECHA = FILTROS.4
#bit OBSTACULO_IZKIERDA = FILTROS.5
#bit OBSTACULO_FRONTAL = FILTROS.6
#bit OBSTACULO_TRASERO = FILTROS.7
int MARCAS3;
#bit INI_DERECHA = MARCAS3.0
#bit INI_IZKIERDA = MARCAS3.1
#bit CENTESIMAS = MARCAS3.2
#bit DECIMAS = MARCAS3.3
#bit UNIDADES = MARCAS3.4
#bit M3_3 = MARCAS3.5
#bit alarma = MARCAS3.6
#bit variable_ana = MARCAS3.7
int TIME_SERVO;
int I ;
int CONT_M_1_2;
int VALOR_TIMER;
int VARIABLE_V_T;
int VALOR_TIMER_2;
int VARIABLE_V_T_2;
int CONTADOR_TIEMPO;
int CONTADOR_LED;
int SEGUNDOS;
int TMR1H_AUX;
int TMR1L_AUX ;
int CONTADOR_USAR;
int CONTADOR_MENSAGE;
int PROGRAM;
long int GIRO;
long int CICLO;
long int TIEMPO_MINIMO;
long int GIRO_DERECHA;
long int GIRO_IZKIERDA;
long int RECTO;
int consigna_temp;
static int MENSAGE[10];
VOID MANIOBRA_EVASION(VOID);
void MAIN(void) {
SET_TRIS_A (0b001111);
SET_TRIS_B (0b11100100);
SET_TRIS_C (0b10011000);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(all_ANALOG);
setup_timer_0 (RTCC_DIV_256);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
set_timer1(60000);
setup_timer_2 ( T2_DIV_BY_16, 125, 10);
/* TMR1H = 253 TMR1L = 17 ----- para 3 ms
para temporizacion de X ms (la máxima posible es de 26ms) 11111101 10001
10ms ; TMR1H = 246 TMR1L = 59 ----para 10 ms
VC = ---------------- = 2500 (Se carga en Ca2 65535 - 2500)--> 53035 *BINARIO = 11110110 111011
4 * 0.125uS * 8
*/
MARCAS = 0;
MARCAS_2 = 0;
MARCAS2 = 0;
FILTROS = 0;
CICLO = 20000;
TIEMPO_MINIMO = 1000;
GIRO = 1200;
CONT_M_1_2 = 0;
CONTADOR_TIEMPO = 0;
CONTADOR_MENSAGE = 0;
MARCAS3 = 0;
FILTROS = 0;
GIRO_DERECHA = 1550;
GIRO_IZKIERDA = 1100;
RECTO = 1400;
OBS_TOTAL = FALSE;
OBS_FRON_DE = FALSE;
OBS_FRON_IZ = FALSE;
SEGUNDOS = 0;
ADELANTE = FALSE;
ATRAS = FALSE;
ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(INT_RTCC);
enable_INTERRUPTS(INT_TIMER1);
enable_INTERRUPTS(INT_TIMER2);
enable_INTERRUPTS(INT_RDA);
enable_INTERRUPTS(INT_AD);
DISABLE_INTERRUPTS(INT_EXT);
DISABLE_INTERRUPTS(INT_RB);
DISABLE_INTERRUPTS(INT_EEPROM);
DISABLE_INTERRUPTS(INT_CCP1);
DISABLE_INTERRUPTS(INT_CCP2);
DISABLE_INTERRUPTS(INT_SSP);
DISABLE_INTERRUPTS(INT_TBE);
PROGRAM = 0;
variable_ana = false;
consigna_temp = 40;
alarma = false;
//////////////////////////////////////////////////////////////////////////////
//////////////// PROGRAMA PRINCIPAL //////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
START:
// PULSO :
valor_timer = giro/128;
variable_v_t = 255 - valor_timer;
// FRECUENCIA :
ciclo = ciclo - giro;
valor_timer_2 = ciclo/128;
variable_v_t_2 = 255 - valor_timer_2;
//output_high(servomotor);
servomotor = true;
set_timer0(variable_v_t);
M_6 = true;
INICIO:
//SI NO DETECTA NADA DE FRENTE AVANZA:
while (TRUE){
if (!obstaculo_derecha && !obstaculo_frontal && !obstaculo_izkierda){
giro = recto;
delay_ms (20);
adelante = true;
atras = false;
M_0 = false;
}
// SI DETECTA OBSTACULO A LA DERECHA GIRA A LA IZKIERDA SOLO PARA ESKIVARLO:
IF ((obstaculo_derecha && !obstaculo_izkierda && !obstaculo_frontal)||(obs_fr_de_aux && obstaculo_derecha)){
adelante = true;
atras = false;
giro = giro_izkierda;
delay_ms(20);
}
ELSE
ini_derecha = false;
// SI DETECTA OBSTACULO A LA IZKIERDA GIRA A LA DEREXA SOLO PARA ESKIVARLO:
IF ((obstaculo_izkierda && !obstaculo_derecha && !obstaculo_frontal)||(obs_fr_iz_aux && obstaculo_izkierda)){
adelante = true;
atras = false;
giro = giro_derecha;
delay_ms(20);
}
ELSE
ini_izkierda = false;
// FIN SEÑALES AUXILIARES DE GIRO FORZADO
IF ((obs_fr_iz_aux || obs_fr_de_aux)&& !obstaculo_trasero){
delay_ms(50);
obs_fr_iz_aux = false;
obs_fr_de_aux = false;
}
//SI DETECTA OBSTACULO GRANDE A LA IZKIERDA PARA E INTENTA SALVARLO:
IF (obstaculo_frontal && obstaculo_izkierda && !obstaculo_derecha && !set_giro_de){
set_giro_iz = true;
MANIOBRA_EVASION();
}
ELSE{
set_giro_iz = false;
}
//SI DETECTA OBSTACULO GRANDE A LA DERECHA PARA E INTENTA SALVARLO:
IF (obstaculo_frontal && obstaculo_derecha && !obstaculo_izkierda && !set_giro_iz) {
set_giro_de = true;
MANIOBRA_EVASION();
}
ELSE{
set_giro_de = false;
}
// DETECCION DE OBSTACULO TOTAL
IF ((obstaculo_frontal && obstaculo_derecha && obstaculo_izkierda && !obstaculo_trasero) && (!set_giro_de && !set_giro_iz)) {
adelante = false;
atras = true;
giro = giro_derecha;
FOR (I=0;I<=30;++I){
IF (!Obstaculo_trasero && !M_0)
delay_ms(20);
ELSE
M_0 = true;
}
}
ELSE{
M_0 = false;
}
IF(M_0 && (obstaculo_frontal && obstaculo_derecha && obstaculo_izkierda)){
atras = false;
DELAY_MS(20);
giro = giro_izkierda;
DELAY_MS(1500);
atras = true;
DELAY_MS(1700);
M_0 = false;
}
}
/* CONTROL RADIO
while(program == 1){
if (obstaculo_derecha || obstaculo_izkierda || obstaculo_frontal)
motor_motriz_avance = false;
if (obstaculo_trasero)
motor_motriz_retroceso = false;
}
*/
}
/////////////////////////////////////////////////////////////////////////////
////////////// SUBRUTINAS /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void MANIOBRA_EVASION(void) {
IF (!OBSTACULO_TRASERO){
ADELANTE = FALSE;
ATRAS = TRUE; // RETROCESO
IF (SET_GIRO_IZ)GIRO = GIRO_IZKIERDA;
IF (SET_GIRO_DE)GIRO = GIRO_DERECHA; //COMPRUEBA HACIA KE LADO TIENE KE GIRAR
FOR(i=0;i<=15;++I){
IF(!OBSTACULO_TRASERO){
DELAY_MS(50);
}
ELSE{
OBS_FR_IZ_AUX = FALSE;
OBS_FR_DE_AUX = FALSE;
RETURN;
}
}
}
ELSE{
IF (SET_GIRO_IZ){
OBS_FR_IZ_AUX = TRUE;
}
IF (SET_GIRO_DE){
OBS_FR_DE_AUX = TRUE;
}
ATRAS = FALSE;
}
}
//////////////////////////////////////////////////////////////////////////////////////
////////////////// INTERRUPCIONES /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
#INT_RTCC
TIMER_0(){
int contador_analogico;
// PULSO :
VALOR_TIMER = GIRO/128;
VARIABLE_V_T = 255 - VALOR_TIMER;
// FRECUENCIA :
CICLO = CICLO - GIRO;
VALOR_TIMER_2 = CICLO/128;
VARIABLE_V_T_2 = 255 - VALOR_TIMER_2;
// DURACION PULSO:
IF (M_6){
SERVOMOTOR = FALSE;
M_6 = FALSE;
M_7 = TRUE;
set_timer0(VARIABLE_V_T_2);
RETURN;
}
// DURACION FRECUENCIA (20 MS)
IF (!M_6){
SERVOMOTOR = TRUE;
M_6 = TRUE;
set_timer0(VARIABLE_V_T);
++ CONTADOR_LED;
IF (CONTADOR_LED == 10){
IF (LED_ROJO && !alarma){
LED_ROJO = FALSE;
CONTADOR_LED = 0;
}
ELSE{
LED_ROJO = TRUE;
CONTADOR_LED = 0;
}
}
++contador_analogico;
if (contador_analogico == 50){
set_adc_channel(0);
read_adc(ADC_START_ONLY);
variable_ana = true;
}
if (contador_analogico == 100){
set_adc_channel(1);
read_adc(ADC_START_ONLY);
contador_analogico = 0;
variable_ana = false;
}
}
}
#int_TIMER1
TIMER_1(){
IF (MS_10){
IF (ADELANTE && !alarma){
MOTOR_MOTRIZ_AVANCE = TRUE;
}
ELSE{
MOTOR_MOTRIZ_AVANCE = FALSE; //MOTOR ON
}
IF (ATRAS && !alarma){
MOTOR_MOTRIZ_RETROCESO = TRUE;
}
ELSE{
MOTOR_MOTRIZ_RETROCESO = FALSE;
}
IF ((GIRO != RECTO) || OBSTACULO_FRONTAL){ //VELOCIDAD MODERADA
set_timer1(60000);
}
ELSE{
IF (ATRAS && (SEGUNDOS<2)){ //VELOCIDAD DE ARRANKE
set_timer1(1000);
}
ELSE{ //VELOCIDAD NORMAL
set_timer1(9000);
}
}
MS_10 = FALSE;
}
ELSE{
MOTOR_MOTRIZ_AVANCE = FALSE; //MOTOR OFF
MOTOR_MOTRIZ_RETROCESO = FALSE; //;TIEMPO DE DESCANSO MOTOR
set_timer1(62000);
MS_10 = TRUE;
}
}
#INT_TIMER2
TIMER_2(){
//;*********** INICIO DE FILTRADO ENTRADAS
// ;**************************************
IF (FILTRADO_DERECHA && !IMPACTO_DERECHA){
OBSTACULO_DERECHA = TRUE;
}
ELSE{
OBSTACULO_DERECHA = FALSE;
FILTRADO_DERECHA = FALSE;
}
IF (FILTRADO_IZKIERDA && !IMPACTO_IZKIERDA){
OBSTACULO_IZKIERDA = TRUE;
}
ELSE{
OBSTACULO_IZKIERDA = FALSE;
FILTRADO_IZKIERDA = FALSE;
}
IF (FILTRADO_FRONTAL && !IMPACTO_FRONTAL){
OBSTACULO_FRONTAL = TRUE;
}
ELSE{
OBSTACULO_FRONTAL = FALSE;
FILTRADO_FRONTAL = FALSE;
}
IF (FILTRADO_TRASERO && !IMPACTO_TRASERO){
OBSTACULO_TRASERO = TRUE;
}
ELSE{
OBSTACULO_TRASERO = FALSE;
FILTRADO_TRASERO = FALSE;
}
if (!IMPACTO_DERECHA)
FILTRADO_DERECHA = TRUE;
IF (!IMPACTO_IZKIERDA)
FILTRADO_IZKIERDA = TRUE;
IF(!IMPACTO_FRONTAL)
FILTRADO_FRONTAL = TRUE;
IF (!IMPACTO_TRASERO)
FILTRADO_TRASERO = TRUE;
// ******* FIN DE FILTRADO_ENTRADAS
// ********************************
}
#INT_RDA
RECEPCION(){
IF (RCSTA_1 || RCSTA_2){
RCSTA_4 = FALSE;
IF (RCREG != 0){
RCREG = 0;
}
RCSTA_4 = TRUE;
CONTADOR_MENSAGE = 0;
RETURN;
}
MENSAGE[CONTADOR_MENSAGE]=GETCHAR();
++CONTADOR_MENSAGE;
IF ((MENSAGE[0]=="1")){
GOTO CONTINUAR;
}
ELSE{
CONTADOR_MENSAGE=0;
RETURN;
}
CONTINUAR:
if (contador_mensage>=6){
IF(MENSAGE[1]=="P"){
if (MENSAGE[2]=="X"){
PROGRAM = 1;
CONTADOR_MENSAGE = 0;
}
if (MENSAGE[2]=="B"){
program = 0;
CONTADOR_MENSAGE = 0;
}
if (MENSAGE[2]=="T"){
consigna_temp = ((mensage[3]-48)*100)+((mensage[4]-48)*10)+(mensage[4]-48);
CONTADOR_MENSAGE = 0;
PRINtF("consiga temperatura =%du ºC
",consigna_temp);
}
}
IF(MENSAGE[1]=="G"){
GIRO = ((MENSAGE[2]-48)*1000)+((MENSAGE[3]-48)*100)+((MENSAGE[4]-48)*10)+(MENSAGE[5]-48);
CONTADOR_MENSAGE = 0;
}
IF (MENSAGE[1]=="A"){
ADELANTE = TRUE;
ATRAS = FALSE;
CONTADOR_MENSAGE = 0;
}
IF (MENSAGE[1]=="R"){
ATRAS = TRUE;
ADELANTE=FALSE;
CONTADOR_MENSAGE = 0;
}
IF (MENSAGE[1]=="S"){
ADELANTE = FALSE;
ATRAS = FALSE;
CONTADOR_MENSAGE = 0;
}
}
/*/////////////////////////////////////////////////
disable_interrupts(INT_RDA);///aki esta el fallo,si habilito
delay_ms(60); ///este trozo de codigo,todos los
enable_interrupts(INT_RDA);///temporizadores se he ralentizan
*/////////////////////////////////// y se me va el programa a fer la mar
}
#INT_AD
Analog(){
float resultado_ana;
long int grados;
int grados_motor;
resultado_ana = read_adc();
resultado_ana = (resultado_ana*150);
grados = resultado_ana/1023;
if (variable_ana)
PRINtF("temperatura ambiente =%lu ºC
",GRADOS);
else{
grados_motor = grados;
PRINtF("grados motor =%d ºC
",grados_motor);
}
if(grados_motor>=consigna_temp)
alarma = true;
else{
if(grados_motor<(consigna_temp - 5))
alarma = false;
}
}
perdonar ke os suelte todo este rollo pero eske si no lo veo no lo creo....Vale,puedo entender ke al hacer un retraso de 60ms. dentro de un ainterrupcion,el resto de temporizadores no puedan actuar,pero....CON LA INTERRUPCION DESHABILITADA¡???Si ese codigo "en teoria" no debe de ejecutarlo!Aparte,ke tampoco le he transmitido nada!!
Saludos!!!
-
Tienes habilitadas las interrupciones del TMR0, TMR1 y TMR2 (aparte también la de RDA y la del A/D).
¿Que ocurriría si cuando se está ejecutando por ejemplo la rutina de interrupción del TMR0, se desbordara por ejemplo el TMR1?
Pues, si mal no recuerdo del ensamblador cuando se entra en una interrupción el bit global de habilitación de interrupciones se bloquea (pasa a 0) para evitar que cuando esté dentro de una interrupción se pueda atender a otra (si me equivoco en algo corregirme), con lo cual no se haría caso de la interrupción del TIMER1 perdiendo precisión. Debido a esto que te cuento no es necesario que uses disable_interrupts(INT_RDA) cuando estes dentro de una interrupción ya que seguro que no la va a atender.
El problema deben de ser esos 60ms ¿Porqué?
-
Pocher tiene razón.
Al entrar en una rutina de interrupción,el compilador te baja el bit de habilitación global de interrupciones y lo vuelve a habilitar cuando acaba la ejecución de dicha rutina.No tiene sentido que deshabilites una interrupción dentro de su propio código,el delay se va a ejecutar de todas maneras,ya que si pasas por ahí es pq la interrupción se ha producido.Una temporización de 60ms supone un desfase bastante gordo,así que seguramente sea eso lo que provoca el desfase en los timers,y más teniendo en cuenta como has establecido las prioridades de interrupción.
Un saludo
-
Esta claro ke los 60ms. son un retraso enorme como para ralentizarme los temporizadores,pero eske lo ke si ke no entiendo es ke habiendo deshabilitado la interrupcion RDA en el main,esos 60 ms. me esten causando un problema ya ke jamas deberia producirse ese retraso.
Saludos!!
-
En el programa que has enviado la int RDA sí está habilitada en el main.
-
wofer:
es interesante que te acostumbre a usar esta forma
#int_TIMER1
TIMER_1(){
timer=1;
disable_interrupts(int_timer1);
}
.
.
.
main
{
.
.
.
if (timer)
{
//lo que quieras
enable_interrupts(int_timer1);
}
.
.
}
de esta forma los tiempos empleados en las interrupciones son minimos. el caso de la UART es aun mas critico. usa la interrupcion para llenar un buffer y en todo caso aumentar un contador. lo demas en el bucle principal.
saludos
-
Tienes razon Pocher,en el codigo ke puse si ke esta habilitada,pero da igual,lo he probado tanto habilitada como deshabilitada y el comportamiento es el mismo.....no deberia ejecutar ese retraso!Voy a hacer mil y una pruebas para ver si consigo dar con el porke ya ke este tipo de problemas raros con las interrupciones es el ke tenia con el Basic y por eso me cambie al C....pero veo ke me persiguen!!

Palaconcurso,como tu has dixo de colocar las int. es como se lo he visto a todo el mundo,pero ¿es por alguna razon especial como ke asi el codigo esta mas cerca del vector de interrupcion por el tema de los direccionamientos o algo asi?
Perdonar mi ignorancia,pero eske yo en todo esto tengo muy pocos conocimientos.
Saludos!!
-
simplemente es porque cuando estas dentro de una interrupcion no puedes atender a otras...
imagina que habilitas el timer y la recepcion por el serie, si el codigo que pones en el timer es muy largo (tardas tiempo en ejecutarlo) pierdes los posibles caracteres que entren en el serie ya que el buffer hardware es muy pequeño...
de la forma que te indico el peso de la ejecucion de la rutina esta en el main y puede ser interrumpido por otra interrupcion.
esto es especialmente acusado cuando usas muchas interrupciones.
saludos
-
ok pacalaconcurso.Lo ke pasa eske en este programilla ke tengo no me valdria ya ke uso retrasos dentro del main.............pero me has dado una idea de como temporizar esos retrasos con el timer usando la forma ke tu dices.
Saludos!!