Microcontroladores pic ling c unicamp

915 visualizações

Publicada em

Slides de Aula sobre Microcontroladores PIC - Faculdade de Tecnologia, Unicamp, Limeira.

Publicada em: Engenharia
  • Seja o primeiro a comentar

Microcontroladores pic ling c unicamp

  1. 1. Microcontroladores PIC Linguagem CLinguagem C Prof. Francisco Fambrini Unicamp – Limeira - 2015
  2. 2. Livro recomendado para esta Aula
  3. 3. Disposição dos pinos PIC16F877
  4. 4. Estrutura básica interna de um micocontrolador
  5. 5. Estrutura de um programa em C
  6. 6. Resumo sobre declaração de variáveis e operadores
  7. 7. Algumas configurações de fuse bits
  8. 8. Tipos de Variáveis em C
  9. 9. Modificadores signed e unsigned
  10. 10. Variáveis Globais
  11. 11. Exercícios de fixação
  12. 12. Operadores em C
  13. 13. Operadores relacionais em C
  14. 14. Operadores Lógicos
  15. 15. Operadores de atribuição
  16. 16. Operadores bit a bit
  17. 17. Adicionando botões na entrada do microcontrolador
  18. 18. Lendo um botão em C
  19. 19. Nosso primeiro programa em C // BOTAO E PISCA-LED #include <16f877.h> #use delay (clock=4000000) #fuses XT, NOWDT,PUT,NOBROWNOUT,NOLVP, NOPROTECT main( ){ While(TRUE){ IF (! INPUT (PIN_B0 )) { OUTPUT_LOW(PIN_B7); DELAY_MS(300); OUTPUT_LOW(PIN_B7); DELAY_MS(300); } ELSE { OUTPUT_LOW(PIN_B7); } } }
  20. 20. Problema Fazer o Projeto, para o controle da Bomba d’água B1, sendo que o nível sempre estará entre S1 e S2 (sensores da bóia). Quando o nível atinge o sensor S1 o seu contato fecha ligando a bomba dágua para encher o tanque;Quando o nível atinge S2 a bomba deve ser desligada para evitar que a água transborde.
  21. 21. Esquema do hardware proposto
  22. 22. Questões
  23. 23. Exemplo 2 • Dado o circuito do slide anterior, proponha para este hardware um sequencial em firmware, capaz de acender os leds um de cada vez, sendo que apenas um led fica aceso a cada vez.
  24. 24. Quando o sensor S5 detecta a presença de uma pessoa a porta abrirá rapidamente até que o sensor S3 seja atingido, onde a velocidade diminui Quando chega a S4 o portão para, espera 15 segundos e a seguir, o portão fecha. Chegando a S2 a velocidade diminui e em S1 o portão para. Considera a velocidade lenta como uma saída VL e a rápida como VR. Faça o Projeto do hardware e o esquema elétrico.
  25. 25. Pressionando o botão S1 o guindaste vai para a esquerda até o fim de curso S5 onde pára, só o botão S3 faz ao guindaste retornar até a posição S6. O botão S2 envia o guindaste para a direita até S7 e para retornar aperta-se o botão S4 fazendo o guindaste retornar até S6.
  26. 26. Interrupções em C 1 - Dependem do Compilador. 2- Duas formas para o tratamento de interrupções no compilador PCHW da CCS: • Automática: O compilador gera todo o código do tratamento da interrupçãoO compilador gera todo o código do tratamento da interrupção (flags, configuração de registradores , contexto, etc.) A única tarefa do programador é a construção das funções de tratamento dos eventos individuais de cada interrupção. • Manual: O programador deverá se incumbir de tudo: verificar flags de interrupção, chamadas específicas para tratamento de cada evento, configuração dos registradores, salvar e recuperar contexto, etc.
  27. 27. O que são interrupções? Interrupções, como o nome sugere, interrompem a execução normal e pedem atenção urgente de CPU. Interrupções são situações que a CPU não pode prever quando vai acontecer, elas podem acontecer a qualquer momento, de modo que o CPU não pode esperar por elas. Assim, a CPU continua fazendo seu trabalho normal a menos que interrupção ocorra. Por exemplo, quando o USART (Hardware Comunicação Serial) receberá dados é desconhecida, pode receber dados a qualquer momento.desconhecida, pode receber dados a qualquer momento. Assim, a CPU continua a fazer o seu trabalho normal, que pode ser por exemplo ler a temperatura de um sensor LM35 e mostrar no LCD. A CPU continua a fazer o trabalho "normal", mas assim que a USART receber dados informa a CPU usando uma interrupção. A CPU salva seu estado atual (para que ele possa retornar a ele), e pula para a rotina de serviço de interrupção) ISR imediatamente. A Rotina ISR é geralmente muito pequena e rápida. Assim que a ISR termina, a CPU restaura seu estado que foi salvo e retoma do ponto onde ocorreu a interrupção.
  28. 28. Interrupções com tratamento Automático e Manual Interrupção Automática • Vantagens: Simplicidade • Desvantagens: Gera programas maiores. Gera tempo extra no tratamento das interrupções,ou seja, o tempo entre aocorrência do evento de interrupção propriamente dito e o tratamento da mesma. • Uso: Aplicações simples onde o tempo não é um fator crítico.• Uso: Aplicações simples onde o tempo não é um fator crítico. Interrupção Manual • Vantagens: Adequado quando a aplicação demanda precisão de contagem. • Desvantagens: Gera programas menores. Mais trabalho para o programador. (contexto, flags,registradores, etc.) • Uso: Aplicações de tempo real e/ou onde pequenos atrasos são indesejáveis. • Observação!! Demanda inclusão de código assembler (diretiva específica)
  29. 29. Periféricos que geram interrupção no PIC16F877 • Interrupção por overflow do Timer0; • Interrupção RB (mudança de estado das portas B); • Interrupção externa; • Interrupção de conversão analógico/digital; • Interrupção de transmissão de dados da porta serial (RS232); • Interrupção de recepção de dados da porta serial (RS232);• Interrupção de recepção de dados da porta serial (RS232); • Interrupção por overflow do Timer1; • Interrupção por comparação do Timer2; • Interrupção do módulo CCP1 e CCP2; • Interrupção de atividade da comunicação SPI ou I2C; • Interrupção de colisão de dados do barramento; • Interrupção de escrita da EEPROM; • Interrupção de evento do comparador.
  30. 30. INTCON: o registrador principal que controla as interrupções
  31. 31. Algumas interrupções que serão importantes para o Projeto Final
  32. 32. Hardware interno do microcontrolador
  33. 33. Exemplo: Configurar o TMR0 para que gere interrupções a cada 1 segundo. //Após 125 estouros do TMR0 (125 interrupções), teremos chegado ao tempo de 1 segundo (1Hz). #include <16F877A.h> #use delay ( clock=4000000 ) #fuses HS,NOWDT,PUT,NOLVP #int_timer0 void trata_tmr0 ( ) { static boolean LED; static int contador; set_timer0(131 + get_timer0()) ; contador++; if( contador == 125) {if( contador == 125) { contador = 0; LED = !LED; output_bit(pin_b0, LED); } } void main( ) { // configura o TMR0 para clock interno e prescaler dividindo por 64 setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_64); set_timer0 (131); // inicia o timer 0 em 131 // habilita interrupções enable_interrupts (global | int_timer0); while (true); // espera pela interrupção }
  34. 34. Usar interrupção de Timer para gerenciar máquinas de estado
  35. 35. Analise o código abaixo e diga o que ele faz #include <16F877.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock=20000000) BYTE blink = 0; #int_rb void button_isr() { delay_ms (20); //debounce if( !input(PIN_B4) && !blink ) blink = 1; else if( !input(PIN_B4) && blink ) blink = 0; } void main( ) { enable_interrupts(global); enable_interrupts(int_rb); ext_int_edge( H_TO_L ); do { if(blink){ output_high(PIN_D1); delay_ms(500); output_low(PIN_D1); delay_ms(500); } } while (TRUE); }
  36. 36. Usando o Conversor AD em C #include<16f877a.h> #Device ADC=8 #fuses HS,NOLVP,NOWDT,PUT #use delay(clock=20000000) #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7) void main( ) { int i, value, min, max; printf("Sampling:"); setup_adc_ports( RA0_ANALOG ); setup_adc( ADC_CLOCK_INTERNAL ); set_adc_channel( 0 ); do { // Toma 30 amostras do conversor AD aplicadas no pino A0 min = 255; // e mostra os valores mínimos e máximo dentre as 30 amostras max = 0; // valores tomados em intervalos de 100ms for(i = 0; i <= 30; ++i) { delay_ms(100); value = read_adc(); if(value < min) min = value; if(value > max) max = value; } printf("nrMin:%x MAX: %x", min, max); } while (TRUE); }
  37. 37. No arquivo cabeçalho 16F877A.h encontramos as constantes: • // Constants used in SETUP_ADC_PORTS() are: • #define NO_ANALOGS 7 // None • #define ALL_ANALOG 0 // A0 A1 A2 A3 A5 E0 E1 E2 Ref=Vdd • #define AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF 1 // A0 A1 A2 A5 E0 E1 E2 Ref=A3 • #define AN0_AN1_AN2_AN3_AN4 2 // A0 A1 A2 A3 A5 Ref=Vdd • #define AN0_AN1_AN2_AN4_VSS_VREF 3 // A0 A1 A2 A5 Ref=A3 • #define AN0_AN1_AN3 4 // A0 A1 A3 Ref=Vdd • #define AN0_AN1_VSS_VREF 5 // A0 A1 Ref=A3 • #define AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF 0x08 // A0 A1 A5 E0 E1 E2 Ref=A2,A3 • #define AN0_AN1_AN2_AN3_AN4_AN5 0x09 // A0 A1 A2 A3 A5 E0 Ref=Vdd • #define AN0_AN1_AN2_AN4_AN5_VSS_VREF 0x0A // A0 A1 A2 A5 E0 Ref=A3 • #define AN0_AN1_AN4_AN5_VREF_VREF 0x0B // A0 A1 A5 E0 Ref=A2,A3 • #define AN0_AN1_AN4_VREF_VREF 0x0C // A0 A1 A5 Ref=A2,A3 • #define AN0_AN1_VREF_VREF 0x0D // A0 A1 Ref=A2,A3• #define AN0_AN1_VREF_VREF 0x0D // A0 A1 Ref=A2,A3 • #define AN0 0x0E // A0 • #define AN0_VREF_VREF 0x0F // A0 Ref=A2,A3 • #define ANALOG_RA3_REF 0x1 //!old only provided for compatibility • #define A_ANALOG 0x2 //!old only provided for compatibility • #define A_ANALOG_RA3_REF 0x3 //!old only provided for compatibility • #define RA0_RA1_RA3_ANALOG 0x4 //!old only provided for compatibility • #define RA0_RA1_ANALOG_RA3_REF 0x5 //!old only provided for compatibility • #define ANALOG_RA3_RA2_REF 0x8 //!old only provided for compatibility • #define ANALOG_NOT_RE1_RE2 0x9 //!old only provided for compatibility • #define ANALOG_NOT_RE1_RE2_REF_RA3 0xA //!old only provided for compatibility • #define ANALOG_NOT_RE1_RE2_REF_RA3_RA2 0xB //!old only provided for compatibility • #define A_ANALOG_RA3_RA2_REF 0xC //!old only provided for compatibility • #define RA0_RA1_ANALOG_RA3_RA2_REF 0xD //!old only provided for compatibility • #define RA0_ANALOG 0xE //!old only provided for compatibility • #define RA0_ANALOG_RA3_RA2_REF 0xF //!old only provided for compatibility
  38. 38. SETUP_ADC( )
  39. 39. Set_adc( ) e read_adc( )
  40. 40. Quais são os problemas com esse projeto de hardware ?
  41. 41. Exemplo de configuração dos 2 canais de PWM #include <16F877.h> #fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP #use delay(clock = 4000000) main( ) { output_low(PIN_C1); // Set CCP2 output low output_low(PIN_C2); // Set CCP1 output low setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM setup_ccp2(CCP_PWM); // Configure CCP2 as a PWM setup_timer_2(T2_DIV_BY_16, 124, 1); // 500 Hz set_pwm1_duty(31); // 25% duty cycle on pin C2 set_pwm2_duty(62); // 50% duty cycle on pin C1 while(1); // Prevent PIC from going to sleep (Important !) }
  42. 42. Equações usadas para ajustar os valores do PWM no CCS value = Fosc / (Fpwm * 4 * T2DIV) - 1 setup_timer_2(T2_DIV_BY_X, value, 1); valor = (Desired_Duty_Cycle% * Fosc) / (Fpwm * 4 * T2DIV) set_pwm1_duty(valor);
  43. 43. Exercício A cada 2 segundos o microcontrolador deve adicionar à sua saída analógica 0,5 volt, até alcançar 5 volts. Isto será iniciado quando o operador pressionar o botão start, e quando for pressionado o botão stop a rampa deverá ser decrescente até o motor parar. Para este problema assuma que a saída analógica é a saida do PWM 1.
  44. 44. Memória de dados não voláteis: Eeprom Para escrever na EEPROM Write_eeprom ( end. , valor); Para ler o conteúdo de um determinado endereço:Para ler o conteúdo de um determinado endereço: x = read_eeprom (end.); Obs: valor deve ser um inteiro de 8 bits ! ( int8)
  45. 45. Memória de dados não voláteis: Eeprom - exemplo #include <16F877A.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock=20000000) #rom 0x2100 = { 7, 39 } // Diretiva #ROM inicializa a EEPROM #include <lcd2.c> void main( ) { int8 value, value1;int8 value, value1; lcd_init( ); value = read_eeprom (0x2100); value1= read_eeprom (0x2101); delay_ms(6); lcd_gotoxy(1,1); printf(lcd_putc," Prof. Fambrini "); lcd_gotoxy(1,2); printf( lcd_putc,"D1=%u",value); lcd_gotoxy(9,2); printf(lcd_putc,"D2=%u",value1) ; while(TRUE) { } }
  46. 46. Como guardar um número Float ou um int32 na Eeprom ? //*********************** Gravando Float na EEPROM *****************************// void WRITE_FLOAT_EEPROM (int8 n, float data) { int8 i; for (i = 0; i < 4; i++) write_eeprom (i + n, *(&data + i) ) ; } //**************************** Lendo Float na EEPROM *************************// float READ_FLOAT_EEPROM (int8 n) { int8 i ; float data; for (i = 0; i < 4; i++) *(&data + i) = read_eeprom (i + n); return(data); }

×