collapse

* Posts Recentes

Emulador NES em ESP32 por dropes
[Ontem às 14:14]


Arame de Estendal por almamater
[18 de Abril de 2024, 16:16]


O que é isto ? por SerraCabo
[12 de Abril de 2024, 14:20]


Amplificador - Rockboard HA 1 In-Ear por almamater
[11 de Abril de 2024, 20:46]


Meu novo robô por josecarlos
[29 de Março de 2024, 18:30]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]

Autor Tópico: Introdução ao avr-gcc usando o AvrStudio [Mais timers/mood light]  (Lida 116480 vezes)

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

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #45 em: 03 de Outubro de 2010, 02:51 »
Njay -- a lógica está boa, mas o código não se comporta como deve de ser, visto que devia acender o LED do arduino quando recebe o caracter 'a', e não o está a fazer.
Queria pedir desculpa pelos erros que fiz na minha mensagem anterior -- o código do senso está a funcionar a 100%, e os problemas que estava a ter era por ter trocado as flags para o avrdude no meu IDE, visto que também tenho um atmega88, e não cheguei a trocar o argumento do avrdude de m88 para m328p.
O problema que faz com que o teu código não se comporte como deve de ser, são os tipos das variáveis.
Um 'a' é um signed char. No entanto, a função USART_receive() devolve um unsigned char.
Tens duas opções aí: ou mudas o tipo que a função devolve para char, ou fazes um casting para unsigned char do 'a'.
Aqui está como fica com o casting (linha 23):
Código: (c) [Seleccione]
if ( USART_receive() == (unsigned char)'a' ) {
« Última modificação: 03 de Outubro de 2010, 03:06 por Cynary »

Offline GnGz

  • Mini Robot
  • *
  • Mensagens: 665
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #46 em: 03 de Outubro de 2010, 11:36 »
a outra forma era fazer return em char so?

P.S fez das duas maneiras e nenhuma funciona :S
« Última modificação: 03 de Outubro de 2010, 11:37 por GnGz »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #47 em: 03 de Outubro de 2010, 11:46 »
O problema que faz com que o teu código não se comporte como deve de ser, são os tipos das variáveis.
Um 'a' é um signed char. No entanto, a função USART_receive() devolve um unsigned char.
Tens duas opções aí: ou mudas o tipo que a função devolve para char, ou fazes um casting para unsigned char do 'a'.
Aqui está como fica com o casting (linha 23):
Código: (c) [Seleccione]
if ( USART_receive() == (unsigned char)'a' ) {

Não me parece que isso seja problema. Ambos os tipos têm o mesmo tamanho (8 bits) e na comparação de igualdade o sinal é irrelevante.

Que tal fazer um "serial echo"? Isso tira logo as dúvidas relativas ao código UART estar ou não a funcionar:

Código: [Seleccione]
    while (1) {
        USART_send(USART_receive());
        PORTB ^= (1<<PB5);
        _delay_ms(80);
        PORTB ^= (1<<PB5);
        _delay_ms(80);
    }
« Última modificação: 03 de Outubro de 2010, 11:55 por Njay »

Offline GnGz

  • Mini Robot
  • *
  • Mensagens: 665
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #48 em: 03 de Outubro de 2010, 12:04 »
Feito ... O USART nao funciona...

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #49 em: 03 de Outubro de 2010, 12:29 »
Como estás a testar? Tens o teu terminal bem configurado?
Faz o LED piscar 2 ou 3 vezes no inicio do programa para teres a certeza que o micro está a correr.
O código que aí deixei faz o LED dar uma piscadela rápida a cada caracter que recebe; vês ele piscar?
Mostra aí o teu código completo e a linha de comando que usaste para o compilar.

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #50 em: 03 de Outubro de 2010, 12:31 »
O problema que faz com que o teu código não se comporte como deve de ser, são os tipos das variáveis.
Um 'a' é um signed char. No entanto, a função USART_receive() devolve um unsigned char.
Tens duas opções aí: ou mudas o tipo que a função devolve para char, ou fazes um casting para unsigned char do 'a'.
Aqui está como fica com o casting (linha 23):
Código: (c) [Seleccione]
if ( USART_receive() == (unsigned char)'a' ) {

Não me parece que isso seja problema. Ambos os tipos têm o mesmo tamanho (8 bits) e na comparação de igualdade o sinal é irrelevante.

Isso está errado ...
Para provar isto, convido-te a testar o seguinte código:
Código: (c++) [Seleccione]
#include <iostream>
using namespace std;

signed char i = (1<<7);
unsigned char j = (1<<7);

int main(void) {
  if(i == j)
    cout << "São iguais" << endl;
  else
    cout << "São diferentes" << endl; }

Em termos de bits são iguais ... mas visto que em termos de sinais são diferentes, a comparação dá diferente, visto estares a comparar um 128 com um -128 ... (esta é a principal diferença entre o operador lógico == e o operador bitwise xor ...)

No entanto, estive a testar melhor com o AVR, e é indiferente (o que acho estranho, pois nos primeiros testes fazia diferença ... devo ter feito alguma coisa mal :P)

GnGz: Como assim o USART não funciona? Que tipo de testes fizeste? O teste to Njay não funcionou? Se o teste do Njay funcionou, mas não o que usa um unsigned char, vê se o echo que recebes tem uma nova linha, pois o teu terminal pode estar a enviar o carácter '\n' logo após o 'a', o que faria com que o LED acendesse, apenas por um período de tempo muito curto (quase não se repara), e depois apagasse logo assim que recebesse o '\n'.
« Última modificação: 03 de Outubro de 2010, 12:37 por Cynary »

Offline GnGz

  • Mini Robot
  • *
  • Mensagens: 665
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #51 em: 03 de Outubro de 2010, 12:32 »
Afinal funciona ... mas o meu codigo anterior porque raio nao funciona...

Código: [Seleccione]
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)

//declaração das nossas funções
void USART_init(void);
unsigned char USART_receive(void);
void USART_send( unsigned char data);
void USART_putstring(char* StringPtr);



int main(void){

USART_init();      //Inicializar a usart
DDRB |= (1<<PB5);

while(1){      //Loop infinito

if ( USART_receive() == 'a' ) {   //faltava-te o () depois de USART_receive para o compilador saber que é um função, e o receive estava mal escrito
 PORTB |= (1<<PB5);
 _delay_ms(5000);
}
else {
  PORTB &= ~(1<<PB5);   //falta-te um ponto e virgula aqui para indicar fim de linha
}
}

return 0;
}

void USART_init(void){

   UBRR0H = (uint8_t)(BAUD_PRESCALLER>>8);
   UBRR0L = (uint8_t)(BAUD_PRESCALLER);
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);
   UCSR0C = (3<<UCSZ00);
}

unsigned char USART_receive(void){

   while(!(UCSR0A & (1<<RXC0)));
   return UDR0;

}

void USART_send( unsigned char data){

   while(!(UCSR0A & (1<<UDRE0)));
   UDR0 = data;

}

void USART_putstring(char* StringPtr){

while(*StringPtr != 0x00){
   USART_send(*StringPtr);
   StringPtr++;}

}

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #52 em: 03 de Outubro de 2010, 12:37 »
Afinal funciona ... mas o meu codigo anterior porque raio nao funciona...

Código: [Seleccione]
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)

