collapse

* Posts Recentes

Arame de Estendal por almamater
[Ontem às 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]


Emulador NES em ESP32 por dropes
[10 de Abril de 2024, 15:30]


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: I2C por software em C/C++  (Lida 17223 vezes)

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

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #15 em: 09 de Janeiro de 2010, 22:36 »
Sim, em arm com o arm-elf-gcc

O que não percebeste?
« Última modificação: 09 de Janeiro de 2010, 22:37 por TigPT »

StarRider

  • Visitante
Re: I2C por software em C/C++
« Responder #16 em: 10 de Janeiro de 2010, 00:02 »
Sim, em arm com o arm-elf-gcc

O que não percebeste?


Boas,

Pois, a minha duvida está no facto de "digitalWrite()" e "pinMode()" serem funções nativas do
compilador do Arduino e eu desconhecer que as mesmas existam nas libs de qualquer toolchain
para ARM, incluindo o arm-gcc.

Mas é claro que podes sempre implementar tu as funções, se bem que uma vez que já tens o
define "#define _SCL(val)" o mais lógico seria definir logo aqui os GPIOs, algo no género:

#define BIT(NUM) (0x00000001 << NUM)
#define _SCL(val)  IO0SET = BIT(NUM)

Em que o NUM corresponde ao bit que controla a porta que desejas usar.

Mas como no ARM o estado dos GPIOs são tratados com dois registos separados, vais ter que
usar algo mais no género de:

#define BIT(NUM) (0x00000001 << NUM)
#define _SCL(val)  val==HIGH ? IO0SET = BIT(NUM) : IOCLR = BIT(NUM)

Isto se estivermos a falar do LPC210x, que se estou recordado é o que vais usar.

Abraços
Paulo A.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: I2C por software em C/C++
« Responder #17 em: 10 de Janeiro de 2010, 00:06 »
Já agora uma achegazinha em relação às macros em geral. É boa prática de programação envolver sempre os argumentos de uma macro entre parentesis, no corpo da macro. Por exemplo a macro bit acima,

#define BIT(NUM) (0x00000001 << NUM)

funciona bem enquanto usarmos argumentos "simples" como

BIT(2) ou BIT (ctr)

mas falha se fizermos

BIT(ctr + 1)  BIT(ctr == 1? 2 : 3)  (corrigido, ver mais abaixo no tópico, obrigado ao StarRider!)

Daí que convém definir com os argumentos entre parentesis, como

#define BIT(NUM) (0x00000001 << (NUM))
« Última modificação: 10 de Janeiro de 2010, 14:52 por Njay »

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re: I2C por software em C/C++
« Responder #18 em: 10 de Janeiro de 2010, 00:19 »
Já agora uma achegazinha em relação às macros em geral. É boa prática de programação envolver sempre os argumentos de uma macro entre parentesis, no corpo da macro. Por exemplo a macro bit acima,
#define BIT(NUM) (0x00000001 << NUM)
funciona bem enquanto usarmos argumentos "simples" como
BIT(2) ou BIT (ctr)
mas falha se fizermos
BIT(ctr + 1)
Daí que convém definir com os argumentos entre parentesis, como
#define BIT(NUM) (0x00000001 << (NUM))

Podes explicar o porque disto acontecer?

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: I2C por software em C/C++
« Responder #19 em: 10 de Janeiro de 2010, 00:30 »
Se não me engano, tem a ver com as precedências.
Não tenho a certeza do que acontece neste caso (shift) mas provavelmente o que ele faz é NUM shifts e depois soma 1 ao resultado (no exemplo que o Njay deu) quando o que se pretendia era fazer (NUM+1) shifts.

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #20 em: 10 de Janeiro de 2010, 00:35 »
Pois, a minha duvida está no facto de "digitalWrite()" e "pinMode()" serem funções nativas do
compilador do Arduino e eu desconhecer que as mesmas existam nas libs de qualquer toolchain
para ARM, incluindo o arm-gcc.
Não são funções nativas de Arduino porque o Arduino não é uma arquitectura nem um compilador, é uma mera API + bootloader.

