Ir ao conteúdo
  • Cadastre-se

Funções e rotinas com mikroc


Posts recomendados

Sou novo por aqui e resolvi registrar pois sempre encontro ajuda em minhas pesquisas na net. Estou pretendendo fazer o controle de velocidade de uma ventoinha através da leitura de um sensor de temperatura (LM35). Alem do controle pretendo acionar alguns ledes conforme o valor da temperatura e também mostrar em um display o valor da temperatura e do duty cicle - PWM. Achei na internet um programa destes que pretendo adaptar e fazer o meu, porém fazendo alguns testes utilizando o mikroc e proteus ainda não deu certo. Embora o programa compile sem algum erro quando simulo no proteus não funciona nada. O programa é mais ou menos assim:

 

Conexões do lcd...

declaração de variáveis...

void main ()

{

informação das portas...

rotina1 ();

rotina2 ();

laço infinito

{

rotina3 ();

rotina4 ();

}}

 

void rotina1 ()

{

programa da rotina1...

}

void rotina2 ()

{

programa da rotina1....

}

demais rotinas....

 

Tudo ok. Compila tudo certinho mas não funciona no proteus. Uso o mikroc 5.61

Se alguém puder ajudar.

Link para o comentário
Compartilhar em outros sites

Sou novo por aqui e resolvi registrar pois sempre encontro ajuda em minhas pesquisas na net. Estou pretendendo fazer o controle de velocidade de uma ventoinha através da leitura de um sensor de temperatura (LM35). Alem do controle pretendo acionar alguns ledes conforme o valor da temperatura e também mostrar em um display o valor da temperatura e do duty cicle - PWM. Achei na internet um programa destes que pretendo adaptar e fazer o meu, porém fazendo alguns testes utilizando o mikroc e proteus ainda não deu certo. Embora o programa compile sem algum erro quando simulo no proteus não funciona nada. O programa é mais ou menos assim:

 

Conexões do lcd...

declaração de variáveis...

void main ()

{

informação das portas...

rotina1 ();

rotina2 ();

laço infinito

{

rotina3 ();

rotina4 ();

}}

 

void rotina1 ()

{

programa da rotina1...

}

void rotina2 ()

{

programa da rotina1....

}

demais rotinas....

 

Tudo ok. Compila tudo certinho mas não funciona no proteus. Uso o mikroc 5.61

Se alguém puder ajudar.

Pensei encontrar apoio mais rápido...continuo no aguardo...

Link para o comentário
Compartilhar em outros sites

"A qualidade da resposta é diretamente proporcional a qualidade da pergunta feita."

@EJO,

Você começou bem descrevendo o seu problema e o que queres, mas ainda falta informação, apenas um fluxograma não irá ajudar na resolução do seu problema.

Como ja citado, coloque o código que você pegou da internet e adaptou a sua aplicação, juntamente com o esquema elétrico do que foi implementado no Proteus, vale lembrar que no mundo dos microcontroladores, nem tudo é problema de software, existe hardware ai no meio que se mal operado não responde corretamete :)

Ficamos no aguardo das informações para lhe ajudar melhor.

Abs.

Felipe

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Amigo, não entendi bem qual é a sua duvida...  Mas de cara lhe digo que a estrutura do seu "Fluxograma" esta errado.

  É uma regra do MikroC e se não me engano também é uma regra  do padrão ANSI que a funções devem ficar antes do main, se forem colocadas depois ​é necessário declara-las antes do main, vou dar um exemplo de estrutura correto:

void funcao 1 (){...}main(){...} 

 dependendo do quantas funções que você utiliza pode atrapalhar a interpretação do programa coloca-las antes do main, neste caso pode se coloca-las depois do main utilizando a seguinte estrutura:

void funcao1() //aqui você só declara a funçãomain(){...}void funcao1() //aqui você declara a função e escreve o código{...} 

  Se você não declara a função antes do main o compilador não a reconhece e na hora da compilação diz que a função não foi encontrada, pelo menos na versão do MikroC que eu uso. Como você disse que o programa esta compilando, não sei se realmente seu problema é na estrutura do código, mas com as informações que você deu é o máximo que posso ajuda-lo.

Outra coisa: É feio cobrar os outros por algo que eles não tem obrigação...hehe.... Fica a dica, nos ajude para podermos te ajudar também.

 

  Espero ter lhe ajudado de alguma maneira.

Grato Luiz Gustavo. 

Link para o comentário
Compartilhar em outros sites

Senhores, vamos com calma...

Não penso que ficou ruim o meu primeiro questionamento (Felipe_Eletronic), apenas iniciei uma discussão que é o objetivo do fórum. Com indagações e respostas chegar a conclusão do problema citado/proposto. Também não estou cobrando nada de ninguém (LuizGBarrio), apenas fiz o comentário pois tenho interesse em resolver meu problema e como disse vi essa possibilidade aqui no fórum em função de outras pesquisas que fiz. Enfim, vamos com calma...

