Os pinos individuais de diferentes portas de um microcontrolador podem ser mapeados para um registrador e seus valores podem ser alterados ao alterar o valor do registrador?


12

P: Os pinos individuais de diferentes portas de um microcontrolador podem ser mapeados para um registrador e seus valores alterados ao alterar o valor do registrador?

Cenário: usei alguns pinos de cada porta (8 bits) do microcontrolador. Agora, quero fazer interface com um dispositivo que precise de um barramento de 8 bits (suponha D0 a D7 EM SEQUÊNCIA), ou seja, preciso de 8 pinos do controlador para poder conectá-los de maneira individual.

portx0  -> D0 // x is the name of port followed by bit location on that port
portx1  -> D1
...
portx7  -> D7

mas eu não tenho uma porta inteira de 8 pinos que eu posso conectar com este dispositivo, mas tenho alguns pinos do portx, alguns do porty e outros do portz. O novo cenário de conexão é como (conexão do microcontrolador ao dispositivo, respectivamente)

portx0  -> D0
portx1  -> D1
portx2  -> D2
porty4  -> D3
porty5  -> D4
porty6  -> D5
porty7  -> D6
portz1  -> D7

Nesta condição, se eu quiser enviar um valor, diga

unsigned char dataReg = 0xFA;

para o meu dispositivo do controlador, tenho que executar operações pouco inteligentes no valor a ser enviado e definir cada pino de acordo com o valor no registro individualmente. Por exemplo

portx0 = ((dataReg & 0x01) >> 0 );  // Masking and shifting as bit position
portx1 = ((dataReg & 0x02) >> 1 );
portx2 = ((dataReg & 0x04) >> 2 );
porty4 = ((dataReg & 0x08) >> 3 );
porty5 = ((dataReg & 0x10) >> 4 );
porty6 = ((dataReg & 0x20) >> 5 );
porty7 = ((dataReg & 0x40) >> 6 );
portz1 = ((dataReg & 0x80) >> 7 );

Agora, chegando à questão principal, para evitar esses cálculos individuais em cada bit em portas diferentes, pinos individuais de portas diferentes de um microcontrolador podem ser mapeados para um registro e seus valores podem ser alterados ao alterar o valor do registro?


1
Eu tive a mesma idéia há um tempo atrás. Com os PICs, isso não é possível: microchip.com/forums/tm.aspx?high=&m=696277 - Não acho que seja possível com nenhum micro, mas listar seu dispositivo seria útil.

Respostas:


6

Parece que sua pergunta se resume a ter um valor de 8 bits no firmware e querer ler e escrever isso de e para uma coleção arbitrária de pinos de porta.

Não há uma maneira direta de hardware para fazer isso. Você precisa escrever duas rotinas, uma para ler o valor de 8 bits e outra para escrevê-lo. Outros mencionaram o uso de sindicatos, mas isso é uma péssima idéia. Com os sindicatos, você precisa lidar com todos os bits separadamente, e o código se torna dependente da ordem de bits do micro. Este pode ser o caminho a seguir de qualquer maneira, se todos os 8 bits estiverem espalhados de forma completamente independente. Nesse caso, há pouco que você pode fazer além de criar um código especial para cada bit.

A melhor maneira de fazer isso, especialmente se você pode agrupar os bits em alguns blocos contíguos nas portas físicas, é usar mascaramento, deslocamento e ORing. Por exemplo, se os três bits mais baixos do byte interno estiverem nos bits <6-4> de uma porta, mova à direita esse valor da porta em 4 e AND com 7 para colocar esses bits em sua posição final. Shift e mascarar (ou mascarar e shift) bits de outras portas no lugar e montar o byte final de 8 bits ORing os resultados nele.

Esse tipo de ajuste de bits de baixo nível é mais fácil de fazer no assembler que o C. Eu provavelmente colocaria as rotinas de leitura e gravação de bytes em um único módulo do assembler e tornaria a interface acessível pelo C.


6
Minha resposta seria quase idêntica à sua, exceto que eu não usaria montagem; as manipulações de bits são triviais em C. Acho que seria mais uma dor de cabeça (re) aprender a convenção específica de chamadas em C para o compilador e como executar o vinculador. Depende realmente do compilador e de como isso dificulta as coisas. :-)
akohlsmith

@ Andrew: Sério? As convenções de chamada estão claramente descritas em qualquer manual do compilador que eu tenha visto onde possa haver necessidade de interface com o código de montagem. A manipulação de bits pode ser "trivial" para escrever em C, mas essa é uma área em que os compiladores podem produzir código horrendo. Se a velocidade ou o espaço do código não importarem, use o que você quiser. Estou mais à vontade com o assembler para mexer com pouco nível, então eu usaria isso. Se essa é uma rotina de baixo nível de velocidade, você deve fazê-lo no assembler. Realmente deve ser fácil.
Olin Lathrop

