sábado, 25 de setembro de 2021

AVRIBE, O PROTÓTIPO FÁCIL

 Olha só, eu faço muito teste em breadboard, desse tipo abaixo, barra simples, dupla, tripla, o que precisar.  Já fiz muita coisa nesses boards, digital, analógica, e principalmente com microcontroladores.



Mas sempre que uso um microcontrolador, comumente um AVR (Atmel) tipo At90S2313 ou AtMega8, ou AtMega48 ou AtMega88, é um tal de espeta o chip e liga todos os fios e conector enjambrado para fazer a conexão com a gravação ISP, antes de qualquer outra coisa.  

Precisava algo mais prático.

Então resolvi fazer uma plaquinha “esperta” de desenvolvimento, que dou o nome de “AVRibe” (averibe) que contenha todo o necessário para o AVR rodar mesmo sem o uso do breadboard, e a ideia é espetar a “AVRibe” no breadboard só mesmo para ter os pinos de I/O e tensões ali disponíveis.

Ficou muito bom e recomendo algo assim para todos.

No do At90S2313 até instalei um segundo jumper de seleção de 5V e 3V, e para gerar os 3V soldei ao AVRibe uma bateria CR123A de 3V e que dura uma eternidade.   Eu quase não uso 3V, mas os displays de Celular da Nokia, tipo 3310, e alguns outros chips, como memória serial, etc, usam 3V e é um saco, então preparei o AVRibe do 2313 para tal.

 
Na plaquinha tem o soquete para o microcontrolador, cristal, regulador de 5V (7805), jumper de power, referência de 2.5V, LEDs indicativos e conector macho para o jack de uma simples fontezinha 9V 500mA. Claro que não podia faltar os 6 pinos do conector ISP para conectar o gravador USBASP.

No AVRibe abaixo, com o AtMega8, a construção foi a mesma do At90S2313, porém sem a bateria de 3V, mas contendo jack de power, regulador 7805, uma referência de 2.5V (LM385-2V5), botão de reset e jumper de power (servindo como switch), capacitores, indutor de filtro para o AVCC, etc.  

Note que eu uso barrinha de pinos na parte de baixo, para espetar no breadboard, e uso dois pinos a mais, um de cada lado, para também levar o 2.5V de referência e o segundo para reforçar o terra, e obviamente 6 pinos para o ISP de gravação via USBASP.

Com certeza absoluta eu deveria ter feito isso há muito tempo atrás.
Ah sim, essa coisa branca enrolada nos fios coloridos, é a própria capa do cabinho de onde os fios foram retirados, que foi cortada helicoidalmente com uma pequena tesoura, como descascar uma laranja… fica bom para juntar os fios, fácil de instalar e retirar sem remover os fios.






AtMega128 vs At89s8252 - Firmware

Pois é, estou desenvolvendo um firmware para uma máquina nova, usando o AtMega128 (Atmel) 16MHz com 256kBytes SRAM externa, 1MB Eeprom externa, etc, mas cada nova rotina deve ser testada, e para isso tem que gravar a Flash do AtMega toda vez… tá bom, a flash dele suporta 10 mil regravações, mas é um saco pensar nisso.   O AtMega128 que estou usando é um TQFP64 soldado na placa de teste, tá bom, é só dessoldar e meter outro, mas, é um saco pensar nisso.

Na época do 8051, usava-se eprom externa, que beleza.  Tinha que apagar, gravar, etc, demorava mais, até um dia eu fazer uma engenhoca com SRAM e um código minúsculo em eprom.  Na verdade fiz um bootloader, na época que nem se pensava nesse nome.  O código mínimo fazia o 8051 rodar a UART na velocidade mais alta possível aceita pelo PC e esse despejava o novo código a rodar via serial, o 8051 recebia, gravava na SRAM externa e ao final ele mesmo virava um flip-flop e substituía a eprom pela SRAM e o novo código entrava no ar.   Muito rápido e funcional.

Não dá para fazer isso com os AtMega, exceto com um novo chip AVR32 que permite rodar código de memória externa.