Como solicitado para darmos prosseguimento segue o código que estou trabalhando e simulando no proteus para depois montar na prática. Estou no serviço e não tenho o esquema do proteus nem o código com as últimas alterações mas não está muito diferente deste aqui não:

 

void pre_main();
void test_led_fan();
void read_lm35();
void led_control();
void pwm();
 
// Conexões LCD 2x16
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// Final Conexões LCD 2x16
 
//Declaração de variáveis globais
unsigned int temp;
 
void main()
{
//função iniciação
pre_main();
//função teste led e fan
test_led_fan();
 
while(1)
{
//leitura LM35
read_lm35();
//controla led's perante temperatura
led_control();
//Velocidade fan
pwm();
}
}
 
void pre_main()
{
//Declaração de info das portas
 
adcon1 = 0b00000100;
trisa = 0XFF; // portA entrada  (trisa = 1)
trisb = 0; // portB saída  (trisb = 0x00)
trisc = 0; // portC saída
trisd = 0; // portD saída
PORTD = 0; // portC nível lógico 0
//Iniciar PWM
PWM1_Init(1500);
//PWM Start
pwm1_start();
PWM1_set_Duty(0);
//Iniciar adc
adc_init();
//Iniciar Lcd
Lcd_Init();
//Iniciar Uart1
UART1_Init(9600);
Lcd_Cmd(_Lcd_CLEAR);
Lcd_Cmd(_Lcd_CURSOR_OFF);
}
void test_led_fan()
{
int j=0;
Lcd_Out(1, 1, "Aguarde: Teste");
Lcd_Out(2, 2, "Led's e Fan");
UART1_Write_text("Aguarde: TESTE\r");
UART1_Write_text("Led's e Fan\r");
do{
portd.f0=1; //verde
portd.f1=1; //amarelo
portd.f2=1; //2x vermelho
delay_ms(200);
portd.f0=0;
portd.f1=0;
portd.f2=0;
delay_ms(200);
j++;
pwm1_set_duty(255);
delay_ms(200);
pwm1_set_duty(0);
}
while(j!=2);
Lcd_Cmd(_Lcd_CLEAR);
Lcd_Out(1, 1, "Aguarde");
Lcd_Out(2, 2, "Led's e Fan OK");
UART1_Write_text("Led's e Fan OK\r");
delay_ms(200);
Lcd_Cmd(_Lcd_CLEAR);
}
void read_lm35()
{
char txt[15];
const unsigned short VREF = 5;
 
unsigned int adc_rd = 0;
adc_rd = ADC_Get_Sample(0);
temp = (adc_rd * VREF)/(1000*240);
//temp = ((unsigned long)adc_rd * VREF * 100)/1024;
floatToStr(temp, txt); //com intToStr não funciona
txt[4] =0;
//
UART1_Write_text(txt);
UART1_Write_text("\r");
Lcd_Out(1, 1, "Temp || Potencia");
Lcd_Chr(2, 5, 223);
Lcd_Chr(2,6,'C');
Lcd_Out(2, 1, txt);
delay_ms(10);
}
void led_control()
{
//indicação dos led's perante temperatura
if (temp <50)
{
portd.f0=1;
portd.f1=0;
}
else if (temp >51 && temp <69)
{
portd.f0=1;
portd.f1=1;
portd.f2=0;
}
else if (temp >70)
{
portd.f0=1;
portd.f1=1;
portd.f2=1;
}
}
void pwm()
{
int i=0;
if(temp > 70)
i=255;
else
{
i=temp*3;
}
PWM1_set_Duty(i);
}
Link para o comentário
Compartilhar em outros sites

@EJO, sem desviar muito o foco da discussão,

 

 

 

Não penso que ficou ruim o meu primeiro questionamento

Não disse que ele ficou ruim, mas a qualidade da informação realmente não ficou boa, não adianta expor um problema sem expor o cenário do problema.

 

 

 

Também não estou cobrando nada de ninguém

Releia o post #2 dessa discussão, mas como se fosse você alguém que quisesse ajudar.

Agora vamos ao seu problema, como disse antes nem tudo em sistemas microcontrolados é software, existem outros pontos que devem ser observados por isso pedi o esquema elétrico do que estás a fazer. Apesar de tudo ainda continuamos no escuro para poder lhe ajudar. 

Aqui vão algumas sugestões populares:

- Alimentação do microcontrolador;
- Cheque a fonte de clock, se for interno configure no software, mas se for externo, coloque o cristal ligado a ele no esquema elétrico;

- Observe se o canal analógico que estás a medir é correspondente ao que o LM35 está ligado ao PIC;
- Cheque no seu PWM, se habilitou antes de tudo o timer2, esse timer é usado como base de tempo para a geração do PWM;
 

- Respeite os tempos de inicialização e operação do LCD (tipico entre 1 e 10ms para cada comando);


Ficamos no aguardo do esquema elétrico e de preferência o código completo que estas a usar para também testarmos em nossa máquina.

:)

Link para o comentário
Compartilhar em outros sites

  • mês depois...

Olá, a todos, pessoal estou desesperado, preciso da ajuda de alguém que seja fera em MikroC, pois estou com um problemão, e nem sei por onde achar a solução: escrevi um programa compilei sem erros, gravei , funcionando tudo ok, dai acrescentei uma linha besta como "delay_ms(100);" , dai compilei sem erros, porém o pic começou a resetar sozinho direto, dai descobri que qualquer linha de codigo a mais causava o mesmo problema, depois de uma semana sofrendo descobri  que aumentando o nivel de otimização de 4 para 5 parou de resetar com a instrução do delay_ms(100); , porém ainda sim , quando acrescento mais codigo o problema volta a ocorrer,

já revisei todo o meu código, e não achei nenhum problema, alguém tem alguma ideia do que possa ser ??

Grato..

 

Link para o comentário
Compartilhar em outros sites

Olá, a todos, pessoal estou desesperado, preciso da ajuda de alguém que seja fera em MikroC, pois estou com um problemão, e nem sei por onde achar a solução: escrevi um programa compilei sem erros, gravei , funcionando tudo ok, dai acrescentei uma linha besta como "delay_ms(100);" , dai compilei sem erros, porém o pic começou a resetar sozinho direto, dai descobri que qualquer linha de codigo a mais causava o mesmo problema, depois de uma semana sofrendo descobri  que aumentando o nivel de otimização de 4 para 5 parou de resetar com a instrução do delay_ms(100); , porém ainda sim , quando acrescento mais codigo o problema volta a ocorrer,

já revisei todo o meu código, e não achei nenhum problema, alguém tem alguma ideia do que possa ser ??

Grato..

 

  Que pic esta usando?? 16f ou 18f? Qual o tamanho do código?

Se for o 16F, tem um problema com a paginação da memoria RAM, pois o MikroC para a serie 16F não controla o Bit IRP (do registrador STATUS), que basicamente seleciona com qual dos bancos você esta trabalhando (Na verdade serve para controle de acesso indireto a memoria, se tiver duvida, da uma olhadinha no Datasheet), quando uma variável fica foram do range do banco de memoria, para declarar-la e acessar-la é necessário comutar o Bit de IRP manualmente no programa, o MikroC não vai te indicar quando fazer isso, apenas te dá a mensagem "irp bit must be set manually for indirect access to variable" da uma olhada no terminal e vê se essa mensagem não apareceu.

 Mas o mais provável é que seja o estouro da pilha (tem um Fuse que segura o PIC no Reset quando ocorre o bem dito Stack Overflow), se for isso que esta acontecendo com você se prepare pois vai ter de refazer o código, de maneira mais leve. A grosso modo, podemos dizer que isso acontece porque o Stack armazena os endereços das sub-rotinas (chamadas de função, etc.) então quanto mais goto's e mais chamadas de função (tipo o Delay_Ms()) mais o Stack fica cheio, então chega uma hora que não tem mais espaço no buffer gerando esse problema ai! Se o fuse de Reset por Stack Overflow do Pic estiver acionado, o PIC reinicia se não ele simplesmente trava!!

  Me lembro que abandonei um programa de umas 1500 linhas que tava fazendo por conta desse problema, invés de refazer "direito" o programa (Usando uma rotina de delay única e reescrevendo rotinas ao invés de usar múltiplas chamadas de função por exemplo), então eu simplesmente copiei e colei no MikroC para AVR e compilei para o ATmega328p (fazendo a devida adaptação e configuração dos registradores) e funcionou!!! Mas não recomendo a ninguém que seja relaxado que nem eu, pois não é assim que se aprende.... hehe

 Se tiver alguma duvida é só perguntar...

 

  Espero ter ajudado.

Grato Luiz Gustavo.

Link para o comentário
Compartilhar em outros sites

@LuizGBarrio ,, ajudou muito, meu programa esta ocupando após a compilação cerca de 25% da rom , provavélmente no fim do primeiro banco, o meu código não é grande , mas não tenho muita experiência em C, estou usando o PIC 16F887, vou copiar meu código abaixo para você ver que não é muito grande (pode até ser mau escrito KKK): , você saberia me dizer se esse problema ocorre somento com os  P16 , se eu mudar pro PIC18F452 vou ter o mesmo problema ???, e se eu tentar mudar de compilador ???, qual outro você recomendaria ???

Um Abraço,

Grato

 

 

