collapse

* Links de Robótica

* Posts Recentes

Palavras Cruzadas por Hugu
[Hoje às 00:54]


[Projecto] Bomba Airsoft por jm_araujo
[Ontem às 16:54]


Apresentação por Tech_JA
[Ontem às 09:19]


Medir Agua que está no Poço por filjoa
[21 de Setembro de 2017, 20:58]


URGENTE - display de 7 segmentos com backpack por helderjsd
[20 de Setembro de 2017, 12:30]


Preços e fabricantes de pcb por Sérgio_Sena
[19 de Setembro de 2017, 10:20]


Isaac Asimov - I, Robot por senso
[18 de Setembro de 2017, 03:41]


ic SL440 da Plessey? por senso
[16 de Setembro de 2017, 13:11]


Compra Colectiva RS-Amidata por brunus
[15 de Setembro de 2017, 22:31]


Ideias para construir um quadrúpede simples por zordlyon
[15 de Setembro de 2017, 10:18]

Autor Tópico: Programar Arduino/AVR -- low level.  (Lida 9946 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Programar Arduino/AVR -- low level.
« em: 10 de Setembro de 2010, 01:06 »
Recentemente, tenho andado a espreitar alguns tutoriais, e a datasheet de alguns AVRs (inclusive o presente no Arduino), e a programar o Arduino com base nisso.
Para atingir a performance máxima, podia programar em assembly, mas com as optimizações no máximo, o código em C, é apenas cerca de 10% menos eficiente, e mais simples de fazer debug e prorgamar.
A maioria dos tutoriais que li estavam em inglês, o que pode ser uma limitação para alguns, e outros não cobriam o AVR presente no arduino, o que levava a que houvesse alguns erros nos registers usados (facilmente corrigidos observando a datasheet).
Então, para facilitar as coisas para outros iniciantes, decidi começar a escrever alguns tutoriais também :), em português
Para já, ainda não tenho nada pronto, mas neste post já deixo umas coisas:
Um tutorial de iniciante muito bom: http://lusorobotica.com/index.php?topic=1069.0
Neste fórum, encontram vários tutoriais também, em inglês (foram esses que li): http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewforum&f=11&sid=bc063b8fce44bb602023706af59cf38b

Estes tutoriais têm dois objectivos principais: facilitar a entrada de iniciantes no mundo da programação em baixo nível de microcontroladores e também facilitar a minha aprendizagem desse mesmo mundo.

Outro bónus, neste primeiro post: como fazer um simples programa de comunicação em serial.
Versão baixo nível (estive horas à procura do motivo para não estar a funcionar bem ... aconteceu que li mal a datasheet, e pus mal a configuração para enviar 8 bits por caracter, e estava a enviar 7 XD):

Código: (c) [Seleccione]
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define B9600 103 // F_CPU = 16000000 -- valor no datasheet

volatile char c = 'A'; // Volátil porque a interrupção pode alterá-lo (coisas que o optimizador de C não pode prever).
char output = 0;

int main() {
  DDRB |= (1<<PB5); // Configurar o pino digital 13 (PB5) para output

  UCSR0B |= (1<<RXEN0) | (1<<TXEN0); // Começar a comunicação USART. TXEN0 -- transmissão; RXEN0 -- recepção
  UCSR0C &= ~(1<<UCPOL0);
  UCSR0C &= ~((1<<UMSEL01) | (1<<UMSEL00)); // Estes dois bits selccionam o tipo de comunicação serial -- assíncrona.
  UCSR0C &= ~((1<<UPM01) | (1<<UPM00)); // Não queremos paridade

  // Os dados enviados/recebidos têm 8 bits.
  UCSR0B &= ~(1<<UCSZ02);
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00);
 
  UCSR0A &= ~((1<<U2X0) | (1<<MPCM0)); // Estamos aqui a certificar-nos que a velocidade do serial não é duplicada (U2X0) e que o serial não é configurado para multiprocessador (MPCM0).
 
  UBRR0L = B9600;
  UBRR0H = B9600>>8; // 9600 baud
 
  // 1 STOP BIT
  UCSR0C &= ~(1<<USBS0);
 
  UCSR0B |= (1<<RXCIE0); // Ligar a interrupção local do USART, que ocorre quando se recebe dados; vector: USART, RX
  sei(); // Ligar interrupções a nível global.
 
  for(;;) {
    if(UCSR0A&(1<<UDRE0)) { // Só enviamos dados quando a flag (UDRE0) que nos indica que o buffer está vazio está "ligada"
      // Enviar o carácter c e nova linha.
      UDR0 = c;
      while(!(UCSR0A&(1<<UDRE0)));
      UDR0 = '\n';
      _delay_ms(1000); } } } // Uma vez por segundo

