Jump to content
zedlav

arduino blinking led de outra forma

Recommended Posts

zedlav

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.

Share this post


Link to post
Share on other sites
zedlav

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

Share this post


Link to post
Share on other sites
Pessanha24

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


Pessanha24"A vida é mais do que Copy & Paste"<*(((-<<*(((-< <*(((-<<*(((-<Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.