// Variaveis Rotary Encoder ####################################################
static unsigned int QUAD1A, QUAD1A_OLD, QUAD1A_NEW, QUAD1B, QUAD1B_OLD, QUAD1B_NEW, QUAD1C;
signed int count;
unsigned char flag; PortBreset;
// Variaveis Interrupção UART ##################################################
static short  rxflag=0 ;
char rxchar;        // Variable for storing the data from UART and array counter
unsigned char rxarray[20];              // array to store the received charaters
static unsigned char command[6]             ;
static short l                              ;
int res                                     ;
void interrupt()   {
//#### Rotary encoder INTERRUPT ###############################################
 
   if(INTCON.RBIF)
   PortBreset = PORTB;  //dummy read of PORTB to reset the mismatch condition
 
    { //if PortB change interrupt
 
      QUAD1A = PORTB.F1;             //
      QUAD1B = PORTB.F2;             //
      QUAD1C = PORTB.F0;
      
      QUAD1A_NEW = QUAD1A;
      QUAD1B_NEW = QUAD1B;
 
       if (QUAD1A_NEW + QUAD1B_NEW == 2) flag = 1;
 
       if ((flag == 1) & (QUAD1A_NEW + QUAD1B_NEW == 1)) {
              QUAD1A_OLD = QUAD1A_NEW;
              QUAD1B_OLD = QUAD1B_NEW;
              flag = 2;
       }
       if ((flag == 2) & (QUAD1A_NEW + QUAD1B_NEW == 0)) {
              if (QUAD1B_OLD == 1) {count++; flag = 3;}
              if (QUAD1A_OLD == 1) {count--; flag = 3;}
       }
 
 
 
 //###### End Encoder ##########################################################
    }
    INTCON.RBIF = 0;     // clear RB flag
    INTCON.RBIE = 1;     // enable on change interrupts
 
//### END Rotary Encoder routine################################################
 
  //##### UART Interrupt routine ###############################################
 
  if (PIR1.RCIF==1) {                         // test the interrupt for uart rx
  PIE1.RCIE = 0;                              //disable interrupt.
    rxchar = Uart1_Read();
    rxarray[l] = rxchar;
    if (l >= 7)  {
        l=0;
        rxflag=0;
        goto ret;
        } else
     if (rxarray[l] == 0x0d) {
      l++  ;
      rxarray[l]=00;
      rxflag = 1;
 
      res=strcpy(command,rxarray);
 
      goto Ret ;
 
      }
      l++;
      ret:          ;      // antes de sair limpar flag da int e re habilitar int
      PIE1.RCIE = 1;       //enable interrupt.
  }
  //### End of UART INTERRUPT ################################################
} //### END OF INTERRUPT ROUTINES ##############################################
// Lcd pinout settings
sbit LCD_RS at RD0_bit;    //RC4
sbit LCD_RW at RD1_bit;    //RC5 Not defined
sbit LCD_EN at RD2_bit;    //RC6
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
 
// Pin direction
sbit LCD_RS_Direction at TRISD0_bit;  //TRISC4_bit
sbit LCD_RW_Direction at TRISD1_bit;  //TRISC5_bit
sbit LCD_EN_Direction at TRISD2_bit;  //TRISC6_bit
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;
unsigned char  caller_id[] = "PU2TWU"           ;
 
//******************************************************************************
unsigned char  comprimento_caller_id            ;
unsigned char  x_position                       ;
unsigned int short lcd_colum=20                 ;
void lcd_print_caller_id()
{
                     comprimento_caller_id = strlen(caller_id)      ;
                     x_position=lcd_colum-comprimento_caller_id     ;
                     x_position=x_position/2                        ;
                     x_position++                                   ;
Lcd_Out(1,x_position,caller_id)                                     ;
}
 
//##############################################################################
unsigned long  Vin                              ;
unsigned int   grau                             ;
unsigned long   temp                             ;
static unsigned int   destination               ;
unsigned int   _degree=0 , _go ,x ,n            ;
static   int   direction                        ;
 
unsigned char  wsgrau[4]                        ;
unsigned char  wsencoder[4]                     ;
unsigned char  wsdestination[4]                 ;
unsigned char  strgrau[6]                       ;
unsigned char  strdestination[6]                ;
unsigned char  strencoder[6]                    ;
unsigned char  offset={0x01}                    ;    // mudar para posição fixa
unsigned char  cpygrau[4]                       ;
unsigned char  s_degree[4]                      ;
unsigned char  grau_symbol[2]={0xdf,0x00}       ;
unsigned short result                           ;
unsigned short i=0,j=0,k,zz=0                   ;
static unsigned char degree_len                 ;
// variaveis para debug
 
