collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[27 de Março de 2024, 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: Routina de 1ms com o tmr0  (Lida 21108 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #15 em: 02 de Novembro de 2014, 22:39 »
Ok, o que eu quero para já é aprender a fazer uma rotina de 1ms com precisão, dai eu posso tirar 1s, 1m ou seja o que for para poder aplicar de futuro noutros projectos, segundo o meu projecto é alimentar este pic com uma pilha CR2032 de 3v que vou ligar a um daqueles modulos pequenos de RF315Khz, dai eu querer usar o oscilador interno e tambem o mais lento possivel, não demasiado lento porque vou ter que usar a USART tambem.
Mas se de futuro eu quiser usar por exemplo o protocolo OneWire preciso de precisão ao milisegundo.
Portanto para já tenho um led com a respectiva resistencia de 220 no pino 5 do 12f1822 ou RA2, mais nada.

Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #16 em: 02 de Novembro de 2014, 22:45 »
Já agora Asena, quando começei isto tinha as subrotinas em assembly, no final o resultado foi igualzinho a este, por isso decidi usar apenas C.

Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Routina de 1ms com o tmr0
« Responder #17 em: 02 de Novembro de 2014, 22:48 »
- Para 1-Wire precisas de precisao ao micro-segundo. O protocolo eh apertado mas permite algum erro.

- Ainda escrevo em ASM qd preciso de precisao em termos de poder controlar os ciclos todos do programa. Posso-te garantir que eh possivel fazer as rotinas q quiseres, a demorar o tempo q quiseres !! :)


Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #18 em: 02 de Novembro de 2014, 23:01 »
Vou procurar e já te mostro.  :)

Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #19 em: 02 de Novembro de 2014, 23:15 »
Asena, não encontrei mas fiz aqui uma rapidamente.
Continua impreciso na mesma.
Usei o Code generator.

Código: [Seleccione]
#include <pic12f1822.h>


/* Setup chip configuration */
__code int __at(_CONFIG1) __CONFIG = _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF;

void setup(void);
void delay_ms(int milis);



void main(void) {

    setup();


    while(1) {

        delay_ms(1000);
        LATA |= (1<<2);
        delay_ms(1000);
        LATA &= ~(1<<2);
    }

}

void setup(void) {

    OSCCON = 0b01011000; // 1MHZ internal clock
    LATA = 0;
    TRISA = 0x00;
    PORTA = 0x00;
__asm
cblock 0x20
d1
endc
__endasm;

}

void delay_ms(int milis) {

    while (milis--) {
    __asm
        movlw   0x51
        movwf   d1
        Delay_0:
        decfsz  d1, f
        goto    Delay_0
    __endasm;
    }
}

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: Routina de 1ms com o tmr0
« Responder #20 em: 02 de Novembro de 2014, 23:34 »
Assim, de forma rápida, no XC8...

Tenta lá o *.hex do anexo.

Não deve dar um erro assim tão grande...
Já usei esse micro e é brutal para aplicações pequenas. Nunca tive grande problemas com coisas destas...

Tem um pequeno desvio... mas deve ser alguma coisa a rondar os ~700uS por cada minuto, segundo o simulador...

O LED vai ficar 1min ligado, 1min desligado, e assim sucessivamente...

Código: [Seleccione]
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

#define _XTAL_FREQ 1000000

unsigned char seg = 0;
unsigned int cont = 0;

void interrupt isr (void)
{
    if(INTCONbits.T0IF)
    {
        TMR0 += 6;

        cont++;

        if(cont>=1000)
        {
            seg++;
            cont = 0;
        }

        if(seg>=60)
        {
            seg = 0;
            LATAbits.LATA2 = !LATAbits.LATA2;
        }

        INTCONbits.T0IF = 0; 
    }

}


void init_osc(void)         //1MHz
{
    OSCCONbits.SPLLEN = 0;
    OSCCONbits.IRCF = 0b1011;
    OSCCONbits.SCS = 0;
}

void init_port(void)
{
    TRISA   = 0;
    LATA    = 0;
    ANSELA  = 0;
}

void interrup(void)
{
    INTCONbits.T0IF = 0;
    INTCONbits.T0IE = 1;
    INTCONbits.GIE = 1;
}

void init_timer0(void)
{
    OPTION_REGbits.TMR0CS = 0;
    OPTION_REGbits.T0SE = 0;
    OPTION_REGbits.PSA = 1;
    TMR0 = 0;
}

void main(void)
{
    init_osc();
    init_port();
    init_timer0();
    interrup();

    LATAbits.LATA2 = 1;
    TMR0 = 6;

    while(1);
}

