• Welcome to LusoRobótica - Robótica em Português.
 

I2C por software em C/C++

Started by TigPT, 08 de January de 2010, 15:40

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

TigPT

Boas,

Alguém já implementou I2C por software em C/C++

Preciso fazer lib disso para o ARM e não me está a apetecer reinventar a roda porque estou muito apertado de timings para outros projectos.

Tyran

#1
Já mas foi em assembly 8051 ;D

Hmm, mas penso que no JeeLabs ele tem por lá qualquer coisa disso na biblioteca Ports penso eu de que...

EDIT: Acabei de ver na ports que tenho das libs do arduino e tem mesmo pelo menos assim rapidamente parece ser pois está a puxar ele as linhas :)

ricardo-reis

tiago, a lib wire do arduino faz tudo o k precisas de i2c, dá uma olhada nisso.. ;)

TigPT

Tenho estado a ver mas ela baseia-se na twi.c e está demasiado orientada à arquitectura avr, creio que até utiliza i2c no avr por hardware em vez de implementar td em software.

Obrigado pelas ajudas.

Tyran

#4
Pois, mas na do ports já é por software penso eu.

EDIT: Sim já confirmei as rotinas todas, não encontrava a sdaOut porque estava inline na classe  ;D


metRo_

mas o arm já tem algum hardware para isso certo?

TigPT

Tem mas o prof quer implementado por software  :-\

creio que já esteja minimamente funcional, ainda não testei mas deve de estar bom, depois faço debug:
#define SDA 2
#define SCL 3

//TODO rever tempos
#define I2C_SETUP_TIME 1
#define I2C_PULSE_TIME 1
#define I2C_HOLD_TIME  1


#include "types.h"
#include "io.h"

#define _SCL(val) (digitalWrite(SCL, val))
#define _SDA(val) (digitalWrite(SDA, val))
#define _SDA_IN (digitalRead(SDA))

void i2c_init()
{
pinMode(SDA, OUTPUT);
pinMode(SCL, OUTPUT);
_SDA(HIGH);
_SCL(HIGH);
}

void i2c_start_seq()
{
_SDA(HIGH);
_SCL(HIGH);
_SDA(LOW);
_SCL(LOW);
_SDA(HIGH);
_SCL(HIGH);
}

void i2c_stop_seq()
{
_SCL(LOW);
_SDA(LOW);
_SCL(HIGH);
_SDA(HIGH);
}

void i2c_begin_transmission(int addr)
{
i2c_start_seq();
i2c_send(addr);
//shiftOut(SDA, SCL, MSBFIRST, addr);
//scl(HIGH);
}

void i2c_end_transmission()
{
i2c_stop_seq();
}

void i2c_send(int byte)
{
_SCL(LOW);
int mask = 0x80;
for (; mask != 0; mask >>= 1) {
_SDA(data & mask);
_SCL(HIGH);
_SCL(LOW);
}
_SDA(HIGH);
_SCL(HIGH);
int ack = ! _SDA_IN();
_SCL(LOW);
return ack;
}

//TODO confirm with datasheet
int i2c_read(){
int data = 0;
int mask = 0x80;
for (; mask != 0; mask >>= 1) {
_SCL(HIGH);
if (_SDA_IN())
    data |= mask;
_SCL(LOW);
}
_SCL(HIGH);
_SCL(LOW);
_SDA(HIGH);
return data;
}



Raul

Estás a fazer um braço robotico?
Não sei ao certo o que queres dizer com ARM
Cumprimentos

TigPT

http://www.arm.com/

É uma familia de microcontroladores tal como a AVR, Microchip, NXP, etc..

Njay

É melhor colocares uns delays para garantires uma frequência máxima de execução... a não ser que o teu chip sejam bem lentinho.

TigPT

Tinha me esquecido, está a 60Mhz, é melhor! Obrigado ;)

metRo_

Quote from: Njay on 08 de January de 2010, 20:43
É melhor colocares uns delays para garantires uma frequência máxima de execução... a não ser que o teu chip sejam bem lentinho.

Isto é para quando por exemplo faço:
for(xpto<100){
   void i2c_send(blabla);
}


ele não enviar os bytes a uma maior frequência do que devia, certo?

Não seria melhor utilizar um timer com esse tempo que vais colocar nos delays e quando este gerar a interrupção alteras uma variável para saber se já foi enviado o byte ou não e se já podes enviar novamente.

TigPT

É mais entre transições de sinais para garantir o bitrate i2c compatível.

Isto é só para nos fazer sentir o protocolo todo que depois fazemos por hardware e não é preciso preocupar com nada.

StarRider

Quote from: TigPT on 08 de January de 2010, 17:16
Tem mas o prof quer implementado por software  :-\

creio que já esteja minimamente funcional, ainda não testei mas deve de estar bom, depois faço debug:
#define SDA 2
#define SCL 3

//TODO rever tempos
#define I2C_SETUP_TIME 1
#define I2C_PULSE_TIME 1
#define I2C_HOLD_TIME  1


#include "types.h"
#include "io.h"

#define _SCL(val) (digitalWrite(SCL, val))
#define _SDA(val) (digitalWrite(SDA, val))
#define _SDA_IN (digitalRead(SDA))

void i2c_init()
{
pinMode(SDA, OUTPUT);
pinMode(SCL, OUTPUT);
_SDA(HIGH);
_SCL(HIGH);
}

void i2c_start_seq()
{
_SDA(HIGH);
_SCL(HIGH);
_SDA(LOW);
_SCL(LOW);
_SDA(HIGH);
_SCL(HIGH);
}

void i2c_stop_seq()
{
_SCL(LOW);
_SDA(LOW);
_SCL(HIGH);
_SDA(HIGH);
}

void i2c_begin_transmission(int addr)
{
i2c_start_seq();
i2c_send(addr);
//shiftOut(SDA, SCL, MSBFIRST, addr);
//scl(HIGH);
}

void i2c_end_transmission()
{
i2c_stop_seq();
}

void i2c_send(int byte)
{
_SCL(LOW);
int mask = 0x80;
for (; mask != 0; mask >>= 1) {
_SDA(data & mask);
_SCL(HIGH);
_SCL(LOW);
}
_SDA(HIGH);
_SCL(HIGH);
int ack = ! _SDA_IN();
_SCL(LOW);
return ack;
}

//TODO confirm with datasheet
int i2c_read(){
int data = 0;
int mask = 0x80;
for (; mask != 0; mask >>= 1) {
_SCL(HIGH);
if (_SDA_IN())
    data |= mask;
_SCL(LOW);
}
_SCL(HIGH);
_SCL(LOW);
_SDA(HIGH);
return data;
}



Boas,

Não percebi bem, esse código é ser executado num ARM ? Com que compilador ?