Usando várias interrupções externas no PIC

9

Eu usei PIC16F877( datasheet ) para vários projetos. Para uma única mudança de pino externo interrompe, você pode usar a PORTB0interrupção. Mas agora eu preciso suportar 8 interrupções externas independentes de troca de pinos, em um único circuito.

Na folha de dados, ele diz que há 15 interrupções PIC16F877, mas acho que essas são contadas, incluindo interrupções do temporizador, etc., que são inúteis nesse caso.

É o que dizem os dados sobre o INTCONregistro.

insira a descrição da imagem aqui

Posso ter 4 interrupções independentes usando o bit0 RBIF? Representa mudança em PB7:PB4. Como posso identificar qual pino foi alterado lendo o valor da porta na rotina de interrupção?

Até eu recebo respostas positivas acima, preciso de 8 interrupções? é claro que ainda posso usar INTE, para PORTB0mudar. Então 4 + 1 = 5, mas e os outros 3? (No entanto, todos os 8 eventos de interrupção são do mesmo tipo, a 4 + 1 + 3 = 8coisa parece feia, não é?)

Não há outras tarefas pesadas esperadas do microcontrolador além do monitoramento de 8 pinos. (Falando sobre as outras tarefas, ele precisará manter um conjunto de variáveis ​​de contador separadas e transmitir frequentemente cerca de 4 bytes para o PC em série)

Todas as sugestões são bem-vindas. Mesmo que seja sobre mudar o microcontrolador para um mais adequado (mas ... não me diga para não usar PICs).

Codinome SC
fonte
2
Sem usar interrupções, pode ser que você possa monitorar os pinos no programa principal. Mas isso não é perfeito. Como alternativa, você pode usar o Arduino. Embora não seja PIC, é bastante simples, você entenderá facilmente como já está familiarizado com PICs.
Anubis
11
Se você usar a interrupção do RBIE, poderá apenas armazenar em buffer o valor anterior a cada vez e um XOR para descobrir o que mudou. Deve ser bem rápido de executar.
precisa saber é
@ PeterJ eu não entendi direito. Buffer que valor?
codinome SC
@PeterJ great! esperando ...
codinome SC
11
Uma maneira é usar uma porta externa de 8 entradas (como a 74LS30 nos velhos tempos) para combinar os sinais externos em um pino de interrupção. Como o 74 (HC) 30 é um portão NAND, você precisaria de todas as entradas altas no estado de repouso - elas também precisariam ser conectadas aos pinos da porta para que você pudesse identificar quais interrupções estavam ativas lendo a porta.
precisa saber é o seguinte

Respostas:

3

Este é o pseudocódigo C para explicar uma ideia. Ele usa um OR exclusivo para descobrir quais pinos foram alterados e chamarão seus diferentes manipuladores dentro de uma interrupção do RBIE. Dependendo de quão crítica é a aplicação, convém verificar como o PIC lida com situações como uma mudança de porta enquanto a interrupção está em execução para garantir que você não perca nenhum evento.

int old_port_b;

void isr_handler()
{
    int new_port_b, changed_pins;
    new_port_b = read_port_b();
    changed_pins = new_port_b ^ old_port_b;
    if (changed_pins | 1)
        rb0_hander();
    if (changed_pins | 2)
        rb1_hander();
        // ... etc
    old_port_b = new_port_b;
}