David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #21 em: 02 de Novembro de 2014, 23:55 »
Sim está bem perto de um minuto  :).
Mas tenho de esperimentar isto com 1s ai é que se vê claramente com um cronometro ao lado.
O código que postei acima com a rotina em assembly tambem está igualmente perto.
Já agora o XC da microchip não traz rotinas de delay ? ou outro tipo de libs ?

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: Routina de 1ms com o tmr0
« Responder #22 em: 03 de Novembro de 2014, 00:16 »
Sim tras... mas no caso usar vários delays para fazer 1 min vai dar num grande erro também...
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: Routina de 1ms com o tmr0
« Responder #23 em: 03 de Novembro de 2014, 00:20 »
Mas tenho de esperimentar isto com 1s ai é que se vê claramente com um cronometro ao lado.
Isso é relativo... vais ter imensa dificuldade em cronometrar manualmente o tempo certo.

Tenta o *.hex em anexo para 1segundo.

O LED vai ter um comportamento semelhante ao de 1min, mas agora a cada segundo.

Segundo o simulador dá um erro de ~12uS...
« Última modificação: 03 de Novembro de 2014, 00:22 por Dave »
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Routina de 1ms com o tmr0
« Responder #24 em: 03 de Novembro de 2014, 08:20 »
Asena, não encontrei mas fiz aqui uma rapidamente.
Continua impreciso na mesma.
Usei o Code generator.

Código: [Seleccione]
#include <pic12f1822.h>


/* Setup chip configuration */
__code int __at(_CONFIG1) __CONFIG = _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF;

void setup(void);
void delay_ms(int milis);



void main(void) {

    setup();


    while(1) {

        delay_ms(1000);
        LATA |= (1<<2);
        delay_ms(1000);
        LATA &= ~(1<<2);
    }

}

void setup(void) {

    OSCCON = 0b01011000; // 1MHZ internal clock
    LATA = 0;
    TRISA = 0x00;
    PORTA = 0x00;
__asm
cblock 0x20
d1
endc
__endasm;

}

void delay_ms(int milis) {

    while (milis--) {
    __asm
        movlw   0x51
        movwf   d1
        Delay_0:
        decfsz  d1, f
        goto    Delay_0
    __endasm;
    }
}



O facto de teres uma parte do codigo em ASM nao significa q as temporizacoes estao certas.

Estahs a ter em conta os saltos para entrar e sair da funcao?
O teu loop While estahs a ser convertido para ASM de q forma?

Trabalhar com tempos precisos tem algumas nuances pois no Arduino as brincadeiras nao teem importancia se atrasarem, mas em trabalhos com plataformas a serio as coisas mudam de figura e tem q se "escrever" tudo como se quer.


Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Routina de 1ms com o tmr0
« Responder #25 em: 03 de Novembro de 2014, 08:21 »
Mas tenho de esperimentar isto com 1s ai é que se vê claramente com um cronometro ao lado.
Isso é relativo... vais ter imensa dificuldade em cronometrar manualmente o tempo certo.

Tenta o *.hex em anexo para 1segundo.

O LED vai ter um comportamento semelhante ao de 1min, mas agora a cada segundo.

Segundo o simulador dá um erro de ~12uS...


Querias dizer ~12 mili-segundos ?   pela imagem do simulador eh o q lah esta.


Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Routina de 1ms com o tmr0
« Responder #26 em: 03 de Novembro de 2014, 08:37 »
Assim, de forma rápida, no XC8...

Tenta lá o *.hex do anexo.

Não deve dar um erro assim tão grande...
Já usei esse micro e é brutal para aplicações pequenas. Nunca tive grande problemas com coisas destas...

Tem um pequeno desvio... mas deve ser alguma coisa a rondar os ~700uS por cada minuto, segundo o simulador...

O LED vai ficar 1min ligado, 1min desligado, e assim sucessivamente...

Código: [Seleccione]
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

#define _XTAL_FREQ 1000000

unsigned char seg = 0;
unsigned int cont = 0;

void interrupt isr (void)
{
    if(INTCONbits.T0IF)
    {
        TMR0 += 6;

        cont++;

        if(cont>=1000)
        {
            seg++;
            cont = 0;
        }

        if(seg>=60)
        {
            seg = 0;
            LATAbits.LATA2 = !LATAbits.LATA2;
        }

        INTCONbits.T0IF = 0; 
    }

}


void init_osc(void)         //1MHz
{
    OSCCONbits.SPLLEN = 0;
    OSCCONbits.IRCF = 0b1011;
    OSCCONbits.SCS = 0;
}

void init_port(void)
{
    TRISA   = 0;
    LATA    = 0;
    ANSELA  = 0;
}

void interrup(void)
{
    INTCONbits.T0IF = 0;
    INTCONbits.T0IE = 1;
    INTCONbits.GIE = 1;
}

void init_timer0(void)
{
    OPTION_REGbits.TMR0CS = 0;
    OPTION_REGbits.T0SE = 0;
    OPTION_REGbits.PSA = 1;
    TMR0 = 0;
}