Sim, implementei funções com esses nomes por ser mais sugestivo e permitir mais tarde fazer porte de Arduino para ARM se existir interesse e tempo.

Não é nada interessante utilizar valores expostos da arquitectura por uma simples razão, é uma biblioteca, é suposto ser portável e flexível. Em vez de ser um conjunto de horas de trabalho enorme que depois não são facilmente migráveis para outros projectos.

Depois posto o resto do código quando estiver mais organizado. (contudo está disponível no SVN para os curiosos)


Podes explicar o porque disto acontecer?

Simplesmente porque não sabes onde a tua macro vai ser utilizada e assim proteges de anomalias tais como pós notação.

#define BIT(NUM) (0x00000001 << NUM)

BIT(3) // origina 3 shifts
BIT(3+1) origina 3 shits e a soma do int 1 no fim dos shits pois o shit tem prioridade à soma.

PS - msr tinha respondido ao mesmo tempo que eu.
« Última modificação: 10 de Janeiro de 2010, 00:40 por TigPT »

StarRider

  • Visitante
Re: I2C por software em C/C++
« Responder #21 em: 10 de Janeiro de 2010, 03:18 »
Não são funções nativas de Arduino porque o Arduino não é uma arquitectura nem um compilador, é uma mera API + bootloader.


Meu caro TigPT,

Arquitectura ? não mencionei essa palavra, o que eu mencionei foi compilador, e ai sim "I stand my
ground" !

A filosofia "Arduino", engloba varias componentes, sendo que o que realmente faz a diferença é
o "Ambiente" Arduino, aquilo que geralmente se chama de IDE e serve para desenvolver o
código "Arduino" que depois será carregado no AVR.

Como em qualquer outro IDE , o do Ambiente de Desenvolvimento do Arduino é constituído por
uma LINGUAGEM, que no caso é baseada no C/C++. A implantação da LINGUAGEM ARDUINO é
somente baseada em C/C++, não é 100% compatível com o padrão ISO/ANSI que especifica
a totalidade da linguagem C/C++.

Como em qualquer linguagem, o Arduino C/C++ tem as suas especificidades, e como qualquer
linguagem o "Ambiente de Desenvolvimento do Arduino" tem a sua "Language Reference".

Acontece que a "Language Reference" do COMPILADOR utilizado pelo IDE do Arduino refere
claramente um conjunto de funções e constantes que são NATIVAS do ambiente/compilador
em si, entre elas estão as funções que "tratam" dos IOs: pinMode,  digitalWrite e digitalRead.

Por isso, sim, o Arduino engloba um IDE com UM COMPILADOR, sendo o compilador baseado
no avr-gcc.

E  pinMode,  digitalWrite e digitalRead são funções que fazem parte da lib do COMPILADOR do
Arduino, dai serem NATIVAS ao COMPILADOR do Arduino e não existirem “nativamente” em mais
nenhum compilador de C/C++.

Já uma API é uma coisa totalmente diferente e que nada tem a ver para o caso, uma API é
uma interface entre um software e um cliente que usa as suas funcionalidades sem sequer
saber dos detalhes da implementação. Se quiseres podemos aprofundar este tema, mas nada
tem a ver para este caso.

No Arduino o que tu tens é IDE (Ambiente de Desenvolvimento) onde escreves o código, aquilo
que em Arduino se chama  “sketch” , fazes a COMPILAÇÃO, e fazes o upload do código compilado
para o AVR, que ai sim, tem um bootloader.

O bootloader  é um pequeno programa residente no AVR e que serve somente para que o IDE
Arduino possa carregar o código COMPILADO para o AVR, e depois de carregado faz o reset da
board e executa o código que foi carregado, deixando de ter qualquer posterior uso durante a
execução do mesmo.

Por acaso até é possível carregar o código gerado pelo COMPILADOR Arduino sem usar o bootloader
do Arduino, basta usar um programador externo, como o AVRDude ou o AVRprog, por exemplo.

É claro que o IDE Arduino ("Arduino software" ou "Arduino environment" como é descrito por vezes)
tem um compilador, de que outra forma achas tu que o AVR conseguia executar o código ? O AVR
não tem um interpretador. O Arduino usa a toolchain avr-gcc para compilar, o avrdude para
fazer o upload e a lib avr-libc.