1
O que estou dizendo é que ter que lidar com isso por algo tão trivial quanto a manipulação de bits não é algo que eu faria, a menos que houvesse uma boa razão para isso. Não conhecemos as especificidades de seu barramento paralelo, mas a maioria dos barramentos possui sinais estroboscópicos que eliminam a necessidade de atualizações "quase atômicas" de todos os pinos do barramento, portanto, a instalação é provavelmente uma otimização desnecessária e uma complexidade desnecessária (mesmo que seja simples).
akohlsmith

@ Andrew: É apenas confuso ou complexo se você não sabe o que está fazendo. Eu acho que o verdadeiro problema é que algumas pessoas têm medo de montador e não o conhecem bem. Isso é um erro. Ele precisa ser uma ferramenta pronta em sua caixa de ferramentas. Se você não o conhece bem ou não se sente à vontade, sempre estará justificando como as coisas devem ser feitas de outra maneira. Algumas coisas são mais fáceis no assembler, se você o conhece e o HLL igualmente bem. A maioria das pessoas não, mas isso é um problema para elas, não para usar o assembler.
Olin Lathrop

2
Sou versado em linguagem assembly em vários microcontroladores / microprocessadores. Eu discordo que deveria ser uma ferramenta pronta; deve ser usado com moderação e somente quando necessário, geralmente para inicialização de nível muito baixo, código crítico de tempo ou tamanho ou, no caso mais comum, otimização de uma área que você já determinou ser um gargalo. Acho que os projetos nos quais os autores que pulam para a montagem porque geralmente escrevem código menos claro ou não reconhecem quando um algoritmo está sendo mal aplicado. Não estou dizendo especificamente que é você, mas no caso mais geral.
akohlsmith

4

Em geral, isso não é possível. Tanto quanto eu sei, não é possível com PICs.

Só sei que existe um microcontrolador que pode fazer isso, o Cypress PSoC . É um sistema altamente configurável no chip. Entre as muitas coisas que permite, você pode definir literalmente seu próprio registro (1-8 bits) e conectá-lo a qualquer pino que desejar, ou mesmo a circuitos internos.

Fiação PSoC

Por exemplo, aqui eu criei um registro de controle de 6 bits. 5 dos bits vão direto para os pinos, enquanto o sexto bit que estou usando no XOR com a entrada de um 7º pino.

Pinos PSoC

No chip, posso optar por alocar esses pinos a qualquer um dos pinos GPIO disponíveis. (São os cinza da imagem)


1
O LPC800 também deve ser capaz de fazê-lo, pois as funções podem ser atribuídas livremente aos pinos.
starblue

-1

Você pode tentar o seguinte. Escreva uma estrutura própria que mapeie para os respectivos pinos das 2 portas (que devem ser usadas). Agora, a atualização do valor neste registro deve definir / redefinir os pinos dessas 2 portas. Apenas tente e deixe-nos saber se funcionou !!

Estou confiante de que isso deve funcionar.


2
Em C, você pode mapear uma estrutura para um local de memória e mapear bits de sua estrutura (campos de bits) para compensações de bits, mas não há como impedir que o compilador mexa com os bits 'entre' e agora existe maneira de visualizar a estrutura 'geral' de um único valor inteiro. Isso não vai funcionar.
Wouter van Ooijen

-1

Se entendi a pergunta corretamente, é fácil em C:

Declaração de tipo genérico, pode ser reutilizada para qualquer registro:

typedef union    // Generic 8-bit register Type
{
  uint8 reg; // Whole register
  struct
  {
    unsigned  bit7     : 1;  // Bit 7 
    unsigned  bit6     : 1;  // Bit 6 
    unsigned  bit5     : 1;  // Bit 5 
    unsigned  bit4     : 1;  // Bit 4 
    unsigned  bit3     : 1;  // Bit 3 
    unsigned  bit2     : 1;  // Bit 2 
    unsigned  bit1     : 1;  // Bit 1 
    unsigned  bit0     : 1;  // Bit 0 
  } bit;
} typ_GENERIC_REG8;

Então, para definir uma porta que queremos abordar:

#define MCU_GPO_PORTx   (*(volatile typ_GENERIC_REG8 *)(0x12345678)) // Number is address

E para ajustar diretamente um pino nessa porta:

#define MCU_PORTx_PINn  (MCU_GPO_PORTx.bit.bit0)

Em código:

MCU_PORTx_PINn = 1; // Set pin high

Registro completo:

MCU_GPO_PORTx.reg = 0xF; // All pins high

Vale a pena ler sobre estruturas, uniões, typedefs e enums - tudo isso torna a vida muito mais agradável no incorporado e em geral!


O OP quer combinar vários bits de portas diferentes em 'um byte'. Não vejo como isso faria isso? Olin Lathrop explica por que não é possível.

Na verdade, isso não resolve o problema e, dependendo de quão "smrt" é seu compilador, pode gerar um novo conjunto de problemas para depuração.
akohlsmith
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.