int main()
{
    old_port_b = read_port_b();
    enable_interrupt();
}
PeterJ
fonte
Entendi, obrigado! mas essa não é a resposta exata que estou procurando. Dessa forma, você pode monitorar RB7:RB4apenas 4 pinos. Mas estou pedindo uma maneira de monitorar 8 pinos. alguma sugestão?
codinome SC
Eu acho que há uma razão pela qual você não pode usar RB0 - RB7, o acima deve funcionar? Caso contrário, eu realmente não consigo pensar em uma maneira, se a alternância rápida do código não for vital, você poderá usar o estilo de código acima em uma interrupção do timer (ou apenas no loop principal).
precisa saber é
Para esse PIC, se você precisar usar interrupções para fazer isso, o truque do XOR no RB4: RB7 e quatro interrupções no RB0: RB3 é o caminho a seguir. Se você não precisa a interrupção, basta consultar toda a porta no seu código, ou usar uma interrupção do timer para lidar com a sondagem, se você precisa de uma taxa de amostragem difícil
Scott Seidman
and four interrupts for the RB0:RB3? O PIC16F877 não suporta interrupções RB1:RB3, não é?
codinome SC
Eu tinha perdido isso na folha de dados, eu estava assumindo que cobria toda a porta. Mas eu vi seu outro comentário uma vez por segundo, então acho que seria melhor apenas executar isso no loop principal. Com as interrupções, você precisará cuidar da atualização das variáveis ​​a qualquer momento durante a execução e como lidar com as alterações dos pinos enquanto a interrupção estiver em execução. Realmente parece que isso apenas o complicará sem nenhum ganho real. A única exceção que eu conseguia pensar é se você queria usar o wake from sleep em interrupção; nesse caso, você precisaria fazer o hardware deles.
precisa saber é
1

Essa parte possui apenas 4 interrupções de troca de pinos e algumas outras que você pode configurar nas arestas selecionadas. Uma estratégia seria detectar uma alteração no valor de 8 bits externamente e interromper a incompatibilidade. Isso fica confuso no hardware, mas será exatamente o que você deseja.

Os parâmetros importantes que você não declarou são a rapidez com que você precisa responder a uma alteração de pinos e qual o tempo mínimo que uma alteração de pinos persistirá para que seja válida. Dependendo das respostas, você pode pesquisar com base em uma interrupção regular no firmware. O 16F877 pode ser executado na taxa de instruções de 5 MHz e a verificação de uma alteração levaria apenas algumas instruções. Digamos que você configure a interrupção a cada 50 instruções. Isso deixaria boa parte do tempo do processador para o código em primeiro plano. A taxa de interrupção seria de 100 kHz e o período de 10 µs. É claro que o código de primeiro plano ainda precisa ver o sinalizador de alteração e fazer algo a respeito, portanto o tempo de resposta será superior a 10 µs, mas você não disse nada sobre o que precisa fazer quando uma alteração é detectada. Se isso só precisa responder no tempo humano,

Olin Lathrop
fonte
Desculpe pelos detalhes ausentes. Como a taxa de resposta esperada once per secondserá suficiente. Quando uma mudança de pino (apenas uma aresta, digamos, subindo) é detectada, um contador (variável) deve ser incrementado. No loop principal, ele deve monitorar os valores dos contadores e, quando se ultrapassa um determinado valor, quatro bytes devem ser transmitidos USARTpara o PC. Redefina o valor do contador relevante para zero. Simples assim. Eu acho que a opção de pesquisa vai dar certo, certo?
codinome SC
2
Uma vez por segundo ! Então, para que toda a agonia das interrupções? Isso é feito facilmente com pesquisas periodicamente. Qual é o problema então?
Olin Lathrop
hum ... eu acho que será melhor, pois existem 8 deles e também, a resposta não pode ser prevista (mas esse valor pode ser considerado o mínimo). Ei! as pessoas podem cometer erros, certo .. :(
codinome SC
1

Você pode usar o NAND do gate de 8 entradas, como mencionado por Brian Drummond, para provocar uma interrupção no pino INT e também conectar suas fontes de interrupção ao Registro de Deslocamento de Entrada / Saída Paralela / Saída Serial de 8 bits, como "74HC165N", para que você precise apenas ler os dados desse Shift Register após o aumento da interrupção e fornecer informações sobre sua fonte de interrupção real ... talvez não seja o caminho mais rápido, mas fácil de expandir e use não mais do que 5 pinos, e se você adicionar um sistema de controle de endereço (MUX, LATCH, ...), precisará de apenas um pinho para notificação de interrupção e outros pinos poderão ser reutilizados em momentos diferentes para recursos diferentes;)

Eli Oulman
fonte