//******************************************************************************
void main()
{
WPUB=0xff                                     ;  //OPTION_REG.B7 = 1 ;       // pullups portb enable
LCD_RW =0 ;
TRISA=0x0f ;         // ajustar conforme perifericos
TRISB=0x07 ;
TRISC=0xf9 ;
TRISD=0 ;
TRISE=0xff;
PORTA=0     ;
CM1CON0 = 0x00 ;
CM2CON0 = 0x00 ;
ADCON0 = 0x81;
ADCON1 = 0xb0;                                   ;
ANSEL = 0x0d ;
ANSELH = 0x00;
IOCB = 0x07 ;
INTCON.RBIF = 0;     // Clear RB interrupt flag prior to enable
INTCON.RBIE = 1;     // enable on change interrupts
INTCON.GIE  = 1;     // enable Global interrupts
INTCON.PEIE = 1;
PIE1.RCIE = 1;       //enable interrupt.
PORTC=0;
PORTB=0;
destination = 180                                ;
 
UART1_Init(9600)                                 ;
Lcd_Init()                                       ;
 
Lcd_Cmd(_LCD_CURSOR_OFF)                         ;
Lcd_Cmd(_LCD_CLEAR)                              ;
lcd_print_caller_id()                            ;
delay_ms(500)                                    ;
count  =    180                                   ;
 
 
while(1)
{
 
Vin=Adc_Read(0)                                  ;                                           ;
//***********************************************
temp=((Vin*360)/ 1023)                           ;
grau=temp                                        ;
 
//******************************************************************************
 
WordToStr(grau,strgrau)                          ;
           j=3                                              ;
           for(i=5;i>=2;i--)
           {
           wsgrau[j]=strgrau                     ;
           j--                                      ;
           }
           result=strlen(wsgrau);
i=0;
   while(i<=result)
   {
   if (wsgrau==0x20) {
   wsgrau=0x30    ;
   }
   i++ ;
   }
 
Lcd_Out(2, 1, "POS:")                              ;
x=0    ;
      while(x<=3) {
      cpygrau[x]=wsgrau[x];
      x++;
      }
 
Lcd_Out(2,offset+4,wsgrau)                       ;
Lcd_Out(2,offset+7,grau_symbol)                  ;
 
//Delay_ms(300)                                    ;
 
    if (count > 360) {
        count = 360                                ;
    }
    if (count < 0) {
        count = 0;   // SET MAX COUNT AND MIN COUNT
    }
 
WordToStr(destination,strdestination)             ;
Lcd_out(3,1,"Dest.:")                            ;
           j=3                                              ;
           for(i=5;i>=2;i--)
           {
           wsdestination[j]=strdestination               ;
           j--                                              ;
           }
lcd_out(3,7,wsdestination)                              ;
Lcd_Out(3,10,grau_symbol)                               ;
Lcd_Out(4, 1,"Local:")                                    ;
WordToStr(count,strencoder)                              ;
           j=3                                                     ;
           for(i=5;i>=2;i--)
           {
           wsencoder[j]=strencoder                       ;
           j--                                              ;
           }
 
 Lcd_Out(4, 7, wsencoder)                                ;
 Lcd_Out(4,10,grau_symbol)                               ;
 
//   ENABLE_INTERRUPTS(global);
//   ENABLE_INTERRUPTS(INT_TIMER0);
//   SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_32);
 
 
 
if (rxflag==1) {
switch (command[0]) {
  case 'C': Uart1_Write_Text("AZ=") ;
           if (degree_len==1) {
           res = strcat(cpygrau, "00");
           }
           if (degree_len==2) {
           res = strcat(cpygrau, "0");
           }
           Uart1_Write_Text(cpygrau) ;
           Uart1_Write(0x0d) ;
           Uart1_Write(0x0a) ;
           break ;
    case 'M': j=0 ; i=1 ;
    while(i<=3) {
    s_degree[j]=command ;
    i++ ;
    j++ ;
    }
    s_degree[3]=0x00 ;
    n=0 ;
    for(i=0;s_degree>='0' && s_degree <='9';i++)
    n=10*n+(s_degree - '0') ;
 destination=n ;
    break;
 
  default: break ;
}
rxflag=0;
l=0;
command[0]=0x00;
command[1]=0x00;
command[2]=0x00;
command[3]=0x00;
command[4]=0x00;
PIE1.RCIE = 1;       //enable interrupt.
} // if rx_flag
 
if(QUAD1C==0) { destination=count ; }
 
direction=grau;
direction=direction - destination ;
 
if((direction<0) && (direction <-4)) { PORTC.F2=1; PORTC.F1=0; }
if((direction>0) && (direction > 4)) { PORTC.F1=1; PORTC.F2=0; }
if(direction==0) {PORTC.F1=0 ;PORTC.F2=0;}
 
// delay_ms(100); //   <<<<<<<<<<<<<<<<<<<<<<<<<<-----------------   detectei o problema quando quis acrescentar este delay aqui...
 
} // end while
} // Main
Link para o comentário
Compartilhar em outros sites

Fala ai..... Paulão , beleza, com esta voce ????, é que saúdades do tk-82C, realmente , bons tempos aqueles em que não tinhamoa windows prá dar pau KKKKKK,

