Pergunta

Eu quero saber o que acontece quando nós escrevemos "0" para um GPIO (a intenção real é para puxar para baixo a saída).

Eu não tenho certeza se o controlador de puxa para baixo o GPIO pin e liga-se internamente para a terra ou ele simplesmente desliga o pino internamente e faz com que ele desconectado do periférico (LED) conectado a ele a partir do micro controlador.

A tarefa real para mim é:

Eu tenho que enviar a um 8 bits de dados a partir de 4 pinos gpio(Ex PORTA4-7).Então, para fazer isso eu tenho que escrever o maior bits(D4-D7) então (D0-D3).

Minha abordagem é:

% Writing the higher bits first
PORTA=PORTA|(DATA & 0xF0);

%Writing the lower bits
PORTA=PORTA|((DATA & 0x0F)<<4);

A principal dúvida é "Será que este pedaço de código perturbar os restantes GPIO (PORTA0-3)".Porque eu estou conectando-los para 4 ADC entradas.

Foi útil?

Solução

A melhor maneira de entender como GPIO são acoplados é apenas de visitar a folha de dados.TI as plataformas msp430 da folha de dados são um excelente exemplo.

A Entrada/Saída secções têm muito explícita ilustrações sobre como o GPIO registra interagir com o IO Almofadas de si.Aqui é a Porta P1.0-P. 17 (a partir da página 80 de Folha de dados acima).

enter image description here

Saídas

O básico vantagem aqui é que:

  • Escrever um '0' para P1OUT.x (e.g bit0 é P1OUT.0) unidade de saída baixa, se a IO pad estiver no modo output.

Aqui é uma simples versão reduzida do que:

enter image description here

Entradas

Da mesma forma, aqui está uma inspeção de utilizar o e / s bloco de 'entrada' modo de

enter image description here

O básico vantagem aqui é que a escrita para P1OUT.x aqui não tem nenhum efeito sobre a saída;o buffer de saída é tri-afirmou!

Perigos

Se o seu programa de ações de uma única porta GPIO-registrar entre várias tarefas, você deve garantir o acesso a este cadastro é thread-safe.Para sistemas embarcados geralmente, isso significa apenas 'certifique-se de ISRs não vai estragar as coisas".Considere -

//... (from main thread)
P1OUT = P1OUT | 0x02;

//... (from some ISR)
P1OUT = P1OUT | 0x01;

isso geralmente se traduz da seguinte desmontagem

//... (from main thread)
mov  P1OUT,  %some_reg
operate on %some_reg
mov   %some_reg, P1OUT

//... (from some ISR)
mov  P1OUT,  %some_reg
operate on %some_reg
mov   %some_reg, P1OUT

//and then the time series looks like   (P1OUT = 0 initially)
[0]:  mov P1OUT,  %some_reg_main_thread  (%reg_m = 0)
[1]:  or  0x02,   %some_reg_main_thread  (%reg_m = 2)
[2]:  ISR fires!
[3]:  mov P1OUT,  %some_reg_isr_thread   (%reg_i = 0)
[4]:  or  0x01,   %some_reg_isr_thread   (%reg_i = 1)
[5]:  mov %some_reg_isr_thread, P1OUT    (P1OUT  = 1)
[6]:  ISR exits
[7]:  mov %some_reg_main_thread, P1OUT   (P1OUT  = 2)

(end result: P1OUT=2, but should be 3 (0x01 | 0x02))

Também, IO Almofadas não são tão simples como parecem, e você deve sempre visitar a folha de dados para compreender o quão ruim/delicado/confuso/etc é.

Por exemplo, na TI exemplo acima, os seguintes perigos de aplicar à sua pergunta original:

(enquanto P1DIR.x = 0)

  • P1REN.x + P1OUT.x

    • se P1REN.x é '1', e você alternar P1OUT.x, que alterna a resistência pullup e fora também

enter image description here

Claro, IO pad topologias são MCU específicas.Eu recomendo a revisão IO-Pad topologia em sua folha de dados antes de avançar no seu projeto.Ele deve ser o seu melhor amigo.

Código De Práticas

Considere usar o |=, &= e ^= operadores quando você pode, por exemplo:

P1OUT |= (1<<2)+(1<<3)   //assert pin2 & pin3 high

e quando não for possível, considere a utilização de refeições de estruturas, ou unidade-testado encapsulamento de rotinas:

struct myporta {
    uint    b3_0    : 4;     //use unsigned int-type
    uint    b4      : 1;
    uint    b5_10   : 6;
    uint    b25_b11 : 15;
    uint    b26     : 1;
    uint    b31_27  : 5;
} __attribute__ ((packed));  //gcc syntax

...
//write to my LED
myporta *porta = &PORTA;   //if you w

porta->b26 = 1;            //turn the led on

nada é pior do que gpio clobbering um do outro!

Outras dicas

O MCU vai dirigir ativamente o pino de baixo, você pode pensar nele como o pino de aterramento, mais informações aqui.

PORTA=PORTA|(DATA & 0xF0);

Isto não irá afetar a 4 pinos inferiores, mas ainda não é o correto.Se a PORTA já está alta e dados contém zeros, você não vai dirigir os pinos de baixo.Você deseja mascarar as partes relevantes de DADOS e você deseja preservar a parte da PORTA que você não está mudando:

PORTA = (PORTA & 0x0F) | (DATA & 0xF0);

e, em seguida, da mesma forma para a configuração de 4 lsb:

PORTA = (PORTA & 0xF0) | (DATA & 0x0F);

Sim, escrever para PORTA vai perturbar todos os bits, mesmo se alguns deles são designados entradas com DDRA.

Você precisará certificar-se de que você não está escrevendo para o maior bits enquanto estiver a tomar ADC leituras de bits inferiores.

Mesmo algo como

% Writing the higher bits first
PORTA=PORTA|(DATA & 0xF0);

%Writing the lower bits
PORTA=PORTA|((DATA & 0x0F)<<4);

não vai funcionar.A leitura da PORTA do lado direito da atribuição que vai ter algum valor para os seus alfinetes, 0 ou 1, mesmo se a tensão está em algum lugar no meio.Que valor terá, então, ser escrito para o mesmo pin, dirigindo-alta ou baixa momentaneamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top