ISR(USART_RX_vect) { // Interrupção quando recebe dados -- alterar o carácter c para o recebido, e caso seja para o 'A', mudar o estado do pino digital 13 (PB5 -- OUTPUT)
  output = ~output; // Alterar o estado do bit do pino 13
  c = UDR0; // Guardar os dados recebidos em c
  if(c=='A') {
    PORTB &= ~(1<<PB5);
    PORTB |= ((output&1)<<PB5); } } // Alterar o estado do pino digital 13.

Versão alto nível (linguagem do arduino):
Código: (c) [Seleccione]
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); }

char c = 'A';
int output = 0;

void loop() {
  if(Serial.available()) {
    c = Serial.read();
    if(c == 'A') {
      output = 1-output;
      digitalWrite(13, output); } }
  Serial.println(c);
  delay(1000); }

A do arduino é obviamente muito mais simples. No entanto, enquanto a de baixo nível só ocupa ~0,4kB, a do arduino ocupa ~2.8kB! (~7 vezes mais!). E estive a ver a biblioteca de Serial do arduino ... basicamente é tudo feito a nível de software, o que põe um grande stress no processador ...
O que este programa faz é basicamente enviar um carácter por Serial, a cada segundo, e quando recebe um carácter por Serial, passar a enviar esse carácter. Quando o carácter recebido é o A, faz toggle do pin 13 (que nalguns arduinos recentes traz um LED).

O primeiro tutorial que colocarei aqui será sobre interrupções. O primeiro tutorial que coloquei mais acima, escrito por Njay explica bastante bem os GPIOs, logo considerarei os mesmos explicados :P
Para compilar os programas, será sempre suficiente usar os seguintes comandos:
Citar
avr-gcc -Wall prog.c -Os -mcall-prologues -mmcu=atmega328 -o prog.out -DF_CPU=16000000
avr-objcopy -O ihex -R .eeprom prog.out prog.hex
(alterar prog.c para o nome do ficheiro; caso isto não seja suficiente, mencionarei isso nos tutoriais)

Para enviar os programas para o arduino, é suficiente usar:
Citar
avrdude -p m328p -c avrisp -P /dev/ttyUSB0 -b 57600 -F -U flash:w:prog.hex
(alterar /dev/ttyUSB0 pela porta série correspondente).

Para os que usem Windows, é provavelmente mais simples configurar o AVR Studio. Como nunca usei, não me arrisco a explicar, mas deixo aqui este tutorial (como também contém um mapping dos pinos do arduino para o seu nome no microcontrolador, aconselho a todos a ler):
http://www.smileymicros.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=70&MMN_position=117:117

Vou assumir que todos os interessados têm alguma experiência em programação de C (vou tentar explicar como se fossem muito burros xD, mas é a primeira vez que faço uma coisa assim :/ -- tentarei responder qualquer dúvida ... agradeço no entanto que chegue à programação da interface serial antes de fazerem perguntas acerca do código acima -- o meu objectivo é que nessa altura já o percebam :P).

EDIT: Código low-level alterado para coincidir com as sugestões do senso, e do Tyran. Obrigado :)
EDIT2: Senso, por alguma razão, o ~output não funciona bem :S com bools. Por isso passei a usar chars, e esqueço os bools :P

EDIT3: PDF publicado! A partir de agora para manter o tópico limpo, todos os tutoriais serão colocados neste PDF, havendo apenas um post de aviso de actualização. Os posts com os tutoriais serão apagados. PDF em anexo.
EDIT4: PDF editado de acordo com sugestões de Njay. E guardado num host mais permanente, caso haja problemas com actualização do fórum.
EDIT5: Secção I²C actualizada. Separei os vários tópicos em PDFs diferentes, mais pequenos, e manti tudo junto num PDF grande.