void main(void)
{
    init_osc();
    init_port();
    init_timer0();
    interrup();

    LATAbits.LATA2 = 1;
    TMR0 = 6;

    while(1);
}



O facto de teres a rotina de Interrupcao cheia de codigo, eh propositadamente educativo? ou eh naturalmente como programas?

A funcao de interrupcao nao deve ter nada a nao ser Set/Clear de Flags. Qq codigo extra atrasa todo o processo em curso no Main.

Assim estaria mais correcto ::


void interrupt isr (void)
{
    if(INTCONbits.T0IF)
    {
        INTCONbits.T0IF = 0; 

        TMR0 += 6;

        FLAG-TMR0 = 1;
    }
}


Main:
   if (FLAG-TMR0)
   {
        cont++;

        if(cont>=1000)
        {
            seg++;
            cont = 0;
        }

        if(seg>=60)
        {
            seg = 0;
            LATAbits.LATA2 = !LATAbits.LATA2;
        }
    }




Eh mais ou menos isto q estava a falar.
E mesmo aquele TMR0 += 6 ali, da-me arrepios :D

Crias uma estrutura so com registos de Flags e podes usar isso por todo o programa.

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: Routina de 1ms com o tmr0
« Responder #27 em: 03 de Novembro de 2014, 09:02 »

Querias dizer ~12 mili-segundos ?   pela imagem do simulador eh o q lah esta.

Há dias lixados... xD

Sim ~12milisegundos :D

Quanto ao resto, não é comum. É um programa rápido para mostrar que funciona.
De qualquer forma, para o que o micro está a fazer, não há nada a correr no main e o timer não para, seja onde estiver. Por isso o resultado, neste caso, ia dar os mesmos tempos, quer da minha forma quer da tua, acho eu... mas tu é que és o mestre :D.


PS: Estava aqui a tentar ver melhor, "FLAG-TMR0" deveria ser "FLAG_TMR0"?
Se não for,  não consigo entender o objectivo. Se puderes, depois dá uma explicação ;)


Abraço.
« Última modificação: 03 de Novembro de 2014, 09:08 por Dave »
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Sérgio_Sena

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.649
    • Electronic Gear for Musicians
Re: Routina de 1ms com o tmr0
« Responder #28 em: 03 de Novembro de 2014, 09:47 »

Querias dizer ~12 mili-segundos ?   pela imagem do simulador eh o q lah esta.

Há dias lixados... xD

Sim ~12milisegundos :D

Quanto ao resto, não é comum. É um programa rápido para mostrar que funciona.
De qualquer forma, para o que o micro está a fazer, não há nada a correr no main e o timer não para, seja onde estiver. Por isso o resultado, neste caso, ia dar os mesmos tempos, quer da minha forma quer da tua, acho eu... mas tu é que és o mestre :D.


PS: Estava aqui a tentar ver melhor, "FLAG-TMR0" deveria ser "FLAG_TMR0"?
Se não for,  não consigo entender o objectivo. Se puderes, depois dá uma explicação ;)


Abraço.


Qual mestre LOL.... mestres somos todos uns dos outros ;)

FLAG-TMR0 eh apenas um pseudo nome.

Algo como isto talvez, quick examplenao formatado nem outras coisas:

Código: [Seleccione]
typedef struct
{
    unsigned char   byState;

    unsigned        bTimerUsartRX:1;
    unsigned        bTimerComms:1;
    unsigned        bTimerAlarm:1;

}_TIMERS;

_TIMERS                 g_TIMERS;






void interrupt interrupcao(void)
{
    if ((TMR2IF) && (TMR2IE))
    {
        TMR2IF = 0;

        // Da indicacao q o timer rolou
        g_TIMERS.bTimerComms = 1;
    }

}


void interrupt interrupcao(void)
{

    if ((TMR2IF) && (TMR2IE))
    {
        TMR2IF = 0;

        // Da indicacao ah maquina de estados dos Timers do proximo passo
        g_TIMERS.byState = ST_Timers_TICK;
    }


}





void main (void)
{
...

if (g_TIMERS.bTimerComms)
{
// executar tarefa
}
}

Offline Electropepper

  • Mini Robot
  • *
  • Mensagens: 116
    • Electropepper
Re: Routina de 1ms com o tmr0
« Responder #29 em: 03 de Novembro de 2014, 10:04 »
Ok pessoal, já deu para tirar umas conclusões.
Usar a interrupção com apenas uma flag(state machine) a dar indicação que o timer rolou.
Ter em conta a chamada e saida para a função de delay assim como fazer o load do tmr0 com o respectivo valor.
Mais logo quando chegar a casa já esperimento isto outa vez.
E tenho de ver se arranjo um oscilóscpio para tirar as teimas.