È possibile mappare singoli pin di diversa porta di un microcontrollore su un registro e modificarne i valori quando si modifica il valore del registro?


12

D: È possibile mappare singoli pin di porte diverse di un microcontrollore su un registro e modificarne i valori quando si modifica il valore del registro?

Scenario: ho esaurito alcuni pin di ciascuna porta (8 bit) del microcontrollore. Ora voglio interfacciare un dispositivo che necessita di un bus a 8 bit (supponiamo da D0 a D7 IN SEQUENZA), vale a dire che ho bisogno di 8 pin dal controller in modo da poterli connettere in un modo uno a uno

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

ma non ho un'intera porta di 8 pin che posso collegare con questo dispositivo, piuttosto ho alcuni pin di portx, alcuni di porty e alcuni di portz. Il nuovo scenario di connessione è il seguente (connessione rispettivamente dal microcontrollore al dispositivo)

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

In questa condizione se voglio inviare un valore dire

unsigned char dataReg = 0xFA;

sul mio dispositivo dal controller devo eseguire operazioni bit-saggio sul valore da inviare e impostare ciascun pin in base al valore nel registro individualmente. Per esempio

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 );

Ora, arrivando alla domanda principale, per evitare questi singoli calcoli su ciascun bit su porte diverse, è possibile associare a un registro i singoli pin di diversa porta di un microcontrollore e modificarne i valori quando si modifica il valore del registro?


1
Ho avuto la stessa idea qualche tempo fa. Con i PIC, questo non è possibile: microchip.com/forums/tm.aspx?high=&m=696277 - Non credo sia possibile con nessun micro, ma elencare il tuo dispositivo sarebbe utile.

Risposte:


6

Sembra che la tua domanda si riduce ad avere un valore di 8 bit nel firmware e voler leggere e scrivere da e verso una raccolta arbitraria di pin della porta.

Non esiste un modo hardware diretto per farlo. Devi scrivere due routine, una per leggere il valore a 8 bit e una per scriverlo. Altri hanno menzionato l'uso dei sindacati, ma questa è una cattiva idea. Con i sindacati, devi gestire ogni bit separatamente e il codice diventa dipendente dall'ordine dei bit del micro. Questo potrebbe essere il modo di procedere comunque se tutti gli 8 bit sono sparsi in modo completamente indipendente. In tal caso, non c'è altro da fare che creare un codice speciale per ogni bit.

Il modo migliore per farlo, specialmente se è possibile raggruppare i bit in alcuni blocchi contigui sulle porte fisiche è utilizzare il mascheramento, lo spostamento e l'ORing. Ad esempio, se i tre bit inferiori del byte interno si trovano sui bit <6-4> di una porta, spostare a destra quel valore di porta di 4 e AND con 7 per portare quei bit nella loro posizione finale. Spostare e mascherare (o mascherare e spostare) i bit da altre porte in posizione e assemblare il byte finale a 8 bit OR inserendo i risultati in esso.

Questo tipo di manipolazione dei bit di basso livello è più facile da eseguire in assemblatore rispetto a C. Probabilmente metterei il byte in lettura e scrivo le routine in un singolo modulo assemblatore e rendere l'interfaccia richiamabile da C.


6
La mia risposta sarebbe quasi identica alla tua, tranne per il fatto che non userei affatto l'assemblaggio; le manipolazioni dei bit sono insignificanti in C. Penso che sarebbe più un mal di testa (ri) apprendere la specifica convenzione di chiamata C per il compilatore e come eseguire il linker. Dipende molto dal compilatore e da quanto sia difficile rendere le cose. :-)
akohlsmith il

@Andrew: Davvero? Le convenzioni di chiamata sono chiaramente enunciate in qualsiasi manuale del compilatore che ho visto dove potrebbe essere necessario interfacciarsi con il codice assembly. La manipolazione dei bit può essere "banale" per scrivere in C, ma questa è un'area in cui i compilatori possono produrre codice orrendo. Se la velocità o lo spazio del codice non ha importanza, usa tutto ciò che ritieni più comodo. Mi sento più a mio agio con l'assemblatore per la manipolazione di bit di basso livello, quindi lo userei. Se si tratta di una routine di velocità critica a basso livello, è necessario farlo in assembler. Dovrebbe essere davvero facile.
Olin Lathrop,