Documento completo: http://netexplorers.org/AVR/AVR_C.pdf
Pequenos conceitos necessários acerca de programação em C: http://netexplorers.org/AVR/uC_C.pdf
Introdução/GPIO (contribuições do Njay): http://netexplorers.org/AVR/Njay.pdf
Interrupções: http://netexplorers.org/AVR/interrupts.pdf
Timers - Parte 1: http://netexplorers.org/AVR/timers.pdf
Timers - Parte 2: http://netexplorers.org/AVR/timers2.pdf
Analog-to-Digital Converter: http://netexplorers.org/AVR/ADC.pdf
Comunicação Serial no AVR (contribuições do senso): http://netexplorers.org/AVR/serial.pdf
Comunicação por I²C: http://netexplorers.org/AVR/I2C.pdf
« Última modificação: 21 de Dezembro de 2010, 03:53 por Cynary »

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.390
  • Helpdesk do sitio
Re: Programar Arduino/AVR -- low level.
« Responder #1 em: 10 de Setembro de 2010, 01:42 »
O teu outuput=1-output não podia ser simplesmente output = ~output?
Acho que devias ter o teu código mais comentado, quem nunca viu isto á frente não sabe o que querem dizer todas aquelas siglas.
Continuas com alguns maus habitos do arduino, por exemplo usar ints, ainda por cima para usar como variavel que guarda dados para meter num porto que tem no máximo 8 bits, habitua-te a usar uint8_t e int8_t, char, unsigned char, e coisas assim para poupar no que é desnecessário.
Apesar de tudo parabens pela iniciativa, ando a fazer o mesmo, brincar com c a sério e deixar o ide do arduino, já usava c em vez do estupido c++ no ide do arduino, mas como quero passar para outros atmegas vou virar-me só para avr-gcc e nada de c++ e de todo o bloat que o core do arduino tem e do consumo estupidamente excessivo de ram e de flash que o mesmo origina.
Quando tiver tempo e não te importares da concorrencia acho que tambem vou escrever um pequeno tutorial.
Avr fanboy

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #2 em: 10 de Setembro de 2010, 01:52 »
O teu outuput=1-output não podia ser simplesmente output = ~output?
Acho que devias ter o teu código mais comentado, quem nunca viu isto á frente não sabe o que querem dizer todas aquelas siglas.
Continuas com alguns maus habitos do arduino, por exemplo usar ints, ainda por cima para usar como variavel que guarda dados para meter num porto que tem no máximo 8 bits, habitua-te a usar uint8_t e int8_t, char, unsigned char, e coisas assim para poupar no que é desnecessário.
Apesar de tudo parabens pela iniciativa, ando a fazer o mesmo, brincar com c a sério e deixar o ide do arduino, já usava c em vez do estupido c++ no ide do arduino, mas como quero passar para outros atmegas vou virar-me só para avr-gcc e nada de c++ e de todo o bloat que o core do arduino tem e do consumo estupidamente excessivo de ram e de flash que o mesmo origina.
Quando tiver tempo e não te importares da concorrencia acho que tambem vou escrever um pequeno tutorial.

~output pode dar resultados indefinidos (neste caso não faria diferença no entanto, visto estarmos a mexer com PORTB), já que todos os bits da variável são alterados, e arriscas-te a mexer noutros bits do register.
Tens razão, devia ser ~output, e não vale a pena usar um int. Aliás, no início tinha um bool, e fazia simplesmente output=!output.
No entanto, como estava a ter problemas no programa, e não sabia o que estava a causar, e visto que nunca percebi se bool é um char/int ou um bit (no primeiro caso, !output não é exactamente 1, o que pode dar comportamentos indefinidos no código, mas foi mesmo de desespero que tentei xD), tentei com int :P
Quanto aos comentários, o meu objectivo é ir depois explicando o código ao longo dos tutoriais, pois explicar aquilo tudo com alguns comentários é mesmo impossível xD
Quanto à competição, agradecia, facilitaria um pouco o meu trabalho hehe.
Estava a pensar guardar tudo num PDF, quando tivesse um número razoável de trabalhos. Importas-te que use os teus no mesmo (claro, crédito atribuído onde é merecido ;))?