manda um beijão prá Sandrinha, fala prá ela que qualquer hora eu ligo, é rapaz to quase me arrependendo de ter largado o asm viu...., como aqui não se ode meter a lenha nos fabricantes de compiladores, vou até ficar quieto !!!, Tô aguardando a resposta do Gustavo , se o problema é só com o PIC16 ou se eu mudar prô PIC18 vou ter o mesmo problema , ou se mudo de compilador,, já tentei usar outro compilador o CCS, o XC8 , mais cada um a sintax de acesso aos sfr são diferentes , a documentação é muito longa e não tão bem organizada prá quem tá começando no C como eu..., pelo menos esse é meu primeiro programinha em C, e não pisca só LED rsrsrsrsrrsrsr, vamos ver no que vai dar , um grande abraço..

Link para o comentário
Compartilhar em outros sites

@Gilberto Gozzi,

Opa eu já avisei ela e ela ficou toda contente, veja se aparece viu sumido !!!!

Olha, voce poderia fazer o mesmo que eu, usar os Avrs, e programar em Basic do Bascom que permite intercalar programas em Assembler !

Estou fazendo coisas que voce não acedita... Quando preciso de muita performance, vai em Asm, que conversa direitinho com o Basic, ambas as linguagens compartilham as variáveis uma da outra !

Ve se passa um dia aqui para ver e tenho certeza que voce vai ter um novo alento ! Processadores 4 vezes mais rápidos, muito mais memória Ram e Flash por um preço baixo, e ainda pode usar os Arduínos como plataforma de montagem !

Vai se lembrar dos bons tempos do Basic do Sinclair, e das famosas rotinas em Assembler residentes !!!! Quem sabe até escrever um novo T-Rex !!!!

Aguarde que o pessoal vai te ajudar com o MikroC, infelizmente eu não consigo nem fazer acender um Led em C.....

Um abraço !

Paulo

Link para o comentário
Compartilhar em outros sites

Gilberto Gozzi

 

 O problema do Bit de IRP acontece apenas na serie 16F. Mas não tenho certeza se essa é a causa, preciso de mais tempo para verificar seu código mais minuciosamente. Se tiver pressa em colocar o projeto em funcionamento, pode usar um 18f452 que dá e sobra...hehe.

 O MikroC é um bom compilador, mas assim como qualquer outro compilador ele tem certas falhas, conhecendo bem elas dá para compensar certos erros, já vi gente que declara as variáveis como absolute, assim o compilador te dá a opção de indicar o endereço da memoria onde aloca-la, assim dá para burlar o problema do mikroC que é principalmente não alocar a memoria de maneira linear, dá vez que tive problemas com o IRP o bufer do primeiro banco não tinha sido preenchido totalmente, mas não sei porque motivo o MikroC jogava meia duzia de variáveis para o segundo banco de memoria RAM.

 Quanto ao compilador, não sei bem o que te dizer, sempre usei o MikroC e raramente tinha problemas, o CCS é muito bom até melhor que o MikroC em alguns aspectos, top mesmo é o Hitech-C, mas ele é padrão ANSI (full ANSI) e é pobre em rotinas e bibliotecas prontas (que justamente é a vantagem do MikroC), mas sempre caímos naquela de "cada um tem seus defeitos e qualidades".

 O único programa que não fiz no MikroC foi o que eu citei no post acima, esse que me fez largar os PIC's e partir para os AVR's...

Bate aqui @aphawk  º/

hehe....

 Uma ferramenta que gosto no MikroC fica na aba View>Statistcs , da uma olhada lá e vera com seu programa se organiza dentro da memoria do PIC, os endereços e tamanhos das funções e variáveis, etc.  Talvez até descubra o que esta errado, hehe, vou dar uma conferida no seu código mais de perto, talvez amanha ou depois, se não se importar de esperar, talvez eu ache uma maneira de roda-lo no 16f887 mesmo, assim te poupa um 18f452 que poderás usar em algo mais complexo....hehe

 

  Espero ter ajudado.

Grato Luiz Gustavo. 

Link para o comentário
Compartilhar em outros sites

Obrigado Luiz Gustavo, você me ajudou bastante, fico te devendo uma,,,vou adaptar pro pic 18F452 e recompilar , vamos ver no que da !!!

 

Grande abraço


Paulão, qualquer hora eu ligo e apareço, se você se lembra quando nos encontramos pela ultima vez , você me deu uma plaquinha do programador pra avr, porém não montei pois você ficou de me mandar o esquema a lista de materiais e o principal o "Firmware" prá eun gravar no avr !!!  rsrrsrsrsrsr, eu ainda sou muito relutante tanto em programar  em basic com com os avrs pois se me lembro bem são uma evolução da familia MSC51 da qual apesar de ainda ter alguns 8051,8749 etc aqui em casa (gosto de guardar velharias) , não tenho boas recordações daquele assembler maldito (KKKKK), aqui ainda tenho também alguns Z80 CPU, Z80 PIO , Z80 CTC, Z80 CIO, Z80 SIO-II, acho que vou acabar por montar um hardware com eles e voltar ao velho e bom : LD a,030

                                                                                                                         LD(HL),a

                                                                                                                         EXX HL,DE

 

 