//declaração das nossas funções
void USART_init(void);
unsigned char USART_receive(void);
void USART_send( unsigned char data);
void USART_putstring(char* StringPtr);



int main(void){

USART_init();      //Inicializar a usart
DDRB |= (1<<PB5);

while(1){      //Loop infinito

if ( USART_receive() == 'a' ) {   //faltava-te o () depois de USART_receive para o compilador saber que é um função, e o receive estava mal escrito
 PORTB |= (1<<PB5);
 _delay_ms(5000);
}
else {
  PORTB &= ~(1<<PB5);   //falta-te um ponto e virgula aqui para indicar fim de linha
}
}

return 0;
}

void USART_init(void){

   UBRR0H = (uint8_t)(BAUD_PRESCALLER>>8);
   UBRR0L = (uint8_t)(BAUD_PRESCALLER);
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);
   UCSR0C = (3<<UCSZ00);
}

unsigned char USART_receive(void){

   while(!(UCSR0A & (1<<RXC0)));
   return UDR0;

}

void USART_send( unsigned char data){

   while(!(UCSR0A & (1<<UDRE0)));
   UDR0 = data;

}

void USART_putstring(char* StringPtr){

while(*StringPtr != 0x00){
   USART_send(*StringPtr);
   StringPtr++;}

}

Faz o seguinte: envia o a pelo terminal, e espera 5 segundos, e diz-nos se ao fim desses 5 segundos o LED desliga, sem enviares mais nada.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #53 em: 03 de Outubro de 2010, 12:44 »
(...) Ambos os tipos têm o mesmo tamanho (8 bits) e na comparação de igualdade o sinal é irrelevante.

