Cela ressemble à une approche comme celle-ci est dans le sens où vous souhaitez aller avec une solution.
Je n'ai pas testé cela car je n'ai pas le matériel mais cela devrait fournir une alternative à regarder. Ceci suppose que vous voulez activer des broches particulières ou désactiver des broches particulières, mais il n'y aura pas de cas où vous voudrez activer certaines broches et désactiver les autres broches pour un périphérique particulier en une seule opération. Si cela devait être le cas, je considérerais que le type RegPinNo
soit un raccourci non signé pour inclure un code d'opération pour chaque combinaison de registre/numéro de broche.Cela suppose également que la synchronisation des opérations n'est pas une contrainte critique et que le matériel a une puissance suffisante pour que les petites boucles ne représentent pas une charge importante pour le débit et le temps CPU nécessaire pour d'autres tâches. Ce code peut donc nécessiter des modifications pour améliorer l'optimisation si cela est une considération. Je suppose que vous voulez une sorte de moyen facilement lisible d'exprimer une commande qui allume et éteint une série de bits dispersés à travers plusieurs zones de la mémoire. La première chose est d'arriver à une représentation de ce à quoi ressemblerait une telle commande et il me semble qu'emprunter un tableau char
pour représenter une chaîne suffirait.
typedef byte RegPinNo; // upper nibble indicates register number 0 - 7, lower nibble indicates pin number 0 - 7
const byte REGPINNOEOS = 0xff; // the end of string for a RegPinNo array.
Et ceux-ci seraient utilisés pour définir un tableau de numéros de registre/broches comme suit.
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
Donc, à ce stade, nous avons un moyen de décrire un dispositif particulier, une LED dans ce cas, est abordée à travers une série d'éléments de numéro de registre/broches.
Ensuite, nous allons créer une petite bibliothèque de fonctions qui utilisera cette représentation pour modifier les broches spécifiques dans des registres spécifiques en parcourant cette matrice de numéros de registre/broche et en effectuant une opération sur le registre ou effacer le bit dans le registre.
typedef unsigned char byte;
typedef union {
byte Byte;
struct {
byte PTAD0 : 1;
byte PTAD1 : 1;
byte PTAD2 : 1;
byte PTAD3 : 1;
byte PTAD4 : 1;
byte PTAD5 : 1;
byte PTAD6 : 1;
byte PTAD7 : 1;
} Bits;
} PTADSTR;
// Define a pointer to the beginning of the register area. This area is composed of
// 8 different registers each of which is one byte in size.
// We will address these registers as Register 0, Register 1, ... Register 7 which just happens
// to be how C does its zero based indexing.
// The bits representing pins on the PCB we will address as Pin 0, Pin 1, ... Pin 7.
extern volatile PTADSTR (* const _PTAD) = 0x00000000;
void SetRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte |= pins[bPinNo];
}
}
void ClearRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte &= ~pins[bPinNo];
}
}
void ToggleRegPins(RegPinNo *x)
{
byte pins[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 4) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0x07; // get the pin number, 0 - 7
_PTAD[bRegNo].Byte ^= pins[bPinNo];
}
}
Vous utiliseriez ce qui précède comme suit. Je ne sais pas à quoi ressemblerait une fonction de temporisation dans votre environnement, donc j'utilise une fonction Sleep()
qui prend un argument quant au nombre de millisecondes à retarder ou à mettre en veille.
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x01, 0x12, REGPINNOEOS }; // LED is addressed through Register 0, Pin 0 and Register 1, Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}
Edition - Un Raffinement
Une mise en œuvre plus efficace qui permettent à plusieurs broches à fixer dans un registre particulier en même temps serait de définir l'utilisation de RegPinNo
comme étant un court non signé `avec l'octet supérieur étant le numéro de registre et l'octet inférieur étant les broches à manipuler comme un masque de bits pour l'octet.
Avec cette approche, vous auriez une fonction SetRegPins()
qui ressemblerait à ceci. Un changement similaire serait nécessaire pour les autres fonctions.
void SetRegPins(RegPinNo *x)
{
int i;
for (i = 0; x[i] != REGPINNOEOS; i++) {
byte bRegNo = (x[i] >> 8) & 0x07; // get the register number, 0 - 7
byte bPinNo = x[i] & 0xFF; // get the pin mask
_PTAD[bRegNo].Byte |= bPinNo;
}
}
Et les typedefs ressembleraient:
typedef unsigned short RegPinNo; // upper byte indicates register number 0 - 7, lower byte provides pin mask
const byte REGPINNOEOS = 0xffff; // the end of string for a RegPinNo array.
Et ces éléments seraient utilisés comme:
void LightLed (int nMilliSeconds)
{
RegPinNo myLed[] = { 0x0002, 0x0103, REGPINNOEOS }; // LED is addressed through Register 0, Pin 1 and Register 1, Pin 0 and Pin 1 (zero based)
SetRegPins(myLed); // turn on the LED
Sleep(nMilliSeconds); // delay for a time with the LED lit
ClearRegPins(myLed); // turn the LED back off
}
Y at-il des adresses de mémoire qui sont mis en correspondance avec des registres particuliers? Par exemple l'adresse de mémoire 0x00000000 est mappée au registre 0 et l'adresse de mémoire 0x00000001 est mappée au registre 1 (en supposant des registres de 1 octet ou de 8 bits)? Je m'attendrais à utiliser la même structure 'PTADSTR' pour la définition, puis à créer un pointeur au début de la zone mémoire où se trouvent les registres et à les référencer comme un tableau de la structure' PTADSTR'. –
Vous ne pouvez pas avoir de pointeur sur un champ de bits. Regardez http://stackoverflow.com/questions/13547352/c-cannot-take-address-of-bit-field. –
@RichardChambers Je peux dire que plus loin dans la définition une structure PTADDSTR est définie à 0x00000001, puis PTBDSTR à 0x00000002, puis PTBDDSTR à 0x00000003 et ainsi de suite, et oui registres 8 bits, je suppose que cela répond à vos premières questions, mais je ne pas votre idée, créer un tableau avec des pointeurs sur les bits de chaque structure, dites-vous? – Hans