1
Quello che sto dicendo è che dovrei lasciarmi andare per qualcosa di così banale come la manipolazione dei bit non è qualcosa che farei a meno che non ci fosse una buona ragione per farlo. Non conosciamo i dettagli del suo bus parallelo ma la maggior parte dei bus ha segnali strobo che eliminano la necessità di aggiornamenti "quasi atomici" di tutti i pin del bus, quindi la caduta nell'assemblaggio è probabilmente un'ottimizzazione non necessaria e una complessità non necessaria (anche se lo è straightforwardish).
akohlsmith,

@Andrew: è solo un po 'complicato o complesso se non sai cosa stai facendo. Penso che il vero problema sia che alcune persone hanno paura dell'assemblatore e non lo sanno bene. Questo è un errore. Deve essere uno strumento pronto nella tua cassetta degli attrezzi. Se non lo conosci bene o non ti senti a tuo agio, giustificherai sempre come le cose dovrebbero essere fatte in un altro modo. Alcune cose sono più facili nell'assemblatore se lo conosci e l'HLL ugualmente bene. Molte persone non lo fanno, ma questo è un problema con loro, non con l'uso dell'assemblatore.
Olin Lathrop,

2
Sono esperto nel linguaggio assembly di numerosi microcontrollori / microprocessori. Non sono d'accordo sul fatto che dovrebbe essere uno strumento pronto; dovrebbe essere usato con parsimonia e solo quando necessario, di solito per inizializzazione di livello molto basso, codice critico per tempi o dimensioni o, nel caso più comune, ottimizzazione di un'area che si è già definita essere un collo di bottiglia. Trovo quei progetti in cui gli autori saltano all'assemblaggio perché è lì che spesso scrivono codice meno chiaro o non riconoscono quando un algoritmo viene applicato in modo errato. Non sto specificatamente dicendo che sei tu, ma piuttosto nel caso più generale.
akohlsmith il

4

In generale questo non è possibile. Per quanto ne so, non è possibile con i PIC.

So solo un microcontrollore che sa fare questo, il Cypress PSoC . È un sistema altamente configurabile su chip. Tra le molte cose che ti permette di fare è definire letteralmente il tuo registro (1-8 bit) e collegarlo a qualsiasi pin che ti piace, o anche a circuiti interni.

Cablaggio PSoC

Ad esempio, qui ho creato un registro di controllo a 6 bit. 5 dei bit vanno direttamente ai pin, mentre il 6 ° bit che sto usando a XOR con l'ingresso da un 7 ° pin.

Pin PSoC

Sul chip, posso scegliere di allocare questi pin a uno qualsiasi dei pin GPIO disponibili. (Sono quelli grigi quello dell'immagine)


1
LPC800 dovrebbe anche essere in grado di farlo, poiché le funzioni possono essere assegnate liberamente ai pin.
Starblue,

-1

Puoi provare quanto segue. Scrivi una tua struttura che mappi ai rispettivi pin delle 2 porte (che devono essere usate). L'aggiornamento del valore in questo registro imposterà / resetterà i pin di quelle 2 porte. Prova e facci sapere se ha funzionato !!

Sono fiducioso che dovrebbe funzionare.


2
In C puoi mappare una struttura su una posizione di memoria, e puoi mappare bit della tua struttura (campi di bit) su offset di bit, ma non c'è modo di impedire al compilatore di fare confusione con i bit "in-Between", e ora c'è modo di visualizzare la struttura 'complessiva' un singolo valore intero. Questo non funzionerà.
Wouter van Ooijen,

-1

Se ho capito correttamente la domanda, è abbastanza facile in C:

Dichiarazione di tipo generico, può essere riutilizzata per qualsiasi 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;

Quindi, per definire una porta che vogliamo indirizzare:

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

E per modificare direttamente un pin su quella porta:

#define MCU_PORTx_PINn  (MCU_GPO_PORTx.bit.bit0)

Nel codice:

MCU_PORTx_PINn = 1; // Set pin high

Registro intero:

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

Vale la pena leggere su strutture, sindacati, dattiloscritti ed enumerazioni - tutti questi rendono la vita molto più bella in embedded e in generale!


OP vuole combinare diversi bit di porte diverse in "un byte". Non vedo come questo farebbe? Olin Lathrop spiega perché non è possibile.

Questo in realtà non risolve il problema e, a seconda di quanto "smrt" è il tuo compilatore, potrebbe generare una serie completamente nuova di problemi per il debug.
akohlsmith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.