Isso está errado ...
(...)

Sim, tens razão, parvoíce minha. Isso acontece apenas porque na expressão do if ambos os membros são promovidos a int, e como neste caso o int é de 16 bits, a diferença surge depois de promovidos. No caso do código original não havia problema (embora seja má prática) porque o 'a' é sempre positivo.

Offline GnGz

  • Mini Robot
  • *
  • Mensagens: 665
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #54 em: 03 de Outubro de 2010, 12:50 »
Aiai ... o erro foi meu... e de tar habituado ao arduino... e fazer mal os reset's... ja funciona ! o meu codigo e ma pratica?

P.S : passados 5 sec o led nao desliga

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #55 em: 03 de Outubro de 2010, 12:51 »
Má prática misturar tipos "com sinal" com "sem sinal" sem casts explícitos.

Fica um aviso: o simulador da versão do AVR studio que tenho (4.13, build 528, já é antiguinha) tem um bug que faz com que o valor escrito no UCSR0 apareça também no UBRR0H.

Ainda ninguém por aqui falou em como se usa o simulador, pois não? Se eu tivesse um tempinho...
« Última modificação: 03 de Outubro de 2010, 12:57 por Njay »

Offline GnGz

  • Mini Robot
  • *
  • Mensagens: 665
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #56 em: 03 de Outubro de 2010, 13:02 »
Má prática misturar tipos "com sinal" com "sem sinal" sem casts explícitos.

Fica um aviso: o simulador da versão do AVR studio que tenho (4.13, build 528, já é antiguinha) tem um bug que faz com que o valor escrito no UCSR0 apareça também no UBRR0H.

Ainda ninguém por aqui falou em como se usa o simulador, pois não? Se eu tivesse um tempinho...

Ainda precebo muito pouco... e nao tou nada habituado ao C.. O meu obrigado a todos...

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: Introdução ao avr-gcc usando o AvrStudio [segunda parte lançada]
« Responder #57 em: 05 de Outubro de 2010, 00:48 »
   Boa noite, hoje iremos falar de como usar os pinos do nosso micro-controlador como entradas e saídas digitais, este deveria ter sido até o primeiro tema a estudar nesta série de tutoriais pois apesar de relativamente simples é de grande uso.
Então, para começar vamos ver quais os registos que cada porto tem associado a ele. Muito basicamente um porto é um conjunto de 8 pinos do micro-controlador que associados aos mesmos registos de controlo e que são numerados alfabeticamente, PORTA, PORTB, PORTC, o numero de portos depende do numero de pinos que o encapsulamento do nosso micro-controlador tem, no caso do atmega328p temos os portos B,C e D, mas o unico que tem os 8 pinos disponível é o porto D, isto acontece porque cada pino pode ter variadas funcionalidades, por exemplo os pinos 6 e 7 do porto B também são os pinos onde se liga o oscilador(cristal), o pino 6 do porto C é onde fica o botão do reset, no porto C do pino 0 ao pino 5 temos as 6 entradas analógicas, e assim sucessivamente para os outros pinos, e isto variada de modelo para modelo pois cada um tem mais ou menos funcionalidades e mais ou menos pinos que permitem ter implementadas essas mesmas funcionalidades, porque no caso do atmega328p se o encapsulamento for TQFP(é um dos vários tipos de smd) temos mais dois pinos ligados ao ADC.
Nesta imagem podem ver a funcionalidade de cada pino e a que porto ele está associado, o chip em questão é o atmega328p usado no arduino:


E a sua relação com os nomes dados aos pinos no arduino:


   Então, como vamos nós interagir com os nossos pinos digitais?
Para começar temos um registo que define se um pino é uma entrada ou uma saída digital, esse registo é o DDRx, sendo x a letra da porta que queremos configurar, no nosso caso temos o DDRB, o DDRC e o DDRD.
Como qualquer valor lógico, cada bit do registo DDRx pode ser 0 ou 1, sendo que um bit a 1 neste registo configura um pino como saída e um 0 configura o pino como uma entrada, vou agora usar um exemplo para mostrar como é que configuramos o porto D em que os pinos 0,1,2,3 são entradas e os pinos 4,5,6,7 são saídas:
Código: [Seleccione]
DDRD = 0b11110000;
Se quisermos que sejam todos saidas:
Código: [Seleccione]
DDRD = 0b11111111;;

   E se forem todos entradas, e se eu quiser que o primeiro e o segundo sejam saídas e o resto entradas?Respondam vocês!