heheh, lembra disso ???, 

um abraço

Link para o comentário
Compartilhar em outros sites

@Gilberto Gozzi,

 

Opa, lembro sim.... mas olha, depois que voce entende o motivo de existirem tantos registradores ( 32 ) com funcionalidades diferentes, fica bem mais fácil !  Tem instruções bem poderosas que fazem coisas em apenas 1 ou dois ciclos de clock, a maioria é de 1 ciclo, porisso que na prática é quase 4 vezes mais rápido que os Pics no mesmo clock.

E esses Pic18F que trabalham a 48 Mhz tem performance equivalente a um AVR a 12 Mhz.

 

Olha que legal :

 

LDI R16,$00  -  carrega r16 com 0

ST X,R16       -  armazena o conteudo de r16 no endereço dado no par de registradores R26:R27

 

E esta aqui :

 

ST X+,R16    -   Idem, porém após já incrementa R26:R27 ! 

 

Lembrou teu código acima ???? E a ultima instrução então, fazer isso em apenas 2 ciclos de clock ????

 

Passa em casa e já pega o AVR gravado....

 

Paulo

Link para o comentário
Compartilhar em outros sites

 o MikroC para a serie 16F não controla o Bit IRP (do registrador STATUS) 

 

ahhh não cara, dessa eu não sabia.... não posso acreditar que o microC tem uma limitação dessa D:

eu nunca percebi isso, quando comecei a fazer códigos grandes comecei a usar a família 18F....

 

 

abrçs

Link para o comentário
Compartilhar em outros sites

mister nintendo

 

 É verdade, eu também não sabia há um tempo atrás, na verdade só uma vez tive problema com isso, mas como você disse, o projeto vai ficando maior a gente vai aumentando o PIC também, né? hehe...

 O problema é que é uma limitação maior do que parece, pois como eu disse antes a variáveis não são alocadas 100% linearmente memoria, assim também não tem como saber o que o MikroC ta jogando para outro banco, então só resta declarar tudo como Absolute e informar o endereço onde começa as declarações das variáveis....

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Por curiosidade, Paulo, já fez tal "overclock" e se fez, funcionou legal?

Já ouvi falar muito disto, mas nunca tentei. Preciso pra  dobrar a frequência de varredura de uma matriz de led (como deve ter percebido na assinatura é o que faço).

Como não utilizo a EEPROMs e nem os ADCs , que poderiam ser afetados, creio que deve dar certo.

Pena que ele não tem PLL interno como o ATTiny45, que com 8MHz do oscilador interno pode-se obter 64MHz para os periféricos apenas mudando os fusebits.

Link para o comentário
Compartilhar em outros sites

@,

Sim comprei um oscilador prontinho de 32 Mhz, que parece um CI de 14 pinos. Foi só ligar e o bicho rodou direitinho. Testei com um Atmega328PA .

Fiz o teste com Adc, mas controlei o clock para ele na mão, e rodou direitinho. Não fiz o teste na Eeprom. Uma coisa foi interessante, o consumo do chip triplicou, o que mostra que realmente as perdas internas cresceram. Minha opinião é a que o ADC deve dar pau se deixar rodar no máximo, pois o capacitor interno não vai ter o tempo projetado para se carregar.

Mas rodou diretinho , liguei e desliguei umas 20 vezes e foi tudo normal.

Se existisse esse PLL..... Mas com o que tem já está muito bom !

Sim, eu vi tua assinatura... Creio que de 20 para 32 Mhz já dá para brincar bem, e se você usa o Bascom, pode implementar as partes críticas em Asm, especialmente as rotinas de interrupção.

Paulo

Link para o comentário
Compartilhar em outros sites

 

 

Sim comprei um oscilador prontinho de 32 Mhz, que parece um CI de 14 pinos. Foi só ligar e o bicho rodou direitinho. Testei com um Atmega328PA .

Overclock no AVR é diversão gratuita, deem uma procurada no google de um cidadão que fez overclock de um Mega desses dentro de um tanque com nitrogenio liquido... 64MHz (e mais!) de pura diversão.

 

 

 

Minha opinião é a que o ADC deve dar pau se deixar rodar no máximo, pois o capacitor interno não vai ter o tempo projetado para se carregar.

Pelo datasheet, e olhando o modelo interno da criança, fique tranquilo, o capacitor interno é de 14 pf, fazendo porcamente a conta do tempo necessário para  a carga do capacitor de amostragem (total cerca de 99%) da 1.67MHZ.

 

 

 