A grande vantagem de usar o AtMega128, com 128kBytes de Flash, é que me deixa respirar.   Escrevendo tudo em assembly, é claro, pois *não existe* nenhuma outra linguagem de programação que se possa considerar séria… rsrs… eu sempre me preocupo em reduzir código, reutilizar código, se o mesmo trecho será usado mais de uma vez – passa a ser subrotina, etc e tal.  Essa “neura” consome tempo, e sempre se pensa em fazer um grande código com uma memória flash minúscula.  Não é à toa que tudo o que eu já escrevi na vida, e tem coisa muito complexa, nunca passou de 7kBytes.   Mas agora, com 128kBytes de flash à disposição, eu respiro e a coisa mudou de cor e cheiro, agora eu não mais me preocupo em economizar espaço, nem de Flash, nem de SRAM, e agora eu deito e rolo, me preocupo sim com velocidade de processamento, e tenho medido tudo para garantir que nada mantenha o AtMega ocupado fora do razoável.

Para ter uma ideia, ainda estou na dúvida sobre controlar os displays de sete segmentos, 20 no total, com refresh de 100Hz do AtMega, usando chips 74HC595 e transistores, ou o Max7219, que faz o serviço de refresh sozinho, mas, a rotina do refresh para o HC595 toma só 3.5 microsegundos. Isso é nada, certo?  Simples, eu não faço o bit-bang de mandar bit a bit, eu uso o dispositivo interno do AtMega chamado SPI, é um tipo de serial que pode transmitir a velocidades altíssimas, de no máximo Clock/2, ou seja, 16MHz/2 = 8Mbps, eu soco o byte no registrador da SPI e ela faz o serviço sujo.  Ou seja, 3.5us a cada 10ms, é um overhead de somente 0.035%, com isso garanto que o AtMega estará 99.965% do tempo livre para outras coisas.

Então, com a nova liberdade de flash do AtMega128, hoje eu entendo porque muita gente não gosta de Assembly e prefere C, pois não precisa se preocupar muito com a maneira que o código final ficará, o tamanho dele, a performance, etc.  É mais fácil, mais livre e menos preocupante.

Agora, veja só.   Esse novo firmware que estou escrevendo, parti do scratch, reescrevendo algo que foi escrito para o At89S8252, um 8051 da Atmel, em 1997.  Já está 98% pronto, escrevi em torno de 5 mil linhas de código em assembly e comentários, em menos de 2 semanas, e está ocupando menos de 5kBytes de código, contra os 7k do 8051.

É estranho, que mesmo não me preocupando em economizar espaço, o que escrevo hoje fica menor que o anterior, e então penso, ou o mesmo tipo de código para o 8051 ocupa mais memória que os AVRs, ou depois de 16 anos eu aprendi naturalmente a escrever de forma mais produtiva e inteligente.  Creio que ambos.

O custo de um AtMega128 compensa, pois passa-se a ter 6 e meia portas de 8 bits, (mais de 50 pinos de I/O), 8 ADCs, alguns podendo ser programados para entrada complementar, duas USARTs, PWM de pancada, 128k de Flash, 4k de SRAM interna, 4k de eeprom interna e permite usar SRAM ou I/Os externos como o 8051 o fazia, e acessa-se esses I/Os ou memória externa como uma extensão da interna, maravilha, além de uma carrada de outros dispositivos internos disponíveis.  Ou seja, o AtMega128 vem carregado com tudo que pode, exceto USB e Ethernet.

Eu iniciei nos AVRs brincando com o At90S2313, depois passei para o AtMega8 e naturalmente sai matando o AtMega128.

Tudo bem que uma série de novos chips da concorrência rodam a mais de 50MHz e possuem muita flash, principalmente os novos ARMs da vida.

Mas é muito gostoso trabalhar com um AVR rodando a 16MHz (16 MIPS) e ver a coisa zunir bits à torto e direito.

SOMA e SUBTRAÇÃO em BINÁRIO

Atendendo a um amigo que pediu para explicar como multiplicar e dividir em assembly.

Gostaria de anunciar que o texto abaixo parece ser longo demais, e chato, mas foi assim feito para exatamente explicar tudo em detalhes, para você que quer aprender de uma vez por todas.  Prepare um bom tempo para ler esse assunto, relaxe e preste atenção, vale a pena.

Antes de mais nada é importante entender muito bem o sistema binário e hexadecimal, e vou explicar primeiro a somar e subtrair em binário, no próximo post veremos multiplicação e no outro divisão.

Pense nos 5 dedos da sua mão direita, com eles você pode contar de 1 a 5, é o que aprendeu na escola. Isso significa que pode contar 5 coisas, digamos, bananas.  Na verdade, consegue contar 6, se imaginar que com todos os dedos fechados pode significar a sexta ou a primeira banana.   Mas isso é só para dar partida na sua cabeça, tudo pode ser diferente.