No caso do porto D temos que ter cuidado porque os pinos 0 e 1 são os pinos que fazem a comunicação serial, e não convém mudar os valores do registo DDRD se não podemos ter problemas de recepção ou de emissão de dados, dai usar o |= e o o &= e não o = apenas, assim declara-mos os nossos DDRD, fazemos a inicialização da USART e sabemos que vai funcionar.

   Agora que sabemos como configurar os pinos vamos ver como é que fazemos os pinos tomarem um valor definido por nós, para escrever nos pinos, ou seja usar os pinos como saídas, usamos um novo registo o registo PORTx, tal como o DDRx trocamos o x pelo porto que queremos usar.
Após configurar um pino como saída podemos escrever o que quisermos nesse mesmo pino, para isso, e partindo do pressuposto que todo o porto está configurado como saída, eis o método usado para escrever no porto:
Código: [Seleccione]
DDRD = 0b11111111; //Configura todos os pinos do porto D como saídas
PORTD = 0b11111111; //Coloca todos os pinos do porto D a 1(HIGH)

De notar que usamos = e não |=, isto poderá causar-nos problemas, como vou explicar mais á frente.
Se quisermos colocar todos os pinos a 0 fazemos assim:
Código: [Seleccione]
DDRD = 0b11111111; //Configura todos os pinos do porto D como saídas
PORTD = 0b00000000; //Coloca todos os pinos do porto D a 0(LOW)

E se for um padrão de ligado, desligado,lidago, desligado, até preencher os 8 bits?

   Agora só nos falta saber como ler um pino, afinal nós não queremos só passar dados para o exterior, também queremos recolher dados, e para os recolher usamos um terceiro registo, o registo PINx, que tal como o DDRx e PORTx trocamos o x pela letra do porto que queremos ler, primeiramente temos de configurar os pinos do porto escolhido como entradas e depois lê-mos essas mesmas entradas, assim:
Código: [Seleccione]
DDRD = 0b00000000; //Configura todos os pinos do porto D como entradas
char my_var=0; //Criamos uma variável com 8 bits para armazenar o que lemos do porto D
my_var = PIND; //E lê-mos os pinos e armazenamos esses dados na nossa variável

Mas nem sempre queremos ler um porto inteiro, podemos querer só a informação de um pino, por exemplo um botão, para isso podemos usar um método diferente:
Código: [Seleccione]
DDRD = 0b11111110; //Configura os 7 bits mais significativos do porto D como saídas e o bit menos significativo como saída;
if(PIND & (1<<PD0)){
//O código que colocar-mos aqui dentro é executado quando o pino 0 está a 1(HIGH)
}
else{
//Esta parte é executada quando o pino 0 está a 0(LOW)
}

[/code

Ou tambem podemos ler o valor de um pino para uma variavel, assim:
[code]DDRD = 0b11111110;
char my_var         //Variavel onde vamos guardar os dados
my_var = (PIND & (1<<PD0));      //E assim lemos o estado do pino 0 para a variavel my_var

Assim como temos o PD0 temos qualquer Px0..7 em que x é a letra do porto que queremos usar e o numero entre 0 e 7 é o numero do pino, usando o operador | podemos comparar vários pinos assim:

Código: [Seleccione]
DDRD = 0b1111110; //Configura os 7 bits mais significativos do porto D como saídas e o bit menos significativo como saída;
if(PIND & ((1<<PD0) | (1<<PD1))){
//o código aqui colocado será executado quando os pinos 0 e 1 estiverem a 1(HIGH)
}

Penso que já estão a perceber a ideia. ;)
Mas ainda podemos fazer mais umas coisas com o nosso pequeno chip, quando usamos um botão como já devem ter reparado, quando o botão é premido normalmente liga o pino á massa, o que provoca um 0(LOW), mas quando se deixa de premir o botão o pino fica a flutuar, ou seja o seu valor é indefinido e isso não é bom e pode gerar problemas, então o nosso atmega328p tem pull-ups internos, o que são pull-ups?
Pull-ups são resistências com um valor de resistência elevado, 10K ohms ou mais para permitir que o pino possa continuar a ser ligado a 0(LOW) sem causar um curto-circuito e queimar alguma coisa, mas que impede o pino de ficar a flutuar num estado indefinido, para isso primeiro temos de configurar os nosso pinos como entradas, e depois isto vai parecer estranho, nos pinos que escolhemos para entradas, vamos usar o registo PORTx para escrever o valor 1(HIGH) nos pinos que escolhemos como entradas e isso vai activar os pull-ups em que escrever-mos 1(HIGH) nos pinos que estão configurados como saídas, um exemplo para clarificar:
Código: [Seleccione]
DDRD = 0b00111100; //Os primeiros 2 e os últimos 2 bits estão configurados como entradas, os restantes são saídas
PORTD = 0b00000011; //Os primeiros 2 pinos continuam sem pull-ups mas os últimos 2 pinos agora têm os pull-ups activados
//Sendo os primeiros pinos os que ficam logo ao lado do 0b e os últimos estão ao lado do ponto e virgula