EDIT: Decidi seguir as tuas sugestões, e comentar e optimizar mais um pouco. O pormenor do (output&1) não é estritamente necessário neste caso, visto que não nos importamos com os outros pinos, mas mesmo assim é um bom hábito a obter, pois se não o fizéssemos, podíamos alterar outros pinos na porta B.
« Última modificação: 10 de Setembro de 2010, 02:03 por Cynary »

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #3 em: 10 de Setembro de 2010, 02:19 »
bool assim sem mais nada não existe, ou fazes por exemplo '#define bool char' ou fazes um include que já não me recorda qual é... e ocupa claro 8bits. Se só quiseres mesmo utilizar 1 bit também dá mas deixa isso para depois.

E já agora se quiseres manter o ~ em vez de ~(....) usa (bool)~(...) pois caso contrário o compilador vai gerar código para 16bits... Tens esta e outras particularidades explicadas no avr-gcc libc.

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #4 em: 10 de Setembro de 2010, 02:36 »
bool assim sem mais nada não existe, ou fazes por exemplo '#define bool char' ou fazes um include que já não me recorda qual é... e ocupa claro 8bits. Se só quiseres mesmo utilizar 1 bit também dá mas deixa isso para depois.

E já agora se quiseres manter o ~ em vez de ~(....) usa (bool)~(...) pois caso contrário o compilador vai gerar código para 16bits... Tens esta e outras particularidades explicadas no avr-gcc libc.

No mínimo uma variável ocupa 1 byte, visto que é um valor na memória ... podemos é usar cada bit de uma variável, ou então aceder a um registo de uso geral para isso ...
Quanto ao bool, tinha-me esquecido :S hábito do C++ xD. E o pormenor do ~ não sabia, obrigado pela dica ;) No entanto, não vou incluir nos exemplos, pois de acordo com o que li, aplica-se a todas as operações ao nível de bits, e é código, que apesar de optimizar um pouco o programa, não faz realmente muita diferença (até fico admirado que o compilador não optimize isso por si só com as flags de optimização ...).
Já alterei o código no post original. O bool está no stdbool.h

EDIT: Fiz um teste, e o casting não fez diferença ... só se depender da implementação da libc ...
O compilador normalmente optimiza certos detalhes como esse, entre outros.
« Última modificação: 10 de Setembro de 2010, 03:34 por Cynary »

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #5 em: 10 de Setembro de 2010, 09:41 »
Podes sempre criar uma estrutura com várias flags de um bit, isso de usar assim cruelmente uma variável e ter lá várias flags nunca me deu muito interesse. Até ao momento ainda não precisei de ser assim tão poupado também, mas de facto traz saudades a área endereçável ao bit do 8051 :D

Deve depender do nível de optimização...

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.390
  • Helpdesk do sitio
Re: Programar Arduino/AVR -- low level.
« Responder #6 em: 11 de Setembro de 2010, 16:48 »
Mais uma vez parabens pelo esforço, só uma coisa, nunca se usam delays numa interrupção, é uma convenção por questões de segurança e fiabilidade do programa.
Avr fanboy

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #7 em: 11 de Setembro de 2010, 17:14 »
Delays não é de todo recomendável numa interrupção, ela deve ser o mais rápida possível para que outras possam também ocorrer. Todo o código pesado duma interrupção deve ser passado para fora da mesma.

Esse método não é o melhor e pode nem funcionar, imagina que apanhavas um bounce mas que mais tarde estabilizava para 0, isto é, apenas apanhaste um ruído e não um pressionar do botão... O que podes fazer é pegar num dos algoritmos usados como por exemplo testar se o nível de input continua no mesmo valor durante 10 leituras com x milisegundos de intervalo entre as mesmas. Deves apanhar várias técnicas espalhadas pela net...

