Aula 15 Prof. Ricardo Teixeira Tecnologia em Mecatrônica Industrial SENAI Memória Flash Memória Flash • A memória Flash de programa pode ser escrita e lida durante a operação normal do programa. • A operação de gravação na memória Flash causa a parada da execução do programa até que a gravação seja completada. • Ela não pode ser acessada durante a escrita. • Durante a escrita os periféricos continuam a funcionar e as interrupções são empilhada até que a escrita acabe. Memória Flash • Quando se precisa o espaço da memória de programa para dados devemos tomar cuidado para não sobrescrever o próprio programa. • É preciso verificar o primeiro endereço livre. Para isto abra o arquivo com extensão .lst após compilar seu programa no CSS e verifique o endereço da instrução SLEEP, como na imagem (0x011E). • O primeiro endereço disponível será o endereço do SLEEP + 1, neste caso 0x011F. • Como a memória de programa no PIC18F4550 vai até o endereço 0x7FFF, temos que nos certificar de utilizar apenas até este ponto. Acesso à Flash • read_program_eeprom(address) – Lê a memória de programa no endereço address (16 ou 32 bits, varia por PIC). – value = read_program_eeprom(address); • write_program_eeprom(address, value) – Escreve na memória de programa no endereço address o valor value. – write_program_eeprom(0x1000, 0x1234) • erase_program_eeprom(address) – Apaga FLASH_ERASE_SIZE bytes na memória de programa. – erase_program_eeprom(0x1000); Exercício 1 • Crie um programa que exibe o conteúdo da memória Flash no display LCD – Na primeira linha o endereço – Na segunda linha o conteúdo da memória – O programa é controlado por dois botões • um deles lê a posição anterior • O segundo lê a posição posterior Bootloader • Bootloader é um programa utilizado para gravar de forma mais simples o microcontrolador. • Ao utilizar o bootloader não é preciso utilizar um gravador específico, o próprio chip torna-se capaz de gravar o programa em sua memória, como é o caso dos chips com USB nativamente . • Em outros casos apenas um circuito de conversão USB/USART é necessário para a gravação via USB. Revisão Estrutura básica do programa • Arquivo de interface do microcontrolador #include <18F4550.h> • Bits de configuração #fuses XT, NOWDT, MCLR • Função principal e loop principal // função principal void main () { // loop principal while (true) { } } Estrutura básica do programa • Arquivo de interface do microcontrolador #include <18F4550.h> • Bits de configuração #fuses XT, NOWDT, MCLR • Delay do sistema – Se usar o oscilador interno ( #fuses INTRC ) #use delay (clock=4HMz) – Se usar um cristal como oscilador ( #fuses XT ) #use delay (crystal=4HMz) Estrutura básica do programa • Função principal e loop principal // função principal void main () { // loop principal while (true) { } } Portas de Entrada e Saída • Funções de saída: – output_x (int valor), onde x representa a porta (a, b, c, d ou e). – output_low (PIN_Px), coloca o bit especificado por PIN_Px em nível baixo (0). Px é a letra da porta e o respectivo bit (A0, B1 etc.) – output_high (PIN_Px), coloca o bit especificado por PIN_Px em nível alto (1). Px é a letra da porta e o respectivo bit (A0, B1 etc.) – output_toggle(PIN_Px), alterna o estado, alto e baixo do bit. – output_bit( PIN_Px, bit), altera o pino Px para o valor de bit (0 ou 1). Portas de Entrada e Saída • Funções de entrada: – input_x (), lê a porta representa por x (a, b, c, d ou e). – intput(PIN_Px), lê o pino especificado. – Intput_state(PIN_Px), lê o pino especificado sem mudar a direção. Portas de Entrada e Saída • Registradores TRIS – Cada porta possui um registrador TRIS associado a ela – O nome TRIS vem de Tri-state em alusão às portas de 3 estados (alto, baixo e desconectado) – Os bits de cada registrados TRIS configuram o bit da porta respectiva como entrada ou saída. – Para setar o valor do registrador, por exemplo da porta B, usamos set_tris_b (0b00001111), os 4 primeiros bits estão definidos como entrada(1) e o resto como saída (0). Oscilação • O oscilador determina a velocidade de execução das instruções. • Podemos utilizar o oscilador interno ou externo. • O clock interno é o clock externo dividido por 4. Assim se utilizamos um cristal de 4MHz para o clock externo, o clock interno será de 1MHZ. • O ciclo de máquina, ou seja, o tempo de execução de cada instrução (ou pelo menos da maioria delas) é 1/’clock interno’. Assim, com clock interno do 1MHz teríamos 1/1000000 de clock interno, ou 1μ𝑠 (0,000001𝑠). Temporização • Funções de Atraso – Não são precisas – São criadas a partir de instruções asm • delay_cycles(int8 n) – n – constante de 1 a 255 – Espera n ciclos de máquina • delay_us(int16 time) – Time – 0 a 65535 – Espera time microsegundos • delay_ms(int16 time) – Time – 0 a 65535 – Espera time milisegundos Temporização • As funções de atraso são a pior forma possível de se contar ou esperar algum tempo! • A forma correta é a utilização dos timers internos do microcontrolador (Timer0 até Timer3, no caso do PIC18F4550). Módulo TIMER0 (8 ou 16 bits) • Comumente conhecido como RTCC (Real Time Counter Clock). • Temporização sem comprometer o processamento do microcontrolador até ocorrência da interrupção. • Incrementado pelo clock interno ou pelo pino externo T0CKI (Timer zero clock input), pino RA4. Módulo TIMER0 - Prescaler • Diminui a velocidade do TIMER. • Configurado no registrador T0CON<3:0> nos bits PSA e T0PS2:T0PS0 e vai de 1:2 áté 1:256. • Pode ser alterado em tempo de execução. Módulo TIMER0 - Interrupção • Ocorre quando há a contagem do TIMER0 no registrador TRM0 chega ao valor máximo. • Este valor depende do modo de operação. Em 8 bits o valor é 0xFF e em 16 bits 0xFFFF. • A interrupção do TIMER0 pode ser habilitada ou não. • Mesmo que a interrupção esteja desligada é possível olhar TRM0IF (timer zero interruption flag) e saber se ocorreu um estouro. Como calcular o tempo de interrupção? • Vamos supor que temos um sistema com o cristal de 20MHz. Teremos, 20.000.000 𝐶𝑙𝑜𝑐𝑘 𝑖𝑛𝑡𝑒𝑟𝑛𝑜 = = 5.000.000 𝐻𝑧 4 1 𝐶𝑖𝑐𝑙𝑜 𝑑𝑒 𝑚á𝑞𝑢𝑖𝑛𝑎: = 0,2𝑢𝑠 5.000.000 • Como o timer, em modo 16 bits, conta até de 0 até 65.535, são 65.536 períodos. • Assim cada estouro do timer ocorre com 65.536 ∗ 0,2us = 13.107,2us. • Com o prescaler 1:32, cada contagem do timer dura 32 ciclos de máquina. Logo, cada estouro ocorre com 32 ∗ 65.536 ∗ 0,2 = 419.430,4us • Então temos aproximadamente 420ms a cada estouro. Circuito de Reset • O pino Master Clear Reset permite a criação de uma forma de reset via hardware. • O pino é ativo em 0, isto é, quando seu nível for zero estará em modo reset. • É preciso que utilizar o fuse MCLR (#fuses MCLR). Bounce • Mas como podemos evitar este problema? • Para evitar o problema causado pelo bounce pode-se: – Comparar o estado novo com o antigo diversas vezes – Ao se perceber a 1 primeira transição aguardar um tempo antes de voltar a ler o botão. Algoritmo do Debounce • Leia o estado do botão • Se o estado for ativo (em 0 ou em 1, depende do que você precisa), aguarde algum tempo (ex.: 10ms) • Leia novamente o estado do botão e se ele se mantiver no estado ativo execute a ação desejada. Código int1 botao = input(PIN_B0); If (botao == 1) { delay_ms(10); botao = input(PIN_B0); If (botao == 1) { // ações desejadas } } Interrupções • É uma forma de tratar determinados eventos que ocorrem, seja por interferência do usuário ou por alguma fonte interna ao hardware. • Quando o evento observado pela interrupção ocorre o código é interrompido e o processamento desviado para a ação que deve ser tomada devido ao evento ocorrido. Interrupções • Quando devo usar interrupções? – Contagem de tempo; – Analisar a mudança de estado e/ou borda; – Finalização da conversão A/D; – Interrupção de chagada de dados seriais; – Comunicação I²C e SPI; Interrupções no PIC18F4550 • No PIC18F4550 temos várias possibilidades de interrupção. – Interrupções externas; – Interrupções de estouro dos Timers; – Interrupções de mudança de entrada na Porta B; – Recepção e Transmissão Serial; – Conversão A/D etc. Conversão Analógico Digital • Converte uma tensão analógica em um número digital binário proporcional. • Dois parâmetros precisam ser conhecidos: – Qual a faixa de tensões possíveis. – Qual a quantidade de bits. Conversão Analógico Digital • O cálculo da conversão é feito pela proporção do valor lido em relação ao valor máximo do conversor A/D. • O módulo A/D do PIC18F4550 tem resolução de até 10 bits. • Dessa forma quando fizermos a leitura de um pino A/D teremos valor digital entre 0 e 1023, para o caso de 10 bits, e não o valor da tensão de entrada. • Para obter a leitura do valor analógico temos que fazer um cálculo de proporção. – Vamos supor que estamos utilizando o módulo A/D configurado para 10 bits. – Dada uma tensão de entrada Vin de um valor entre 0 e Vref, onde Vref é a tensão de referência do conversor A/D, podemos calcular a tensão de entrada pela proporção Vin = leitura / 1023 * Vref Conversor AD – Exemplo de Configuração #include <18F4550.h> #device ADC = 10 #fuses NOWDT, XT, MCLR #use delay(crystal=4MHz) #INT_AD void conversaoAD () { } void main () { setup_adc( ADC_CLOCK_INTERNAL ); setup_adc_ports( AN0 ); // Apenas o canal 0 será usado set_adc_channel(0); // AN0 enable_interrupts(GLOBAL); enable_interrupts(INT_AD); while (true) { // seu código } } Memória EEPROM • EEPROM (Electrically Erasable Programmable Read Only Memory) • Memória apenas de leitura programável e eletricamente apagável, ou seja • Ela não é uma memória apenas de leitura, não acham? • O PIC18F4550 tem 256 bytes de memória de dados EEPROM. • A memória de dados EEPROM permite operações de leitura e escrita de bytes sem interferência na operação do microcontrolador. • Memória não volátil separada das memória de dados e de programa. Aplicações da EEPROM • Configurações do hardware • Informações de uso de equipamentos – Quantidade de impressões de uma impressora; – Odômetro do carro (mesmo quando trocamos a bateria a marcação não muda em odômetros digitais); – Configurações de alarme, calendário etc; • Logs de erro • De forma geral, qualquer dado que se deseje! CCS e a EEPROM • Interrupção: – INT_EEPROM • Interrupção executada quando a escrita na EEPROM está completa. • Funções – read_eeprom(address) • Lê o dado na posição de memória EEPROM • Ex.: value = read_eeprom(0x0); – write_eeprom(address, value) • Apaga e escreve o dado value no endereço address da EEPROM. • Ex.: write_eeprom(0x0, 0x12); PWM • Pulse Width Modulation, do inglês, Modulação por Largura de Pulso. • Gera uma onda quadrada em um pino digital do microcontrolador. • Sua principal função é controlar tensão de alimentação de dispositivos como motores, lâmpadas, carregadores de baterias de células solares etc. PWM • Observe o exemplo da lâmpada abaixo. Se a lógica um (1) indica o lâmpada-ligada e a lógica zero (0) indica lâmpadadesligada. O consumo da lâmpada será diretamente proporcional a duração do pulso. Essa proporção é chamada normalmente de Duty Cycle. Exemplo no CCS #include <18F4550.h> #FUSES NOWDT, XT, MCLR #use delay(crystal=4MHz) int16 valor = 0; void main() { output_low(PIN_C1); setup_ccp1(CCP_PWM); setup_timer_2(T2_DIV_BY_1, 255, 1); set_pwm1_duty(valor); while (true) { set_pwm1_duty(valor); valor += 5; if (valor > 255) { valor = 0; } delay_ms(100); } } Comunicação Serial vs Paralela Comunicação Serial • Utiliza apenas duas linhas para comunicação TX e RX, onde, RX representa a linha que recebe os dados e a TX a linha que transmite os dados. Comunicação Serial - CCS • Funções importantes – getc() ou getch() / getchar() ou fgetc() • Obtém um caractere do pino de recepção (do stream especificado no caso do fgetc). • Use o KBHIT() para checar se algum caractere está disponível. – gets() or fgets() • Obtém uma string do pino de recepção (do stream especificado no caso do fgets). Use getc para receber cada caractere até return (\r) ser encontrado. – putc() or putchar() or fputc() • Envia um caractere para a linha de transmissão (do stream especificado no caso do fputc). – puts() or fputs() • Envia uma string para a linha de transmissão (do stream especificado no caso do fputs). – printf() or fprintf() • Envia uma string formatada para linha de transmissão (do stream especificado no caso do fprintf). – kbhit() • Retorna true quando um caractere for recebido e estiver disponível para a leitura. ICSP (In-Circuit Serial Programming) • Programação Serial no Circuito – Refere-se a possibilidade de gravar o chip sem removê-lo do circuito final. – Desta forma não é preciso colocar o chip em um gravador. – Evitar danificar o chip por não precisar movê-lo. • Vários gravadores permitem este modo – PIC Kit 2; PIC Kit 3; K150; ICD3; ICD3 etc. • Não é específico da família PIC – A placa Arduino Uno e Nano também tem este modo. ICSP no PIC