Agora, relembrando uma pergunta feita á algum tempo atrás, porque razão usar = e não o |= e &=~ me pode trazer problemas?
Porque como podemos ter um porto com pinos configurados como entradas e outros como saídas, e podemos ter pinos com pull-ups e outros sem como no exemplo acima, vou introduzir mais um conceito util na manipulação básica de registos, máscaras de bits.
E o que são, máscaras de bits são variáveis de 8 bits que têm um determinado padrão de 0's e 1's que estão lá para evitar por exemplo que desactivemos os pull-ups de um pino quando escrevemos para outros pinos que são saídas, vou aqui dar um pequeno exemplo usando o código de cima para exemplificar:
Código: [Seleccione]
char mascara = 0b00000011; //Esta mascara impede-me de mexer nos últimos dois bits quando utilizar operadores lógicos
DDRD = 0b00111100; //Os primeiros 2 e os últimos 2 bits estão configurados como entradas, os restantes são saídas
PORTD = 0b00000011; //Os primeiros 2 pinos continuam sem pull-ups mas os últimos 2 pinos agora têm os pull-ups activados
PORTD = 0b00101010; //Se fizer isto vou desligar o pull-up do pino 0
//Então em vez de usar o perigoso igual uso o |= para colocar os bits que quero a 1
PORTD &= 0b00101010; //Mas mesmo assim continuo a remover o pull-up do pino 0
PORTD &= (0b00101010 | mascara); //Assim já fica o pino 0 a 1(HIGH) e os outros bits continuam como eu quero

Assim já podem usar os vossos pinos como entradas e saídas digitais e tirar proveitos dos pull-ups que estão incluídos no atmega.
Sei que o assunto de máscaras e operadores lógicos com o AND( & ou &=) o OR(| ou |=) o NOT(~ ou ~=) e o XOR(^ ou ^=) são de difícil compreensão, mas qualquer duvida sobre os mesmos é só dizer, e volto a referir o tutorial alojado no AvrFreaks.com, mais concretamente aqui:
Citar
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37871

Este tutorial foi algo mais teórico, por isso vamos lá criar um programinha que lê um pino e que acende e apaga o led do arduino:
Código: [Seleccione]
Main{
Configurar os pinos, neste exemplo será do porto D
Loop infinito{
ler o valor do botão
Se led estiver ligado e botão==1 desligar led
Se led estiver desligado e botão==0 ligar led
}
}

Antes de passar para C tenho de falar noutro assunto, e que nos pode trazer problemas se não o tivermos em atenção, que é o facto de o botão não criar uma transição limpa de 0(LOW) para 1(HIGH) nem de 1(HIGH) para 0(LOW), mas sim, transita muitas vezes de estado até parar num estado definitivo, isto chama-se oscilação e pode levar a que o led se ligue e desligue várias vezes apesar de só premir-mos o botão uma vez, para evitar isso temos de usar uma técnica chamada deboucing, e existem muitos meios para atingir esse mesmo deboucing, mas o que vou usar é um método muito muito simples que recorre a um delay, podem ler mais sobre as funções de delay aqui:
Citar
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

O método é simples, lê-mos o estado do botão, se for 1(HIGH) quer dizer que não carregamos no mesmo(já mostro uma foto do circuito para perceberem melhor), se for 0(LOW) quer dizer que pressionei o botão, então vou esperar um determinado tempo, neste caso irei usar 25 mili-segundos, mas se acharem que o valor deve ser outro digam, e se o valor se mantiver 0(LOW) considero isso como uma leitura válida.
Esta lógica invertida deve-se ao facto de ter o pull-up activado, logo está a 1(HIGH) quando não estou a tocar no botão e fica 0(LOW) quando carrego no botão.
Código: [Seleccione]
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