Bem, então pense que eu posso fazer você contar 32 bananas só com os 5 dedos da mão direita. Opa, como é que é? Pois é, essa é a forma de contagem binária.

Vamos aproveitar para dar nomes e valores aos dedos da mão direita.

Mão direita – Nome do DedoValor do Dedo
Mínimo1
Anelar2
Médio4
Indicador168
Polegar16

Hmmm, veja que a partir do mínimo que vale “1″, os valores dos outros dedos são sempre o dobro do anterior.  Significa que ao levantar o polegar e fazer o “sinal de positivo”, está mostrando o numero 16.

Ao fazer o “V” de vitória com o indicador e médio, está mostrando 12, que é a soma deles (8 e 4).

Ao fechar o polegar e levantar os outros 4 dedos (como quem mostra o numero 4), em binário estará mostrando 15, que é a soma de 1+2+4+8.

Interessante, não?

Veja, o numero decimal 7 é representado pelos tres dedos, mínimo, anelar e médio. Para subtrair 2, basta fechar o dedo anelar (que vale 2) e ver o que restou levantado, o médio (4) e o mínimo (1), cuja soma é 5.

Bacana, não é? Pois é.  Isso é binário e pode-se fazer somas, subtrações e até multiplicações e divisões.

Quer ver? Faça o “V” de vitória, indicador e médio, que é 12 (8+4).
Dividir por 2 ?  basta mover esse “V” um dedo para a direita, vai levantar o médio e o anelar.  Quanto valem? 2 + 4 = 6… ora, 12 / 2 = 6.

Volte novamente a fazer o “V” da vitória, que é 12.  Agora vamos dividir por 4, ora, dividir por 4 requer deslocar o “V” duas posições para a direita, vai então fazer o “V” com o anelar e o mínimo.  Vale quanto? 1+2 =3

Ahaa… 12 / 4 = 3

Simples?  Pois é, então multiplicação é o contrário, ao multiplicar por 2 desloca o V para a esquerda um dedo, multiplicar por 4, desloca o V dois dedos, e por ai vai.

Hmmm, mas só dá para contar até 31 com uma mão ?  Sim, se incluir o zero (todos os dedos baixos) conta-se 32 movimentos.

Mas se usar a mão esquerda junto com a direita, sendo o polegar da esquerda então valendo o dobro do polegar da direita, 32, então o dedo mínimo da mão esquerda vai valer o máximo de todos os dedos, irá valer 512, vejamos:

DICA: Você pode até fazer anéis de papel e vesti-los nos dedos, cada um com o valor acima, para entender direitinho essa coisa de “binário”.

Uau, então se levantar só os dois polegares, estarei mostrando 32 + 16 = 48  em binário?  Sim, com só dois dedos, mostrará 48.

Note que o mínimo direito só vale “1″, mas é ele quem determina se a contagem binária dos dedos será “par” ou “impar”… até ele que vale menos é super importante.  Por outro lado, o mínimo esquerdo é o que tem mais valor, 512, por estar mais à esquerda de todos os outros dedos.

E se levantar os cinco dedos direitos, como dizendo “olá” para o amigo, está mostrando 16+8+4+2+1 = 31… e se levantar todos os dedos só da mão esquerda, estará mostrando 512 + 256+ 128 + 64 + 32 = 992, e se levantar todos os dedos das duas mãos, estará mostrando 1023.

Portanto, “Olá!!!” com a mão direita… 31, com a mão esquerda… 992

Okay, você está curioso.  E se a pessoa não tiver o mínimo da mão esquerda? bem, nesse caso ele só contará até 511, e só contará até a metade dos 1023 e o apelido “meia conta” poderá grudar nele.

Se estiver com todos os dedos levantados e deslocar isso um dedo para a direita, o que ocorre?
Obviamente que o dedo mínimo esquerdo (512) vai baixar, porque não existe nenhum dedo à esquerda dele para ser copiado para ele, mas todos os outros dedos movem para a direita, e todos continuarão levantados.  O que acontece com o mínimo direito (1) ao ser deslocado para a direita? ele some, porque não existe nenhum dedo à direita dele para copia-lo.   Então todos os dedos permanecem levantados, exceto o mínimo esquerdo (512), e agora temos 9 dedos levantados, que somando valem 511, exatamente o mesmo de todos os 10 dedos (1023) menos o 512 do mínimo da esquerda que baixou.