Sim, eu vi tua assinatura... Creio que de 20 para 32 Mhz já dá para brincar bem, e se você usa o Bascom, pode implementar as partes críticas em Asm, especialmente as rotinas de interrupção.

Paulo, de um tempo pra cá você falando tanto de Assembly, quem te viu quem te ve :D

Abs.

Link para o comentário
Compartilhar em outros sites

  • 3 meses depois...

Gostaria de solicitar a ajuda de vocês com um codigo estou utilizando o mikroC e simulando no protheus. Qual seria minha ideia estou com um codigo para o controle de rotação PWM e RPM mais hoje para aumentar o a rotação eo Duty Cycle preciso de um potenciométrico  queria a ajuda de voce para melhorar esse codigo para determinar uma rotação o PIC executar esse controle caso alguma coisa trave o motor automaticamente o PIC aumenta o Duty Cycle .. E o PIC que estou usando é 18F4520..

 

Sengue o Codigo:

 

 

// VARIAVEIS GLOBAIS
unsigned char ucTexto[10];   // Matriz para armazenamento de texto.
unsigned char ucPorcentagem; // Armazena a porcentagem do PWM.
unsigned int iLeituraAD = 0; // Define variável para armazenamento da leitura AD.
unsigned int iReg_timer1;    // Armazena o RPM.
 
unsigned int pulsos = 0;
unsigned int setpoint();
  int y = 0; // Declaração de variável global
// CONFIGURAÇÃO DOS PINOS DO LCD.
sbit LCD_RS at RE2_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
 
// DIREÇÃO DOS PINOS.
sbit LCD_RS_Direction at TRISE2_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;
 
 
void interrupt(){
   if (INTCON.TMR0IF == 1){    // Se o flag de estouro do TIMER0 for igual a 1, então
      PORTB.RB0 = ~PORTB.RB0;  // Inverte o estado do PORTB.RB0.
       TMR0L = 0XDC;           // Carrega valores de contagem
       TMR0H = 0XB;            // Carrega valores de contagem
      INTCON.TMR0IF = 0;             // Seta T0IE, apaga flag de entouro do TIMER0
      iReg_timer1 = (TMR1L*600/8);    // Pega valor lido do timer1 e multiplica por 600 para saber rotação por minuto.
                                     // e divide por 7 pois a ventoinha para dar uma volta completa realiza 7 pulsos.
      TMR1L = 0;                     // Limpa contador.
   }
}
 
 void Erro(){
 
 
       }
 
void main(){
   TRISB = 0;                       
   TRISD = 0;                        
   TRISC.RC0 = 1;                   
   TRISC.RC2 = 0;                   
   TRISE = 0;                       
   PORTB = 0;                        
 
   // Configuração das interrupções
   INTCON.GIEH = 1;   // Habilita as interrupções e a interrupção de alta prioridade.
   INTCON.GIEL = 1;   // Habilita as interrupções e a interrupção de baixa prioridade
   RCON.IPEN = 1;     // Configura 2 niveis de interrupção.
 
   // Timer 0
   INTCON.TMR0IF = 0;
   INTCON2.TMR0IP = 1;
   INTCON.TMR0IE = 1;
 
   //temporização de 100 milisegundos
   T0CON = 0B10000101; 
   TMR0L = 0XDC;       
   TMR0H = 0XB;      
   INTCON.TMR0IF = 0;  
 
   // Timer 1 para modo contador de pulsos externos
   T1CON = 0B10000011;
   TMR1L = 0;         
   TMR1H = 0;          
   PIR1.TMR1IF = 0; 
 
   ADCON0 = 0b00000001;             .
   ADCON1 = 0b00001110;              
   ADCON2 = 0b10111110;             
   // Config. LCD no modo 4 bits
   Lcd_Init();                              
 
   Lcd_Cmd(_LCD_CLEAR);                      
   Lcd_Cmd(_LCD_CURSOR_OFF);                
   Lcd_Out(1, 1, "Duty Cycle:    %");            .
 
 
   PWM1_Init(5000);                  
   PWM1_Set_Duty(255);        
   PWM1_Start();                     
      // if (setpoint < 1000);
 
 
   
   while(1){   // Aqui Definimos Uma Condição Sempre Verdadeira Como Parametro, Portanto Todo O Bloco Será Repetido Indefinidamente.
      
      iLeituraAD= ADC_Read(0);         
      iLeituraAD=(iLeituraAD*0.24);     ]
      PWM1_Set_Duty(iLeituraAD);        
      iLeituraAD=(iLeituraAD*0.41);     
      WordToStr(iLeituraAD, ucTexto);   
      Lcd_Out(1,11,ucTexto);           
      WordToStr(iReg_timer1, ucTexto); 
      Lcd_Out(2,1,ucTexto);           
      Lcd_Out_CP(" RPM");             
      Delay_10us;
 
 
       
      }
 

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...