Busque no blog

quinta-feira, 25 de julho de 2013

Zilog - ZDSII a IDE de programação free em C. - 3ª Parte

Zilog - Acendendo um LED com Z8 encore XP! - Parte 3 




Configurando as PORTAS do Z8 Encore corretamente.

          Vamos continuar nossa série com uma implementação mais completa e mais avançada. Nesta parte vamos falar de operações lógicas que facilitam a vida de programadores C que é a operação de mudar bits individualmente ou em bytes para mudar o status de um pino ou bit de algum registrador, o que facilita e muito no uso de registradores como I/Os em modo geral e em função alternativa.
          Observe a tabela a seguir, com relação a manipulação de bits com operação lógica e
aritmética :



( & ) AND
( | ) OR
BIT1
0
1
0
1
0
1
0
1
BIT2
0
0
1
1
0
0
1
1
RESULTADO
0
0
0
1
0
1
1
1
          Neste caso, BIT1 tem 4 bits e em hexadecimal tem valor 5 e o BIT2, tem valor em hexadecimal de 3. Lembrando que de 0 a 9 os valores decimais e hexadecimais são os mesmos. A simbologia ( ~ ) em qualquer bit representa um complemento 2 que é inverter o sinal do bit. 
          Nesta terceira parte, vamos manipular bits e bytes. Nosso foco maior será com bits.
          Esta parte do artigo é necessária para compreender como é mais seguro e cômodo usar manipulação binária para um ou quais bits específicos sem comprometer os demais bits que não queremos mexer. 

          Controlando e configurando BIT0 do port A 

          Vamos começar com um pequeno circuito composto com um LED de 3.3V e um resistor de 100R em série para mostrar ligados ao pino PA0 do port A, siga o circuito e faça as modificações conforme exemplo para ver o LED acender e permitir que só este seja manipulado, deixando os demais sem manipular. 

          Vamos abrir o ZDSII e criar um novo programa para a linha Z8F0822 e criar um arquivo com o nome que achar pertinente e copie e cole ou reescreva nesse arquivo as linhas de código a seguir : 
          
          # include
         void main(void)
                                   {
                                    PAOUT = 0x01 ;  // zeramos os pinos do port A. 
                                    PAADDR = 4 ;    // habilita o modo alta corrente.Registro PHDEx.
                                    PACTL =  0x01 ; //  mas selecionamos o PA0 somente nesse modo
                                    PAADDR = 1 ; // selecionamos o registro de direção de dados DDx, 
                                    PACTL = 0xFE ; // 0xFE = 11111110b - 0 é saída e 1 é entrada.
                                    PAADDR = 0x00 ; //desligamos qualquer função extra por segurança.
                                    
                                    PAOUT = 0x00 ; port A em zero.
                                    PAOUT = 0x01 ; Somente pino PA0 em nível alto. 
                                    return ; 
                                   }
          
          Aqui foi iniciado o port A, pino PA0 em nível um, justamente para poder manter o LED nesse pino desligado e permitir fazer as  devidas configurações nos demais pinos. Configuramos o pino no modo alta corrente que é o mesmo que manipular o registro PHDEx, onde x é um valor de 0 a 7 selecionável pelo registro PAADDR e manipulado com valores impressos por PACTL. Depois definimos a direção dos dados, com o pino PA0 como saída colocando o bit 0 do registrados DDx em zero, onde x é um valor de 0 a 7. 
          Para acessar o registrador DDx, usamos valores em hexadecimal, com valor de 0xFE que, em binário é o mesmo que 11111110b, notamos que o registro DDx tem o bit zero em DD0 com valor zero, ou seja, em modo saída. 
          Colocamos PAADDR = 0x00 por último para proteger o microcontrolador de qualquer configuração acidental. 
          No final, colocamos PAOUT em 0, acendendo o LED e em seguida em um, apagando o LED. 
          Salve, compile e baixe para o microcontrolador o programa compilado. Se perceber, é provável que seu LED não acenda, não se preocupe, isso é normal, vamos resolver isso a seguir nos próximas linhas. Porém se usar o conceito de breakpoint no programa, poderá ver que o LED, na teoria, acende e apaga nas últimas linhas. 
          Toda vez que formos mudar o nível lógico desse pino, estaremos mudando também dos demais pinos simplesmente manipulando eles em bytes. Para que isso não ocorra teremos de usar recursos da linguagem C para manipular apenas o bit que queremos e para isso vamos dispor da tabela acima, dada no início deste artigo.
           Na tabela temos o BIT1, BIT2 e resultado. demos um valor de 0101b ( 0x05 em hexa) e 0011b ( 0x03 em hexa ) assim, fizemos uma operação lógica AND (& ) tendo como resultado 0001b ( 0x01 em hexa ) e outra operação lógica OR ( | ), tendo como resultado o valor 0111b ( 0x07 em hexa).
          Nessa linha podemos fazer uso de operações lógicas para mudar bits individuais de registros e portas com os operadores & e | , que são, respectivamente, os símbolos de AND e OR. Não confundir com os operadores lógicos de bytes && e || , que são AND e OR entre bytes e não entre bits individuais. 
          No exemplo a seguir vamos usar uma das formas de manipular os bits do pino PA0 sem mexer nos demais, usando o conceito de operação lógica.

          {
           unsigned char temp; // criamos uma variável de nome 'temp'.
           temp = PAOUT ; // colocamos os valores de PAOUT em tempo.
           temp = temp | 0x01 ; // fazemos um OR com 00000001b e recolocamos em temp.
           PAOUT = temp ; // colocamos em PAOUT os valores de temp. 
          }

          Lemos o port A e colocamos seu valor em 'temp', logo depois fazemos um OR lógico com um valor binário de 0001b com temp e recolocamos o resultado em temp, depois recolocamos em PAOUT. 
          Como podemos ver, para manipular um bit do port A temos de escrever quatro linhas de código, o que seria dispendioso para um programa mais elaborado, então usamos uma maneira mais eficiente e com o mesmo resultado, só escrevendo : 

        {
         PAOUT = PAOUT | 0x01 ; 
        }

          Ou muito mais eficiente ainda, podemos usar os recursos da linguagem C : 

          {
           PAOUT |= 0x01 ; 
          }

          Agora que aprendemos a usar a operação lógica para manipular bits, podemos reescrever nosso código que foi apresentado no início de uma maneira mais eficiente e ter um código mais enxuto e rápido na compilação do mesmo. Assim, podemos ter o que se segue : 

          #include  
          void main (void) 
                           {
                             PAOUT = 0x01; // colocamos o bit 0 em um.
                             PAADDR = 4 ; // selecionamos modo de saída de alta corrente     
                             PACTL |= 0x01 ; // selecionamos apenas o PA0 como alta corrente, colocando o registro PHDE0 em um.
                             PAADDR = 1 ; // selecionamos o registro de direção de dados.
                             PACTL &= ~0x01 // colocamos apenas o PA0 como saída, deixando os demais como estão. 
                             PAADDR = 0x00 ; // desativamos o registrador PACTL para não haver configuração acidental. 
                             PAOUT &= ~0x01 ; // zeramos o bit PA0 e acendemos o LED.
                             PAOUT |= 0x01 ; // setamos o bit PA0 e apagamos o LED.
                             return ; 
                            } 

           Com isso, ainda não conseguimos acender nosso LED no mundo físico, porém, conseguimos ver as mudanças de valores de bits na simulação dentro do programa com breakpoints. Se você não sabe debugar programas com o uso de breakpoints, sugiro ler a documentação referente ao ZDSII e o microcontrolador que esteja utilizando.
          Com o que aprendeu, faça alterações para ver o que acontece. Para fazer nosso LED piscar no mundo real, vamos agora criar uma função chamada atraso para controlar o tempo de acender e apagar o LED e ver nosso programa funcionar. 

   Controlando o tempo de piscar do LED.

          Desde o primeiro momento o termo usado era piscar led e até agora não vimos isso de verdade e foi de propósito para que pudéssemos passar o máximo de conhecimento a fim de ter ferramentas de manipulação de dados e ter um trabalho eficiente. 
          
          #include
         void main ( void ) 
                                {
                                     PAOUT |= 0x01 ; // colocamos o pino PA0 em um para apagar o LED.
                                     PAADDR = 4 ; // selecionamos modo alta corrente. 
                                     PACTL |= 0x01 ; // selecionamos apenas o pino PA0 nesse modo. 
                                     PAADDR = 1 ; // selecionamos o modo de direção dos dados 
                                     PACTL &= ~0x01 ; // colocamos o pino PA0 como saída. 
                                     PAADDR = 0x00 ; // evita configuração acidental 

                     while ( 1 )
                                    {
                                     atraso() ; 
                                     PAOUT &= ~0x01 ; // zera o bit PA0 e acende o LED
                                     atraso() ; 
                                     PAOUT |= 0x01 ; // seta o bit PA0 e apaga o LED.
                                    }
                    return ; 
                                 }

          Desde que a constante seja 1 sempre, while ( 1 ), o valor do pino PA0 muda a cada tempo o que permite apagar e acender nesse tempo de atraso().  Agora vamos escrever, logo depois de main() a função atraso(). Para achar o valor de contador basta usar contador = (atraso em segundos) * (frequência de clock em Hz)/86, pois while() leva 86 ciclos de clock, assim, 0.25 segundos são achados por contador = 0.25 * 20000000/86 o que dá, para um micro com 20Mhz de cristal, um valor de contador = 58139

          static void atraso (void)
                                            {
                                             unsigned int long contador = 58139 ; 
                                                     while (contador > 0 ) 
                                                                      {
                                                                        contador -= 1 ; 
                                                                       }
                                              return ; 
                                            }
  
          Assim teremos o programa completo e pronto para ser compilado e transferido ao microcontrolador e, aí sim, conseguimos ver nosso LED piscar como prometido, mas tinhamos que prover ferramentas que facilitassem a compreensão de todo o processo. Pegue o programa abaixo, salve, compile e transfira. 

  #include
        void atraso(void) ;
         void main ( void ) 
                                {
                                     PAOUT |= 0x01 ; // colocamos o pino PA0 em um para apagar o LED.
                                     PAADDR = 4 ; // selecionamos modo alta corrente. 
                                     PACTL |= 0x01 ; // selecionamos apenas o pino PA0 nesse modo. 
                                     PAADDR = 1 ; // selecionamos o modo de direção dos dados 
                                     PACTL &= ~0x01 ; // colocamos o pino PA0 como saída. 
                                     PAADDR = 0x00 ; // evita configuração acidental 

                     while ( 1 )
                                    {
                                     atraso() ; 
                                     PAOUT &= ~0x01 ; // zera o bit PA0 e acende o LED
                                     atraso() ; 
                                     PAOUT |= 0x01 ; // seta o bit PA0 e apaga o LED.
                                    }
                    return ; 
                                 }
          
static void atraso (void)
                                            {
                                             unsigned int long contador = 58139 ; 
                                                     while (contador > 0 ) 
                                                                      {
                                                                        contador -= 1 ; 
                                                                       }
                                              return ; 
                                            }

          Terminamos aqui a nossa parte de fazer um LED piscar, esperamos poder ter mais exemplos de uso dos periféricos do microcontrolador Z8 encore!, especialmente a linha Z8F0822, que é nosso foco neste artigo e que é aplicável para as outras linhas dessa empresa. 
Até a próxima e muito obrigado, nobres leitores. 

Nenhum comentário:

Postar um comentário