O sucesso do Arduino, e a sua principal força, é o seu IDE e as funções disponibilizadas por este
nas suas libs, essas funções, como o pinMode,  digitalWrite e digitalRead, vieram permitir que
muitos que não compreendem nem sabem o que está “por detrás” possam utilizar um uC de uma
forma simples e rápida, mas isso vem com um preço, e o preço é depois nos faltam as bases
quando queremos ir mais alem, mas nada como ler as datasheets, está lá tudo, boa sorte na
tua demanda.

Não é nada interessante utilizar valores expostos da arquitectura por uma simples razão, é uma biblioteca, é suposto ser portável e flexível. Em vez de ser um conjunto de horas de trabalho enorme que depois não são facilmente migráveis para outros projectos.

Era somente um exemplo, usa-o da forma que consideres melhor para o projecto em causa, como
define, macro ou numa função, a ideia era somente partilhar a informação.


Abraços
Paulo A.
« Última modificação: 10 de Janeiro de 2010, 04:01 por StarRider »

StarRider

  • Visitante
Re: I2C por software em C/C++
« Responder #22 em: 10 de Janeiro de 2010, 03:25 »
Já agora uma achegazinha em relação às macros em geral. É boa prática de programação envolver sempre os argumentos de uma macro entre parentesis, no corpo da macro. Por exemplo a macro bit acima,

#define BIT(NUM) (0x00000001 << NUM)

funciona bem enquanto usarmos argumentos "simples" como

BIT(2) ou BIT (ctr)

mas falha se fizermos

BIT(ctr + 1)

Daí que convém definir com os argumentos entre parentesis, como

#define BIT(NUM) (0x00000001 << (NUM))

Boas,

Sim, tens razão. 

Esse "define" serve somente para demonstrar que se trata de "um bit" para cada porta num registo
de 32 bits, dependendo da forma como o código é implementando, numa função por exemplo, acaba
por nem ser necessário.

Abraços,
Paulo A.


StarRider

  • Visitante
Re: I2C por software em C/C++
« Responder #23 em: 10 de Janeiro de 2010, 12:22 »

Simplesmente porque não sabes onde a tua macro vai ser utilizada e assim proteges de anomalias tais como pós notação.

#define BIT(NUM) (0x00000001 << NUM)

BIT(3) // origina 3 shifts
BIT(3+1) origina 3 shits e a soma do int 1 no fim dos shits pois o shit tem prioridade à soma.

PS - msr tinha respondido ao mesmo tempo que eu.

Boas,

Não, desculpa mas estás errado,  na expressão (0x00000001 << 3+1), que é a
gerada pelo preprocessador,  ou pelo compilador em si se não tiver reprocessador,
e seguindo as normas  ISO/ANSI  usadas por todos os compiladores conhecidos
o operador "+" tem procedência sobre o "<<"  !

A expressão evolui para (0x00000001 << 4), e só depois é feito o shift!

Logo, o shift SERÁ SEMPRE 4 BITS !

Acho que se deve ter um pouco mais de cuidado com as afirmações que fazemos,
pois podemos estar a induzir os outros em erro.

Para quem não se "recorda" das regras, aqui ficam alguns links... muitos outras fontes
existem, ou então consultem os manuais dos vossos compiladores:
http://www.cppreference.com/wiki/operator_precedence
http://msdn.microsoft.com/en-us/library/126fe14k.aspx

Ou então experimentem vocês mesmo, façam algo neste género:

#define BIT(NUM) (0x00000001 << NUM)
void main()
{
    long xpto;
    xpto = BIT(3+1);
    printf("%l", xpto);
}

E vão ver que o resultado é 16 ou seja b0000 0000 0000 0000 0000 0000 0001 0000

Abraços
Paulo A.


« Última modificação: 10 de Janeiro de 2010, 12:38 por StarRider »

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #24 em: 10 de Janeiro de 2010, 12:35 »
Ainda não tive tempo de ler todo o post mas deixo já uma nota:

http://www.cplusplus.com/doc/tutorial/operators/

Tabela do fim da página:
Citar
From greatest to lowest priority, the priority order is as follows:


Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #25 em: 10 de Janeiro de 2010, 13:06 »
Concordo com grande parte do que disseste, contudo há uma coisa que não entendo...

O que é uma "Linguagem de Programação"?
Para mim uma linguagem de programação é um conjunto de keywords e sintaxe que permite descrever de forma textual comportamentos do hardware que o vai executar.

Assembler, C, C++, C#, Java, Pascal, Cobol, PHP, entre muitas outras, têm uma coisa em comum entre elas, embora se baseiem todas umas nas outras (naturalmente) nenhuma é compatível entre si pois utilizam keywords e sintaxes diferentes.

Arduino, ObjectiveC, SWING, AWP, entre outras, são APIs, blocos de código compatíveis com uma linguagem base que permitem estende-la facilitando assim a vida ao programador evitando estar sempre a repetir código.

Vamos então olhar para writing_digital.c da API Arduino:
http://code.google.com/p/arduino/source/browse/trunk/hardware/arduino/cores/arduino/wiring_digital.c

Código: [Seleccione]
void pinMode(uint8_t pin, uint8_t mode)
{
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);
        volatile uint8_t *reg;

        if (port == NOT_A_PIN) return;

        // JWS: can I let the optimizer do this?
        reg = portModeRegister(port);

        if (mode == INPUT) *reg &= ~bit;
        else *reg |= bit;
}

Como  se pode ver, de forma muito clara, esta função é um call a um boloco de código em C-AVR que permite alterar o modo de funcionamento do pin em questão para o segundo argumento passado.

Comparemos com o meu código para ARM:
http://code.google.com/p/lpc210x/source/browse/trunk/libs/io.c

Código: [Seleccione]
void pinMode(int pin, int mode){
        if (mode)
                io_write_U32(GPIO + IODIR, io_read_U32(GPIO + IODIR) | (1 << pin));
        else
                io_write_U32(GPIO + IODIR, io_read_U32(GPIO + IODIR) & ~(1<<pin));     
}

void io_write_U32(U32 addr, U32 val)
{
        *(U32 *) addr = val;
}

Mais uma vez, uma call para um bloco de código que modifica o funcionamento de um pin nesta em C-ARM.

O que quero dizer é que no meu ponto de vista (muitos poderão discordar e gostava de ouvir porque para poder reeducar-me se achar que estou errado) são meras APIs, isto é, blocos de código que facilitam a vida ao programador, mas não são uma linguagem de programação pois não são conjuntos de keywords e sintaxes que permitem escrever código de forma diferente, apenas escondem parte das rotinas pois elas são tipicamente iguais.

Espero que todos estejam cientes que as minhas palavras são apenas minhas, neste meu processo critico de aprendizagem onde tento expor o que sei e o que penso para que possamos em conjunto criticar as minhas observações e molda-las para um conhecimento mais correcto.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: I2C por software em C/C++
« Responder #26 em: 10 de Janeiro de 2010, 14:49 »
Por acaso estava convencido que os operadores de deslocamento tinham precedência sobre a soma (na prática nunca tenho problemas com isso porque apenas "confio" na precedência das operações aritméticas e uso parentesis para tudo o resto).

De qualquer forma a achega mantém-se, pois há outras formas de a coisa correr mal nesta macro, como

BIT(ctr & 7)
BIT(ctr == 1? 2 : 3)

e outros.

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #27 em: 10 de Janeiro de 2010, 14:53 »
Sou só eu que estou a ler de forma diferente?

http://www.cppreference.com/wiki/operator_precedence
Citar
The operators at the top of this list are evaluated first.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: I2C por software em C/C++
« Responder #28 em: 10 de Janeiro de 2010, 14:59 »
Não percebi Tiago...

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re: I2C por software em C/C++
« Responder #29 em: 10 de Janeiro de 2010, 15:01 »
Esquece.. estou mesmo a dar em doido, é esta dor de estomago que tenho desde manhã que me está a afectar o raciocinio!