Outra coisa, não precisas de inicializar as variáveis globais a 0 pois isso acontece na secção .init

Já não usas o bool? Eu costumo fazer num ponto h common.h:
Código: [Seleccione]
#define bool unsigned char
#define false 0
#define true !false

Mas pelo que tu queres fazer podes usar uma operação XOR...

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #8 em: 11 de Setembro de 2010, 17:20 »
Eu menciono no tutorial que os delays não são recomendáveis :P
Como disse, apenas usei para demonstrar um método básico de debouncing (e também explico que só uso porque não tenho nada no código principal).
Além disso, também serviu para mostrar como as interrupções funcionam através das flags.
O bool do stdbool.h não funcionou para o que estava a fazer ... por alguma razão, o ~output não dava o resultado esperado quando era bool, por isso manti-me pelos chars :P não me confunde e funcionam xD
Estou a tentar desenvolver uma técnica mais sofisticada de debouncing, que envolve contar o tempo que passa entre a transição para o estado low e o estado high. Mas como envolve timers, vou deixar para um tutorial futuro.
Quanto a inicializar as variáveis globais a 0, tens razão, só quis ser o mais claro possível.
« Última modificação: 11 de Setembro de 2010, 17:31 por Cynary »

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #9 em: 11 de Setembro de 2010, 17:47 »
Talvez trocar o '~'  por '!'

Com o xor numa expressão fazias tudo sem precisar de variáveis auxiliares.

Sim compreendo o que dizes e parabéns pelo esforço para a comunidade ;) Era interessante ter algum feedback, vamos dar tempo e esperar que alguém queira também enveredar por isto :D

Qualquer ajuda que precises para fazer algo apita :)

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #10 em: 11 de Setembro de 2010, 17:52 »
Talvez trocar o '~'  por '!'

Com o xor numa expressão fazias tudo sem precisar de variáveis auxiliares.

Sim compreendo o que dizes e parabéns pelo esforço para a comunidade ;) Era interessante ter algum feedback, vamos dar tempo e esperar que alguém queira também enveredar por isto :D

Qualquer ajuda que precises para fazer algo apita :)

Obrigado!
Não troco o ~ pelo ! devido a uma particularidade: o comportamento do '~' está bem definido (mudar todos os bits da variável ... o tipo bool deve ter alguma particularidade ou optimização que faz com que isto não funcione exactamente dessa forma). O '!' altera o valor lógico da variável, mas exactamente como, não está bem definido, dependendo do compilador (pode por exemplo, para alterar de falso para verdadeiro só mexer num dos bits, ou em bits random). Ao usar o !, estaria a arriscar que o bit menos significativo da variável ficasse igual ao estado anterior (caso fosse uma transição de falso para verdadeiro), não mexendo assim na porta de output, e apenas alterando as outras.
O XOR funcionaria perfeitamente claro, e nesta aplicação é mais do que razoável utilizá-lo. Para outras aplicações, tem no entanto o risco de alterar o estado das outras portas, por isso prefiro não apanhar muito esse hábito.

Gostaria era de ver mais pessoas a tentar isto, pois o controlo directo do microcontrolador dá-nos muito mais opções do que o IDE do arduino.
Talvez depois do tutorial acerca de timers, coloque um sobre coisas básicas (manipulação de bits, registers, etc.), a ver se mais "novatos" espreitam isto xD

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #11 em: 11 de Setembro de 2010, 19:26 »
Era simples, em vez de fazer a lógica com o 1 fazias == true por exemplo :)

Não altera desde que só faças ao bit que desejares, não ias fazer ao porto todo.

Pois, mas até ao momento somos apenas 3 a ter postado lol vamos dar tempo :p
« Última modificação: 11 de Setembro de 2010, 19:28 por Tyran »

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #12 em: 12 de Setembro de 2010, 01:34 »
Era simples, em vez de fazer a lógica com o 1 fazias == true por exemplo :)

Não altera desde que só faças ao bit que desejares, não ias fazer ao porto todo.

Pois, mas até ao momento somos apenas 3 a ter postado lol vamos dar tempo :p