Opa, 511 é um a menos do valor 512 do mínimo esquerdo.  Certo, pois se somar um nessa conta dos nove dedos levantados, não existe lugar para esse “um” entrar e ele corre e levanta o mínimo esquerdo e derruba todos os 9 dedos que estavam lentados e a soma passa a ser 511+1 = 512.

Vamos esquecer os dedos e ver da forma binária, mas vamos só usar 4 bits (bits=dedos), e vamos dar nomes à esses bits, 8, 4, 2, 1.

 Bit  8  4  2  1
      —  –  —  –
      0  1  0  0  < Valor decimal 4, só o bit 4 está levantado
      1  0  1  1  < Valor decimal 11, 8 + 2 + 1
      1  0  0  0  < Valor decimal 0, nenhum bit levantado
      1  1  1  1  < valor decimal 15, todos os bits levantados

Que tal então darmos nomes diferentes para cada uma dessas combinações?  Veja, são 16 combinações e uma boa parte delas é conhecida, de zero a nove, mas ainda existem a 11, 12, 13, 14 e 15.   Para facilitar vamos nomear essas combinações acima de nove em A, B, C, D, E, F.   Então vai ficar assim:


HEXADECIMAL
8 4 2 1 < bits
– - – -
0 0 0 0 = 0
0 0 0 1 = 1
0 0 1 0 = 2
0 0 1 1 = 3
0 1 0 0 = 4
0 1 0 1 = 5
0 1 1 0 = 6
0 1 1 1 = 7
1 0 0 0 = 8
1 0 0 1 = 9
1 0 1 0 = A
1 0 1 1 = B
1 1 0 0 = C
1 1 0 1 = D
1 1 1 0 = E
1 1 1 1 = F

Muito bem, agora temos o nome desses numeros de zero a 15, que é de zero a F.

Parabéns, acabou de parender HEXADECIMAL, uma forma de contar de zero a 15 (F) com quatro bits.
Só para fixar, “A” + 1 é o que? é “B”, e 7 + 3 o que é? não é 10, é “A”, lembre-se, estamos falando de hexadecimal, e não mais decimal, okay?

A forma usual de representar um valor qualquer em hexadecimal é incluindo “0x“, ou “$” atrás do numero:

“5″ em hexadecimal pode ser representado assim:
0×5 ou 0×05 ou $5 ou $05

“5″ em binário é “0101″ e deve ser representado com “0b” atrás dos bits:
0b0101

“5″ em decimal pode ser representado basicamente como “5″, mas para evitar confusão usaremos “0d” atrás do numero:
0d05

Ah sim, “atrás” do número é do lado esquerdo, também chamado de “prefixo”, pois o que vem a frente é à direita do número, chamado de “sufixo”.

Okay, eu também não concordo com isso, mas já fui severamente acusado de usar isso errado.

Observe a combinação de bits, olhe o “E” e olhe o “7″.  Se deslocar o 7 um bit para a esquerda, ele vira “E”, e se deslocar o “C” uma vez para a direita? vira 6.  E se deslocar mais uma vez para a direita? vira 3.  E se deslocar mais uma vez para a direita? vira 1.  Ué? 3 dividido por 2 resulta em 1?  Pois é, não tem como representar meio bit, pois o certo seria 1,5 mas não dá.  Binário só conta inteiros, a menos que se defina isso diferente, verá isso mais a frente.

 Parabéns, já descobriu como dividir e multiplicar em binário…

 Opa, mas e se eu quiser multiplicar por 3 e não só por 2, 4, 8, etc?

O segredo está em somar resultados parciais.  Você faz o mesmo em decimal no papel e lápis. Mas isso veremos no próximo post desse blog, Multiplicando e Dividindo em Binário.


SOMA EM BINÁRIO
8 4 2 1  <–  Bits0 1 1 0  = 6
0 0 0 1  = 1 +
— — - - 

Okay, mas como somamos Bits?  É fácil, basta seguir uma regrinha simples que só usa “0″ e “1″.

0  +  0  =  0
0  +  1  =  1
1  +  0  =  1
1  +  1  =  10

Oooopa, 1+1 = 10? não seria 2 ?  Bem, seria “2” se fosse em decimal, mas aqui estamos somando em binário e binário só tem zeros e uns.  Lembre-se agora cada bit só pode ser representado por “0″ ou “1″. Lembre-se dos dedos levantados ou baixados.  

Para facilitar pense assim:

Binário     Decimal

00    =    0
01    =    1
10    =    2
11    =    3

Então vamos fazer a tal soma ai acima:

8 4 2 1  <–  Bits
— — - - 
0 1 1 0  = 6 
0 0 0 1  = 1 + 
- – - - 
      1 = 0 + 1 
    1   = 1 + 0
  1     = 1 + 0 
0       = 0 + 0 
- – - – baixando e somando tudo 
0 1 1 1 = 7

Esse foi fácil, vamos complicar?

8 4 2 1  <–  Bits 
— — - - 
0 1 1 0  = 6    (Bits da Linha de Cima)
0 0 1 0  = 2 +  (Bits da Linha de Baixo)
- – - –  
      0 = 0 + 0  (Bit1C + Bit1B)
  1 0   = 1 + 1  (Bit2C + Bit2B) ocorreu “vai um”
  1     = 1 + 0  (Bit4C + Bit4B)
0       = 0 + 0  (Bit8C + Bit8B)
- – - – baixando e somando tudo 
1 0 0 0 = 8

Ooopa, que raios é Bit4C ???

Vamos fazer uma convenção aqui.

A soma aí acima tem 4 bits, 8, 4, 2 e 1, vamos chamar cada coluna dessa de Bit8 Bit4 Bit2 e Bit1. Como estamos lidando com duas linhas, vamos chama-las de linha de cima e linha de baixo, então teremos Bit8C, Bit4C, Bit2C e Bit1C (os quatro bits de cima), e BIt8B, Bit4B, Bit2B, Bit1B (os quatro bits de baixo), e também teremos os quatro bits do resultado, Bit8R, Bit4R, Bit2R e Bit1R.
Se fossemos falar em voz alta a soma acima, seria assim, começando pela direita para a esquerda:

(Bit1C + Bit1B) Zero mais Zero igual a zero, (Bit2C + Bit2B) um mais um é igual a zero e “vai um” à esquerda, esse “vai um” é somado com os Bit4C + Bit4B, então, UM (que foi), mais um (Bit4C), mais zero (Bit4B), igual a zero e “vai um” à esquerda, que quando somado com os zeros (Bit8C + Bit8B); o UM (que foi), mais zero, mais zero, é UM, que aparece embaixo como Bit8R.

Soma em binário é bem simples, basta pegar a idea.


SUBTRAÇÃO EM BINÁRIO

Subtração é exatamente o inverso, vejamos:

8 4 2 1  <–  Bits
— — - -
0 1 1 0  = 6
0 0 0 1  = 1 –
- – - -

Vamos olhar como se olha em subtrair em decimal.  O Bit1B deverá ser subtraido do Bit1C, mas não dá para subtrair um de zero, então empresta-se o próximo bit à esquerda na linha de cima (Bit2C), então estaríamos subtraindo o valor “1″ (Bit1B) dos dois bits valor “1″ e “0″ (Bit2C Bit1C) da linha de cima, veja:

8 4 2 1  <–  Bits
— — - -
0 1 1 0  = 6
0 0 0 1  = 1 –
- – - -

Agora dá, pois “1 0” em binário, (Bit2C e Bit1C), significa “2″ em decimal, e o valor “1″ (Bit1B) pode ser subtraido.

Então binário “10 – 1″  é o que?
Veja, “10″ em binário é “2″ em decimal, certo?  Então, em decimal 2-1 = 1, okay?
Então, em binário “10 – 1″ = “1″
Ficou claro? para ir em frente isso TEM que ficar claro.

Então o valor binário “1”  (Bit1B) subtraindo do valor binário “10” (Bit2C Bit1C) resulta em valor binário “1″ (Bit1R), mas emprestou um da esquerda, lembre-se disso, exatamente como se faz em decimal, e fica assim:

8 4 2 1  <–  Bits
— — - -
0 1 1 0  = 6
0 0 0 1  = 1 –
- – - –
      1

Agora, o um emprestado é somado na nossa mente na posição certa, (Bit2B), ficando assim:

8 4 2 1  <–  Bits
— — - -
0 1 1 0  = 6
0 0 1 1  = 1 –
- – - –  
    0 1

Então, agora os dois Bit2C e Bit2B, valor binário “1“,  se anulam, e sobra zero em Bit2R.

O resto vai fácil, os dois bits4, 1 – 0 = 1 e zero – zero (os dois bits 8) = 0, o que resulta em:

8 4 2 1  <–  Bits
— — - -
0 1 1 0  = 6
0 0 0 1  = 1 –
- – - –  
0 1 0 1 = 5

Opa, 6 – 1 = 5.  Simples, não?

Bem, creio que deu para entender, no próximo post veremos multiplicação e divisão.