Sunday 22 October 2017

Arduino Shift Out Binary Options


Este projeto envolve a decodificação de um número de entradas (neste caso 7) para exibir como valores numéricos em um Sete Segmento Display (SSD) usando algo chamado Binary Coded Decimal (BCD), um Diode Matrix e um micro - chip chamado BCD4511 (ou CD4511). Eu tive uma curva de aprendizagem muito íngreme com este projeto e eu explorei um número inteiro de opções diferentes, incluindo o uso do meu Arduino com shift-in e shift-out registros para conservar pinos de E / S. No entanto, no final, eu encontrei esta solução para ser mais robusto e eu queria reunir todas as informações úteis que eu reuni durante a minha pesquisa para que outros possam ter um trabalho mais fácil em fazer o mesmo. Etapa 1: Diode Matrix Mostrar todas 2 imagens Eu queria fazer uma exibição de posição de engrenagem para a minha moto como Ill ser descascando o conjunto do painel existente como parte de convertê-lo em uma bicicleta de corrida. A moto tem um interruptor dentro da caixa de engrenagens que aterra um dos sete pinos de cada vez para indicar qual engrenagem (ou neutro) é selecionado. Isso tudo é bom e bom, mas conectar esses leads diretamente aos pinos de um SSD criaria uma bagunça que inevitavelmente hospedaria erros de sobreposição, como partes de uma conexão seria curta para outra e começaria a exibir uma combinação do Número 1 e 2 e assim por diante. Entre na Diode Matrix. Este filhote de cachorro obtém em torno dos erros causados ​​por ter de conectar segmentos do SSD juntos, e permite que cada conexão aterrada (ou entrada) para exibir apenas as partes do SSD que você deseja. No começo eu estava indo para usar apenas a matriz de diodo para conduzir o SSD, mas se você contar os diodos necessários na foto sua cerca de 33 (forma muito solda para o meu gosto). Então é aqui que o micro chip BCD4511 e Binary Coded Decimal (BCD) entram em play. Arduino powered 7 seg LED display usando Shift Registers - Eu fiz isso no TechShop Sete exibições segmentadas são grandes. Eles são bastante simples, não têm muito poder, e têm muita flexibilidade quando se trata de exibir números. Mas reservando 14 pinos apenas para executá-lo é uma dor. Se só houvesse uma maneira de usá-los sem sacrificar tantos pinos preciosos. Acontece que há Shift Registers são ICs lógicos que podem armazenar ou deslocar dados enviados para eles. Eles só pegar três pinos Combine isso com a função arduino quotShiftOutquot e há muito mais opções de repente aberto. Oh, e mais uma grande coisa. Eles podem ser encadeados juntos para ter ainda maior flexibilidade e ainda apenas usando três pinos. Apenas uma outra das muitas coisas que eu fiz no TechShop hoje. Bit Math Tutorial por CosineKitty Introdução Muitas vezes, quando a programação no ambiente Arduino (ou em qualquer computador, para esse assunto), a capacidade de manipular bits individuais se tornará útil Ou mesmo necessário. Aqui estão algumas situações em que a matemática de bits pode ser útil: Salvando memória, compactando até 8 valores de dados verdadeiros / falsos em um único byte. Ativação / desativação de bits individuais em um registro de controle ou registro de porta de hardware. Executando certas operações aritméticas envolvendo a multiplicação ou divisão por potências de 2. Neste tutorial, primeiro exploramos os operadores bit a bit básicos disponíveis na linguagem C. Em seguida, aprendemos a combiná-los para realizar certas operações úteis comuns. O sistema binário Para explicar melhor os operadores bit a bit, este tutorial irá expressar a maioria dos valores inteiros usando a notação binária, também conhecida como base dois. Neste sistema, todos os valores inteiros usam apenas os valores 0 e 1 para cada dígito. É assim que praticamente todos os computadores modernos armazenam dados internamente. Cada 0 ou 1 dígito é chamado um bit. Abreviação de dígito binário. No sistema decimal familiar (base dez), um número como 572 significa 510 2 710 1 210 0. Da mesma forma, em binário um número como 11010 significa 12 4 12 3 02 2 12 1 02 0 16 8 2 26. É crucial que Você entende como o sistema binário funciona para seguir o restante deste tutorial. Se você precisar de ajuda nesta área, um bom lugar para começar é o artigo da Wikipédia sobre o sistema binário. Infelizmente, a maioria dos compiladores C não tem qualquer meio de expressar números binários diretamente no código-fonte. Alguns permitem que o prefixo 0b seguido por uma série de 0 e 1 dígitos, e. 0b11 3. O compilador C utilizado pelo Arduino não suporta esta sintaxe. No entanto, a partir de Arduino 0007, as constantes B0 a B11111111 são definidas para sua conveniência. Bitwise AND O operador AND bit a bit em C é um único ampersand, amp. Usado entre duas outras expressões inteiras. AND bitwise opera em cada posição de bit das expressões circundantes de forma independente, de acordo com esta regra: se ambos os bits de entrada são 1, a saída resultante é 1, caso contrário a saída é 0. Outra forma de expressar isso é: No Arduino, o tipo int É um valor de 16 bits, portanto, usar amplificador entre duas expressões int faz com que 16 operações simultâneas AND ocorram. Em um fragmento de código como: Cada um dos 16 bits em aeb são processados ​​usando o AND bit a bit, e todos os 16 bits resultantes são armazenados em c. Resultando no valor 01000100 em binário, que é 68 em decimal. Um dos usos mais comuns de AND bit a bit é selecionar um bit particular (ou bits) a partir de um valor inteiro, muitas vezes chamado de mascaramento. Por exemplo, se você quiser acessar o bit menos significativo em uma variável x. E armazenar o bit em outra variável y. Você poderia usar o seguinte código: Bitwise OU O operador OR bit a bit em C é o símbolo de barra vertical,. Como o operador de amplificador, opera independentemente cada bit em suas duas expressões inteiras circundantes, mas o que ele faz é diferente (é claro). O bitwise OR de dois bits é 1 se um ou ambos os bits de entrada é 1, caso contrário, é 0. Em outras palavras: Aqui está um exemplo do OR bit a bit usado em um snippet de código C: Bitwise OR é freqüentemente usado para Certifique-se de que um determinado bit está ativado (definido como 1) em uma determinada expressão. Por exemplo, para copiar os bits de a em b. Ao certificar-se que o bit mais baixo está definido como 1, utilize o seguinte código: XOR Bitwise Existe um operador um pouco incomum em C chamado OR exclusivo bit a bit. Também conhecido como XOR bit a bit. (Em inglês, este é normalmente pronunciado eks-or.) O operador bit-bit XOR é escrito usando o símbolo de circunferência. Este operador é semelhante ao operador OR bit a bit. Exceto que ele é avaliado em 1 para uma determinada posição quando exatamente um dos bits de entrada para essa posição é 1. Se ambos são 0 ou ambos são 1, o operador XOR é avaliado em 0. Outra maneira de olhar para XOR bit a bit é que cada bit No resultado é um 1 se os bits de entrada são diferentes, ou 0 se eles são os mesmos. Aqui está um exemplo de código simples: O operador é freqüentemente usado para alternar (ou seja, mudar de 0 para 1, ou 1 para 0) alguns dos bits em uma expressão inteira, deixando os outros sozinhos. Por exemplo: Bitwise NOT O operador bitwise NOT em C é o caractere til. Ao contrário de amp e. O operador NOT bitwise é aplicado a um único operando à direita. Bitwise NOT muda cada bit para o seu oposto: 0 torna-se 1 e 1 torna-se 0. Por exemplo: Você pode se surpreender ao ver um número negativo como -104 como resultado desta operação. Isso ocorre porque o bit mais alto em uma variável int é o bit de sinal chamado. Se o bit mais alto for 1, o número é interpretado como negativo. Esta codificação de números positivos e negativos é referida como twos complemento. Para obter mais informações, consulte o artigo da Wikipédia sobre o complemento de dois. Como um aparte, é interessante notar que para qualquer inteiro x. X é o mesmo que - x-1. Às vezes, o bit de sinal em uma expressão inteira assinada pode causar surpresas indesejadas, como veremos mais adiante. Operadores de deslocamento de bit Existem dois operadores de deslocamento de bit em C: o operador de deslocamento esquerdo ltlt eo operador de deslocamento de direita gtgt. Esses operadores fazem com que os bits no operando esquerdo sejam deslocados para a esquerda ou para a direita pelo número de posições especificadas pelo operando direito. Por exemplo: Quando você muda um valor x por y bits (x ltlt y), os bits y mais à esquerda em x são perdidos, literalmente deslocados para fora da existência: Se você está certo de que nenhum dos valores em um valor estão sendo deslocados para o esquecimento , Uma maneira simples de pensar no operador do lado esquerdo é que ele multiplica o operando esquerdo por 2 elevado à potência operando direita. Por exemplo, para gerar potências de 2, as seguintes expressões podem ser empregadas: Quando você muda x para a direita por y bits (x gtgt y) eo bit mais alto em x é a 1, o comportamento depende do tipo exato de dados de x . Se x é do tipo int. O bit mais alto é o bit de sinal, determinando se x é negativo ou não, como discutimos acima. Nesse caso, o bit de sinal é copiado em bits mais baixos, por razões históricas esotéricas: Esse comportamento, chamado extensão de sinal. Muitas vezes não é o comportamento que você quer. Em vez disso, você pode desejar que os zeros sejam transferidos da esquerda. Acontece que as regras de deslocamento à direita são diferentes para as expressões int não assinadas, então você pode usar um typecast para suprimir as que estão sendo copiadas da esquerda: Se você for cuidadoso para evitar a extensão de sinal, pode usar o operador shift direito gtgt como Maneira de dividir por potências de 2. Por exemplo: Operadores de atribuição Muitas vezes na programação, você deseja operar sobre o valor de uma variável x e armazenar o valor modificado de volta em x. Na maioria das linguagens de programação, por exemplo, você pode aumentar o valor de uma variável x por 7 usando o código a seguir: Como esse tipo de coisa ocorre com freqüência na programação, C fornece uma notação abreviada na forma de operadores de atribuição especializados. O fragmento de código acima pode ser escrito de forma mais concisa como: Acontece que bit a bit AND, bitwise OR, deslocamento à esquerda e deslocamento à direita, todos têm operadores de atribuição abreviada. Aqui está um exemplo: Não há operador de atribuição abreviada para o operador bitwise NOT se você deseja alternar todos os bits em x. Você precisa fazer isso: Uma palavra de cautela: operadores bit a bit versus operadores booleanos É muito fácil confundir os operadores bit a bit em C com os operadores booleanos. Por exemplo, o amplificador de operador AND bit a bit não é o mesmo que o amplificador booleano do operador AND. Por duas razões: Eles não calculam números da mesma maneira. O amplificador Bitwise opera independentemente em cada bit em seus operandos, enquanto o ampamp converte ambos os seus operandos para um valor booleano (verdadeiro 1 ou falso 0) e retorna um único valor verdadeiro ou falso. Por exemplo, 4 amp 2 0. porque 4 é 100 em binário e 2 é 010 em binário, e nenhum dos bits é 1 em ambos os inteiros. No entanto, 4 ampamp 2 verdadeiro. E verdadeiro numericamente é igual a 1. Isso ocorre porque 4 não é 0 e 2 não é 0, portanto ambos são considerados como valores verdadeiros booleanos. Os operadores bit a bit sempre avaliam ambos os seus operandos, enquanto os operadores booleanos usam a chamada avaliação de atalho. Isso só é importante se os operandos tiverem efeitos colaterais, como fazer com que a saída ocorra ou modificar o valor de outra coisa na memória. Aqui está um exemplo de como duas linhas de código semelhantes podem ter comportamento muito diferente: Se você compilar e fazer o upload desse programa e, em seguida, monitorar a saída serial da GUI do Arduino, verá as seguintes linhas de texto repetidas a cada segundo: É porque tanto fred (0) como fred (1) são chamados, resultando na saída gerada, os valores de retorno 0 e 1 são AND de bitwise juntos, armazenando 0 em x. Se você editar a linha e substituir o amp bitwise com sua ampola de contrapartida booleana. E compilar, carregar e executar o programa novamente, você pode se surpreender ao ver apenas uma única linha de texto repetido a cada segundo na janela do monitor de série: Por que isso acontece Isso é porque ampola booleano está usando um atalho: se o seu O operando esquerdo é zero (aka falso), já é certo que o resultado da expressão será falso. Portanto, não há necessidade de avaliar o operando correto. Em outras palavras, a linha de código int x fred (0) ampamp fred (1) é idêntica em termos de: Claramente, a ampola booleana é uma maneira muito mais concisa de expressar esta peça surpreendentemente complexa da lógica. Como com AND bit a bit e booleano E, há diferenças entre OR bit a bit e OR booleano. O operador OR bit a bit sempre avalia ambos os seus operandos, enquanto que o operador booleano OR avalia seu operando direito somente se seu operando esquerdo for falso (zero). Além disso, bitwise opera independentemente em todos os bits em seus operandos, enquanto boolean trata ambos os seus operandos como verdadeira (diferente de zero) ou false (zero), e avalia como verdadeiro (se qualquer operando é diferente de zero) ou falso (se ambos Operandos são zero). Juntando tudo: problemas comuns resolvidos Agora começamos a explorar como podemos combinar os vários operadores bit a bit para executar tarefas úteis usando a sintaxe C no ambiente Arduino. Uma palavra sobre os registros de porta no microcontrolador Atmega8 Geralmente, quando você quer ler ou gravar em pinos digitais no Atmega8, você usa as funções internas digitadas () ou digitalWrite () fornecidas pelo ambiente Arduino. Suponha que na sua função setup (), você quisesse definir os pinos digitais 2 a 13 como saída, e então você queria que os pinos 11, 12 e 13 fossem ajustados em ALTO e todos os outros pinos definissem LOW. Aqui é como um normalmente iria realizar isso: Acontece que há uma maneira de realizar a mesma coisa usando acesso direto às portas de hardware Atmega8 e operadores bit a bit: Este código tira proveito do fato de que os registros de controle DDRD e DDRB cada conter 8 bits Que determinam se um dado pino digital é saída (1) ou entrada (0). Os 2 bits superiores em DDRB não são usados, porque não há tal coisa é pino digital 14 ou 15 no Atmega8. Da mesma forma, os registos de porta PORTB e PORTD contêm um bit para o valor escrito mais recentemente para cada pino digital, HIGH (1) ou LOW (0). De um modo geral, fazer este tipo de coisa não é uma boa idéia. Por que não? Aqui estão algumas razões: O código é muito mais difícil para você depurar e manter, e é muito mais difícil para outras pessoas entenderem. Leva apenas alguns microssegundos para o processador executar código, mas pode levar horas para você descobrir por que ele não está funcionando direito e corrigi-lo Seu tempo é valioso, certo Mas o tempo de computadores é muito barato, medido no custo de A eletricidade que você a alimenta. Geralmente é muito melhor escrever o código da maneira mais óbvia. O código é menos portátil. Se você usar digitalRead () e digitalWrite (), é muito mais fácil escrever o código que será executado em todos os microcontroladores Atmel, enquanto os registros de controle e porta pode ser diferente em cada tipo de microcontrolador. É muito mais fácil de causar Não intencionais com acesso direto à porta. Observe como a linha DDRD B11111110 acima menciona que ele deve deixar o pino 0 como um pino de entrada. Pin 0 é a linha de recepção na porta serial. Seria muito fácil acidentalmente causar a sua porta serial para parar de trabalhar, alterando pino 0 em um pino de saída Agora que seria muito confuso quando de repente você é incapaz de receber dados em série, não seria Então você pode estar dizendo a si mesmo, grande, Por que eu iria querer usar este material, então Aqui estão alguns dos aspectos positivos do acesso direto à porta: Se você estiver executando com pouca memória do programa, você pode usar esses truques para tornar seu código menor. Ele requer muito menos bytes de código compilado para escrever simultaneamente um monte de pinos de hardware simultaneamente através dos registros de porta do que seria usando um loop for para definir cada pino separadamente. Em alguns casos, isso pode fazer a diferença entre o ajuste do programa na memória flash ou não. Às vezes, você pode precisar definir vários pinos de saída exatamente ao mesmo tempo. Chamar o digitalWrite (10, HIGH) seguido de digitalWrite (11, HIGH) fará com que o pino 10 vá para ALTO vários microssegundos antes do pino 11, o que pode confundir certos circuitos digitais externos sensíveis ao tempo que você conectou. Alternativamente, você poderia definir ambos os pinos de alta exatamente no mesmo momento no tempo usando PORTB B1100Você pode precisar ser capaz de ligar pinos e desligar muito rapidamente, ou seja, dentro de frações de um microssegundo. Se você olhar para o código-fonte em lib / targets / arduino / wiring. c. Você verá que digitalRead () e digitalWrite () são cada uma cerca de uma dúzia de linhas de código, que são compilados em algumas instruções de máquina. Cada instrução de máquina requer um ciclo de clock em 16MHz, que pode somar em aplicações sensíveis ao tempo. Acesso direto à porta pode fazer o mesmo trabalho em muito menos ciclos de clock. Exemplo mais avançado: desativar uma interrupção Agora vamos pegar o que aprendemos e começar a fazer sentido de algumas das coisas estranhas que às vezes você verá programadores avançados fazer em seu código. Por exemplo, o que significa quando alguém faz o seguinte Este é um exemplo de código real da biblioteca de tempo de execução Arduino 0007, no arquivo libtargetsarduinowinterrupts. c. Em primeiro lugar, precisamos saber o que significam GICR e INT0. Acontece que GICR é um registro de controle que define se certas interrupções de CPU estão habilitadas (1) ou desativadas (0). Se pesquisarmos os arquivos de cabeçalho padrão do Arduino para INT0. Encontramos várias definições. Dependendo do tipo de microcontrolador que você está escrevendo, você tem So So em alguns processadores, a linha acima do código irá compilar para: e em outros, ele irá compilar para: Vamos estudar o último caso, como é mais ilustrativo. Em primeiro lugar, o valor (1 ltlt 6) significa que deslocamos 1 deixado por 6 bits, que é o mesmo que 6 ou 64. Mais útil neste contexto é ver esse valor em binário: 01000000. Em seguida, o Bitwise operador NOT é aplicado a este valor, resultando em todos os bits sendo alternado: 10111111. Em seguida, o operador de atribuição bit a bit AND é usado, de modo que o código acima tem o mesmo efeito que: Isso tem o efeito de deixar todos os bits sozinho em GICR , Exceto para o segundo-para-maior bit, que é desligado. No caso em que INT0 foi definido como 0 para o seu microcontrolador particular, a linha de código seria interpretada como: que desliga o menor bit no registro GICR, mas deixa os outros bits como estavam. Este é um exemplo de como o ambiente Arduino pode suportar uma grande variedade de microcontroladores com uma única linha de código-fonte de biblioteca de tempo de execução. Salvando a memória, compactando vários itens de dados em um único byte Existem muitas situações em que você tem muitos valores de dados, cada um dos quais pode ser verdadeiro ou falso. Um exemplo disso é se você está construindo sua própria grade de LED e você deseja exibir símbolos na grade, ativando ou desativando LEDs individuais. Um exemplo de um bitmap 5x7 para a letra X pode ter este aspecto: Uma maneira simples de armazenar uma imagem desse tipo está usando uma matriz de inteiros. O código para esta abordagem pode ter este aspecto: Se este fosse o único bitmap que tinha no seu programa, seria uma solução simples e eficaz para o problema. Estamos usando 1 byte de memória de programa (de que há cerca de 7K disponível no Atmega8) para cada pixel em nosso bitmap, para um total de 35 bytes. Isso não é tão ruim, mas o que se você queria um bitmap para cada um dos 96 caracteres imprimíveis no conjunto de caracteres ASCII Isso consumiria 9635 3360 bytes, o que deixaria muito menos memória flash para a realização de seu código de programa. Existe uma maneira muito mais eficiente de armazenar um bitmap. Vamos substituir a matriz bidimensional acima por uma matriz de bytes 1-dimensional. Cada byte contém 8 bits e usaremos os 7 bits mais baixos de cada um para representar os 7 pixels em uma coluna de nosso bitmap 5x7: (Aqui estamos usando as constantes binárias predefinidas disponíveis a partir do Arduino 0007.) Isso nos permite usar 5 bytes para cada bitmap em vez de 35. Mas como podemos fazer uso deste formato de dados mais compacto Aqui está a resposta: nós reescrever a função DisplayBitMap () para acessar os bits individuais em cada byte do BitMap. A linha crucial para entender é A expressão (1ltlty) seleciona um dado bit dentro de dados que queremos acessar. Em seguida, usando AND bit a bit, o amplificador de dados (1ltlty) testa o bit dado. Se esse bit for definido, um valor diferente de zero resultará, fazendo com que o if o veja como sendo true. Caso contrário, se o bit for zero, ele será tratado como falso, então o else será executado. Referência Rápida Nesta referência rápida, nós nos referimos aos bits em um inteiro de 16 bits começando com o bit menos significativo como bit 0, eo bit mais significativo (o bit de sinal se o inteiro é assinado) como bit 15, como ilustrado em Este diagrama: Sempre que você vê a variável n. Seu valor é assumido como sendo de 0 a 15. Aqui está uma função interessante que usa tanto bitwise amp e boolean ampamp. Retorna true se e somente se o inteiro de 32 bits dado x é uma potência perfeita de 2, isto é 1, 2, 4, 8, 16, 32, 64, etc. Por exemplo, chamar IsPowerOfTwo (64) retornará true. Mas IsPowerOfTwo (65) retorna false. Para ver como essa função funciona, vamos usar o número 64 como um exemplo de uma potência de 2. Em binário, 64 é 1000000. Quando subtrair 1 de 1000000. temos 0111111. Aplicando bitwise amp. O resultado é 0000000. Mas se fizermos o mesmo com 65 (binário 1000001), temos 1000001 amp 1000000 1000000. que não é zero. Aqui está uma função que conta quantos bits no inteiro de 16 bits x são 1 e retorna a contagem: Outra maneira é esta: Vários truques para operações comuns de bit-oriented podem ser encontrados aqui.

No comments:

Post a Comment