- Diagrama de circuito:
- Código de sequência piscando do microcontrolador PIC PIC16F877A LED e explicação de funcionamento:
Em nosso tutorial anterior, aprendemos sobre como piscar um LED usando o microcontrolador PIC e construímos o mesmo circuito na placa Perf. Em seguida, usamos PICkit 3, ICSP e MPLAB IPE para despejar o programa em nossa placa Perf. Agora, neste tutorial, avançaremos para usar mais pinos no microcontrolador PIC. Usaremos 7 saídas (LEDs) e uma entrada. Para este tutorial, usaremos a placa Perf antiga (mostrada abaixo) e adicionaremos bastões de berg para puxar os pinos necessários para a segunda placa de LED. No final deste tutorial, iremos gerar uma sequência de LEDs piscando usando o microcontrolador PIC PIC16F877A e aprenderemos como usar várias entradas e saídas, alguns princípios básicos sobre o loop 'for' e chamada de função.
A placa de LED nada mais é que outra placa de desempenho, na qual soldaremos os LEDs com um resistor limitador de corrente (mostrado abaixo). Também adicionaremos um botão para iniciar o LED de sequência piscando.
Diagrama de circuito:
Código de sequência piscando do microcontrolador PIC PIC16F877A LED e explicação de funcionamento:
O código completo foi fornecido abaixo (verifique no final), aqui nós o obteremos linha por linha. Este código começará a acender os LEDs de maneira sequencial quando o botão for pressionado. Para entender as sequências, assista ao vídeo no final do tutorial. Eu recomendo que você compare a saída mostrada no vídeo com o código abaixo e tente entender o programa.
Vejamos o código linha por linha. As primeiras linhas são para definir bits de configuração que foram explicados no tutorial anterior, portanto, estou pulando por agora. A melhor maneira de entender qualquer programa é começar pela função principal ( void main () ), então vamos fazer isso
TRISB0 = 1; // Instrua o MCU que o pino 0 da PORTB é usado como entrada para o botão. TRISD = 0x00; // Instrui o MCU para que todos os pinos tenham saída PORTD = 0x00; // Inicializa todos os pinos para 0
A palavra TRIS é usada para definir se o pino está sendo usado como entrada / saída e a palavra PORTA é usada para fazer um pino alto / baixo. A linha TRISB0 = 1 fará o 0º pino da PORTA B como entrada. Este será o nosso botão. As linhas TRISD = 0x00; PORTD = 0x00; fará todos os pinos da porta D como saída e atribuirá um valor inicial LOW a esses pinos.
Como dissemos que B0 é usado como entrada, conectaremos uma extremidade do botão ao pino B0 e a outra extremidade ao terra. Nesse momento, sempre que pressionarmos o botão, o pino será mantido no solo, conforme mostrado no diagrama de conexão acima. Mas para que isso aconteça, temos que usar um resistor pull up para que o pino seja mantido alto quando o botão não for pressionado. Um resistor pull up é algo assim.
Mas nosso PIC MCU tem um resistor pull up fraco interno que pode ser ativado por software dessa forma, economizando muito trabalho (quando mais botões devem ser conectados).
O que é um resistor pull up fraco?
Existem dois tipos de resistor pull up, um é Weak Pull Up e outro é Strong Pull Up. Os resistores pull up fracos são de valor alto e, portanto, permitem que uma corrente fraca flua e os resistores pull up fortes são de valor baixo, permitindo assim que uma corrente forte flua. Todos os MCU usam principalmente resistores pull up fracos. Para ativar isso em nosso PIC MCU, temos que olhar em nossa folha de dados para OPTION_REG (registro de opção), conforme mostrado no instantâneo abaixo.
Como mostrado, o bit 7 trata do resistor pull up fraco. Deve ser zerado para ativá-lo. Isso é feito por OPTION_REG <7> = 0 . Isso lida especificamente com o bit 7, deixando os outros bits com seus valores padrão. Com isso, entramos em nosso loop while, onde verifica se o botão está pressionado usando if (RB0 == 0). Se a condição for satisfeita, chamamos nossa função com os parâmetros 1, 3, 7 e 15.
piscar (1); // FUNCTION CALL 1 com parâmetro 1 sblink (3); // FUNCTION CALL 3 com parâmetro 3 sblink (7); // CHAMADA DE FUNÇÃO 7 com parâmetro 7 sblink (15); // FUNCTION CALL 4 com parâmetro 15
Por que usamos funções?
Funções são usadas para reduzir o número de linhas em nosso código. Isso é o que a maioria de nós saberia. Mas por que precisamos reduzir o número de linhas, especialmente quando se trata de programação MCU. O motivo é o espaço limitado em nossa memória de programa. Se não otimizarmos o código adequadamente, podemos ficar sem espaço de memória. Isso será útil quando escrevermos longas páginas de códigos.
Qualquer função terá uma função Definition ( sblink (int get) no nosso caso) e uma função Call ( sblink (1) no nosso caso). É opcional ter uma declaração de função; para evitá-lo, coloquei minha definição de função antes de chamar a função em minha função principal.
Os parâmetros da função são o valor que será passado da chamada da função para a definição da função. Em nosso caso, os valores inteiros (1, 3, 7, 15) são os parâmetros que são passados da chamada de função e a variável "get" obtém o valor dos parâmetros na definição da função para processá-los. Uma função pode ter mais de um parâmetro.
Assim que a função for chamada, as linhas abaixo na definição da função serão executadas.
para (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED move a seqüência à esquerda __delay_ms (50); } para (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED move a seqüência à esquerda __delay_ms (50); }
Agora, esta linha parece estranha: PORTD = get << i . Vou explicar o que realmente está acontecendo aqui.
"<<" é um operador de deslocamento à esquerda que desloca todos os bits para sua posição à esquerda. Agora, quando chamamos a função sblink (int get) com o parâmetro '1' como sblink (1), ela transforma o valor de 'get' em 1, que em binário é 0b00000001. Portanto, esta linha será como PORTD = 0b00000001 << i .
O valor de "i" irá variar de 0 a 7, uma vez que usamos um 'for loop' para (int i = 0; i <= 7 && RB0 == 0; i ++). O valor de 'i' sendo de 0 a 7 mudará o resultado da seguinte forma:
Como você pode ver, ligamos um LED por vez (da esquerda para a direita), mantendo os demais desligados. O próximo 'for loop' para (int i = 7; i> = 0 && RB0 == 0; i--) , também fará o mesmo, mas desta vez o LED será ligado da direita para a esquerda em uma sequência, já que começamos de 7 e descemos para 0. Usamos um atraso de 200ms para que possamos visualizar o LED sendo LIGADO e DESLIGADO.
Agora, quando passamos o valor 3 na função sblink (int get) , a função sblink (3) será executada, o que torna o valor de 'get' 0b00000011, portanto, o resultado em PORTD será:
Portanto, desta vez, dois LEDs serão ligados a qualquer momento usando sblink (3). Da mesma forma para sblink (7) e sblink (15), três e quatro LEDs estarão LIGADOS em sequência. Depois de concluído, faremos com que todos os LEDs estejam acesos usando a linha PORTD = 0xFF . Confira o vídeo abaixo para uma demonstração completa.
Espero que você tenha entendido o código e, portanto, tenha aprendido como usar as funções 'for' e 'while' loop para obter as saídas desejadas. Agora você pode ajustar o código para fazer sua sequência diferente de LED piscar. Vá em frente, compile seu código e despeje-o em seu MCU e aproveite a saída. Você pode usar a seção de comentários se ficar preso em algum lugar. Eu também anexei a simulação e os arquivos do programa aqui.
Por enquanto, em nosso próximo tutorial, aprenderemos como usar temporizadores PIC16F877A em vez de usar funções de atraso. Você pode navegar por todos os tutoriais do microcontrolador PIC aqui.