Então estás a sugerir implementar um if? Funcionaria, mas aí seria muito mais pesado para o processador do que um ~ (claro, neste caso não notaríamos diferença, em grandes programas sim).
E quanto ao == true, não sei se é uma boa ideia, tendo em conta as definições que fizeste do true false e bool ...
Como disse, o comportamento do ! não está completamente definido quando se converte de falso para verdadeiro, logo, podes estar a comparar dois valores inteiros (de 8 bits) com valores lógicos iguais, mas diferentes valores, resultando aí num false (a forma correcta seria com um "&& true").

Mencionei no meu post anterior que o XOR não funcionaria bem devido ao risco de alterar outras portas ... esqueçam o que eu disse xD
Tinha-me esquecido exatamente de como o XOR funcionava -.- Pensava que dois 0s no XOR davam 1, afinal dão 0 xD
Logo, um XOR funcionaria perfeitamente :P peço desculpa pela confusão que isto gerou.
Tentarei complicar com um tutorial impecável sobre timers ainda esta semana :)
« Última modificação: 12 de Setembro de 2010, 01:42 por Cynary »

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: Programar Arduino/AVR -- low level.
« Responder #13 em: 12 de Setembro de 2010, 01:59 »
Não dizia um if... por exemplo (flag==true)<<X...

A flag vai estar sempre a fazer 1 0 1 0 1 0, e um 1 está dentro do range do meu !false, isto é, true... eu apenas deixou assim porque às vezes dá-me jeito ter outros valores como true, mas senão pode ficar o true como apenas sendo 1 e mesmo assim funciona esta maneira...

Em vez desse ==true podes fazer um &&true ou manter o &1
« Última modificação: 12 de Setembro de 2010, 02:06 por Tyran »

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Programar Arduino/AVR -- low level.
« Responder #14 em: 12 de Setembro de 2010, 02:54 »
Penso que não percebeste bem o que estava a dizer :S
Não vejo como o exemplo que deste:

(flag==true)<<X

poderia funcionar sempre.
A forma como os operadores lógicos (!, ==, ...) funcionam depende da forma como o compilador os trata.
A forma como definiste true (!false), não significa que true seja obrigatoriamente 1. E não significa que true seja sequer um valor constante! (no entanto, o mais provável é que o compilador optimize de forma a que seja). Assim, ao usares o ==, não estás a possibilitar o uso de vários valores como true. Por exemplo, se o compilador optimizar o !false que definiste como sendo igual a 1, então ao comparares com um 5, dar-te-ia false. Só podes garantir resultados correctos se usares o &&.
Mas o maior erro, está ao fazeres (flag==true)<<X, pois o == pode não devolver obrigatoriamente um 1. Pode devolver um 2 ou 4 ou um 6, ... e nesses casos, estarias a alterar o valor de outros pinos (no caso de 4, o pino X+1, ...), e não estarias a tocar no valor do teu pino (o mesmo problema ocorre ao usar o &&true).
Para fazer toggle de pinos, a melhor solução é mesmo um xor ... se uma variável de estado é necessária, usar operadores lógicos, como o !, para manipular o seu valor, não é aconselhável, visto a não terem comportamentos definidos (imagina que alguém decide programar um compilador em que o operador '!', quando aplicado a algo com o valor 0, corresponde a copiar todo o conteúdo de um register, com pelo menos um bit indubitavelmente igual a 1, e com os outros bits indefinidos, podendo ser alterados, ficas com um valor desconhecido).
Nos testes que fiz no gdb, esse tipo de operações deu-me sempre 1 como resultado ... no entanto, visto não ser obrigatório, pode não funcionar em alguns casos :P.
(esta discussão sobre o funcionamento da linguagem C, e formas de usar bools e fazer toggles a bits está a ficar interessante xD. No entanto, penso que o ideal, seria mover essa parte para outro tópico, possivelmente na secção de software e programação ... visto que está a tirar o foco dos tutoriais aqui :S -- sugeriria criar um novo tópico acerca disto, e mudar para lá as mensagens relevantes, e eliminar as nossas mensagens aqui, ou condensar tudo num só post, e eliminar os outros).
« Última modificação: 12 de Setembro de 2010, 03:02 por Cynary »