uint8_t readButton(void);

int main(void){
DDRD &= ~(1<<PD2); //Configura o pino 2 do porto D como entrada
PORTD |= (1<<PD2); //Activa os pull-ups no pino 2 do porto D
DDRB |= (1<<PB5); //Configura o pino 5 do porto B como saida, é o digital 13 do arduino

while(1){ //Loop infinito
if(readButton()==1){ //Verifico o estado do botão
PORTB ^=(1<<PB5); //O operado ^ chama-se XOR e se um bit está a 0 ele coloca-o a 1 e se está a 1 coloca-o a 0
}
_delay_ms(250); //Delay entre toques no botão
}
}

uint8_t readButton(void){
if((PIND & (1<<PD2)) == 0){ //Se o botão foi premido
_delay_ms(25); } //Faço o debounce do mesmo
if((PIND & (1<<PD2)) == 0){ //Verifico o valor do botão
return 1; } //Se continuar a 0 é uma leitura válida
else{ //Se não continuar a 0, é uma leitura inválida
return 0; }

}

Penso que já não é necessário mostrar passo a passo como se usa o AvrStudio e o Avrdude para programar o atmega, mas relembro-vos de que têm de carregar no botão de reset sempre que querem fazer upload de um programa novo.
O circuito usado é o seguinte:
Pino 2 do porto D(digital 2 do arduino) ligado a uma das pernas do botão, e a outra perna do botão é ligada á massa(Um dos pinos chamados GND no arduino).
Aqui fica um pequeno vídeo do código a correr no arduino, apesar do pequeno debounce que implementei nem sempre funciona perfeitamente, isso pode-se dever ao facto de ter pontaria e carregar no botão enquanto ele está a fazer o delay na função main e algumas vezes pode-se ver que o led liga e desliga apesar de só carregar uma vez, isso acontece porque os botões não são todos iguais e um delay de 25ms pode não ser suficiente.


Ignorem o ruído de fundo, é apenas um filme qualquer que estava a passar na tv, mais uma vez, qualquer duvida digam e boa programação. ;)
« Última modificação: 05 de Outubro de 2010, 20:38 por senso »
Avr fanboy

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: Introdução ao avr-gcc usando o AvrStudio [terceira parte lançada]
« Responder #58 em: 05 de Outubro de 2010, 15:08 »
Está assim tão mau?  :-[
Avr fanboy

Offline Cynary

  • Mini Robot
  • *
  • Mensagens: 182
Re: Introdução ao avr-gcc usando o AvrStudio [terceira parte lançada]
« Responder #59 em: 05 de Outubro de 2010, 18:39 »
Penso que o tutorial está excelente como sempre, mas tenho alguns reparos a fazer:


Citar
no porto C do pino 0 ao pino 5 temos as 5 entradas analógicas

São 6 entradas analógicas, pois inclui o pino 0.

Citar
no nosso caso tempos o DDRB, o DDRC

tempos = temos

E penso que fizeste alguma confusão em relação ao uso do |= ...

Código: [Seleccione]
PORTD |= 0b00101010; //Mas mesmo assim continuo a remover o pull-up do pino 0
Essa afirmação é false ... só removerias o pull-up do pino 0 se usasses o =. Como tens o pull-up anteriormente, ele fica lá, visto que 1|0 = 1.
Nesse caso, a bit mask era desnecessária :P
A bit mask, como a descreveste, seria necessária, se usasses o =, mas não o |=.
Ao longo do código, tens vários exemplos desta confusão, ao dizeres que pões pinos a LOW, ou desligas a pull-up, quando usas o |=. Isso apenas é verdade quando eles já estavam desligados! Se estivessem antes ligados, o |= não os muda!

Um conselho extra acerca do uso do delay (neste caso não faz diferença, mas pode fazer noutros :P): Nunca usem uma variável como argumento do delay! Isto é porque para fazer cálculos, essa função usa floats, e como o AVR não processa floats automaticamente, é necessário carregar mais 2kB em bibliotecas para os processar (mais a lentidão associada :P). Quando se usam constantes numéricas, o compilador optimiza o código, removendo a necessidade de floats, visto que as contas são todas feitas antes da compilação. Mas se se usar uma variável, cujo valor possa mudar, as contas passam a ter de ser feitas durante a execução, o que provoca a necessidade dos floats.