• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

zedlav

arduino blinking led de outra forma

4 mensagens neste tópico

Boas, para alguns isto não é nada de novo.

Depois de consultar isto http://www.arduino.cc/en/Reference/HomePage reparei que eles não meteram referencia ao inline assembly (algo possivel com alguns compiladores de C neste caso o GCC), mas então como é possivel este código ser compilado no ide arduino???

Bem mãos á obra disse eu, vou fazer o teste tipico de piscar a led

Este codigo depois de compilado no ide arduino da um ficheiro com 658 bytes bem mais pequeno que o exemplo oficial.

/*

TESTE PARA ATMEGA168

* Blink
*
* The basic Arduino example.  Turns on an LED on for one second,
* then off for one second, and so on...  We use pin 13 because,
* depending on your Arduino board, it has either a built-in LED
* or a built-in resistor so that you need only an LED.
*
* http://www.arduino.cc/en/Tutorial/Blink
*/

             // LED connected to digital pin 13

void setup()                    // run once, when the sketch starts
{
  
   asm("sbi  0x04, 5");     // sets the digital pin as output
}

void loop()                     // run over and over again
{
  asm("sbi  0x05, 5");  // sets the LED on
  delay(1000);                  // waits for a second
  asm("cbi  0x05, 5");     // sets the LED off
  delay(1000);                  // waits for a second
}

Humm, afinal dá! Claro que dá, quem compila não é o ide mas sim o GCC.

O ide arduino adiciona ao nosso codigo uma funçao chamada main, e uma linha que serve de instruçao ao pre-processador:

#include "WProgram.h"

neste header file (http://en.wikipedia.org/wiki/Header_file) encontra-se outra linha

#include "wiring.h"

E é neste header file que está esta linha em baixo.

#include <avr/io.h>

Se tem este head file (io.h), então tambem isto é valido.

/*
* Blink
*
* The basic Arduino example.  Turns on an LED on for one second,
* then off for one second, and so on...  We use pin 13 because,
* depending on your Arduino board, it has either a built-in LED
* or a built-in resistor so that you need only an LED.
*
* http://www.arduino.cc/en/Tutorial/Blink
*/

             // LED connected to digital pin 13
             

void setup()                    // funçao chamada a partir do main criada por o ide
{
  
  DDRB = 32; 
  
}

void loop()                     // esta funçao está constantemente a ser chamada pela funçao main criada pelo ide
{
  
   PORTB=0;
   delay(1000);
   PORTB=32;
   delay(1000);
   
}

Este fica com um tamanho de 664 bytes.

Este é o exemplo dado pelo pessoal do arduino, mas depois de compilado da o ficheiro de 1124 bytes.

/*
* Blink
*
* The basic Arduino example.  Turns on an LED on for one second,
* then off for one second, and so on...  We use pin 13 because,
* depending on your Arduino board, it has either a built-in LED
* or a built-in resistor so that you need only an LED.
*
* http://www.arduino.cc/en/Tutorial/Blink
*/

int ledPin = 13;                // LED connected to digital pin 13
// PODIAM PÔR #define ledPin 13 


void setup()                    // run once, when the sketch starts
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()                     // run over and over again
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

No proximo post irei programar o arduino sem o ide.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem desta vez é sem ide.

Mais uma vez, para alguns isto não é nada de novo!

O primeiro problema que tive foi onde está o codigo da função delay??? Tive de procurar e encontrei, estava neste ficheiro arduino-00XX/hardware/cores/arduino/wiring.c fui até a pasta arduino-00XX/hardware/cores/arduino, já dentro dessa pasta executei este comando,

$avr-gcc -O2 -fno-builtin -mmcu=atmega168  wiring.c -c -o wiring.o -F_CPU=16000000UL

depois copiei o objecto wiring.o criado pelo GCC para a pasta arduino-00XX e ainda criei o ficheiro C para teste que esta em baixo.

#include "WProgram.h"


/*
SEM IDE PODEMOS POR TUDO NO MAIN E CRIAR UM LOOP INFINITO
void setup()                     
{

   asm("sbi  0x04, 5");     
}

void loop()                     
{
  asm("sbi  0x05, 5");  
  delay(1000);                  
  asm("cbi  0x05, 5");     
  delay(1000);                  
}

*/

int main(void)
{
        init();// esta é mesmo necessaria o delay está dependente desta função
        asm("sbi  0x04, 5");
        //setup();
   
        for (;B){
                //loop();
        asm("sbi  0x05, 5");  
        delay(1000);                  
        asm("cbi  0x05, 5");     
        delay(1000);       
}
        return 0;
}

Agora temos o objecto wiring.o mais o ficheiro C para teste na pasta arduino-00XX, executei mais 2 comandos

$avr-gcc  -Ihardware/cores/arduino/ -mmcu=atmega168 wiring.o teste.c -o teste.elf

$avr-objcopy -O ihex -R .eeprom teste.elf teste.hex

Resta-nos gravar isto no atmega168(core arduino diecimila), para isso usei avrdude.

#avrdude -V -F -c stk500v1 -p m168 -b 19200 -P /dev/ttyUSB0 -U flash:w:teste.hex

Humm, 690 bytes, cheira-me a #ifdef's, mas não intressa porque se forem usar algo da biblioteca do arduino mais vale usar o ide.

Ok, agora quero fazer sem o delay da biblioteca do arduino.

Outra forma é nós fazermos o nosso delay no meu caso fui buscar uma funçao que já tinha criado para o atmega32 escrita em assembly para se poder aceder a partir de C, a função chamada sleep está em baixo.



.arch atmega168


.global	sleep

.type	sleep, @function
sleep:

push    r31
        push    r30
push	r16
start:
ldi	r16, 63
fill:
ldi	r31, 195 	
ldi	r30, 80
dec_1:	
nop
sbiw	r30,1 
brne	dec_1 
dec	r16
cpi	r16, 0 
brne	fill 
dec	r24
brne	start
pop	r16
pop	r30
pop	r31
ret


Para compilar basta isto

$avr-as sleep.s -o sleep.o

Em baixo encontra-se o ficheiro teste.c.


int main(void)
{
        asm("sbi  0x04, 5");
        
        for (;{
        asm("sbi  0x05, 5");  
        sleep(1);                  
        asm("cbi  0x05, 5");     
        sleep(1);       
}
        return 0;
}

Os tres comandos.

$avr-gcc  -mmcu=atmega168 sleep.o teste.c -o teste.elf

$avr-objcopy -O ihex -R .eeprom teste.elf teste.hex

# avrdude -V -F -c stk500v1 -p m168 -b 19200 -P /dev/ttyUSB0 -U flash:w:teste.hex

REFERENCIAS:

https://www.mainframe.cx/~ckuethe/avr-c-tutorial/

http://symbolx.org/robotics/35-info/107-arduinoavr-command-line-dev-environment.html

http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf

http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Excelente contributo...zedlav

Numa versão comum utilizando o Atmega168, tendo em conta o espaço utilizado pelo bootloader do Arduino, temos cerca de 14336 bytes para carregar o nosso programa. Em aplicações que requeiram muitas linhas de código, é necessário optimizar e aqui estão alguns exemplos de como isso pode ser efectuado. Eu próprio vou seguir alguns dos "truques" aqui apresentados.

Sem mais,

Pessanha24

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Parabéns zedlav, este teu post está tão bom que me fizeste registar só para te poder felicitar :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora