Вопрос по коду

GregoryAT
Offline
Зарегистрирован: 06.01.2015

Приветствую Всех.

Прошу помощи в переводе кода с PIC на платформу Arduino.

Из задачи:

Пример программного кода Мастера I2C
Этот пример показывает, как написать программное обеспечение Мастера I2C , включающее поддержку длинных синхро импульсов. Он написан на Cи для процессора PIC, но может быть перенесен на большинство процессоров с минимальными изменениями.

Так как линии SCL и SDA имеют открытый тип утечки, мы используем регистр управления с тремя состояниями, чтобы управлять выводом, сохраняя на выходе низкий уровень сигнала. Выводы порта должны по-прежнему читаться, так как они определены через SCL_IN и SDA_IN. Эти определения и их инициализация, вероятно, все, что Вы должны изменить в программе для другого процессора.

#define SCL     TRISB4 // шина I2C
#define SDA     TRISB1 //
#define SCL_IN  RB4    //
#define SDA_IN  RB1    // 

Для того, чтобы инициализировать порты, нужно установить выходные резисторы в 0 и регистры с тремя состояниями в 1, что отключит выводы и позволит установить на них высокий уровень сигнала с помощью резисторов.

SDA = SCL = 1;
SCL_IN = SDA_IN = 0;

Мы используем маленькую подпрограмму задержки между изменениями в SDA и SCL, чтобы дать четкую последовательность на шине I2C. Это не больше чем просто вызов подпрограммы и возврат из нее.

void i2c_dly(void)

{
}

Следующие 4 функции делают: примитивное начало, завершение, чтение и запись последовательности. Все транзакции по шине I2C могут быть выполнены на основе этих функций.
 

void i2c_start(void)
{
  SDA = 1;             // последовательность стартовых битов i2c
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 0;
  i2c_dly();
  SCL = 0;
  i2c_dly();
}

void i2c_stop(void)
{
  SDA = 0;             // последовательность завершающих битов i2c
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 1;
  i2c_dly();
}

.............................................................

Как вышеуказанное будет "выглядеть" (для пинов A4,A5 (SDA,SCL)) для Ардуино?

Прошу Вашей помощи!

С уважением, GregoryAT.

p.s. Интересует именно момент инициализации (программно) портов для I2C и конкретно из приведённого кода.

 

 

andryn
Offline
Зарегистрирован: 08.06.2018

Посмотрите hardware\arduino\avr\libraries\Wire\src\utility\twi.c , void twi_init(void), void twi_disable(void)

Оно?

GregoryAT
Offline
Зарегистрирован: 06.01.2015

andryn пишет:

Посмотрите hardware\arduino\avr\libraries\Wire\src\utility\twi.c , void twi_init(void), void twi_disable(void)

Оно?

Благодарю за ответ andryn.

Смотрел, но мне необходимо перевести именно то что описано выше (в моём посте).

Если я просто "возьму" например void twi_init(void), то ещё проще Wire.beginTransmission(address) и

Wire.endTransmission() ...

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

1. Пример софт-И2С - говенный. В том смысле, что неправильный.

2. А4 и А5 - пины для ХАРД-И2С, то есть аппаратного, можно на них и софтверный заводить.

3. примеров софт И2С под АВР (Ардуино)- дохера и больше, с разной аккуратностью и разной степенью вовлеченности ассемблера.

В теме "Attiny13 101 применение" есть моя личная реализация.... щас поищу... нашел - сообщение 966

вот код софт-и2с без ассемблера, изучай, он для тиньки, для 328 сам переделаешь. Обрати внимание на закоментированные while!!!! С т.н. "медленным слейвом" работать можно только раскоментировав это циклы ожидания освобождения шины. Для экрана 1602 или RTC - можно без них. Этот код старый и некрасивый. Если что - я поищу посвежее.

... и да, если не секрет, за каким хером тебе нужен софт-И2С?

#define _NOP() asm volatile("nop")

// delay() для тиньки и свой нормальный, а delayMicroseconds() дурной
//поэтому свой нужен

//а вот глобального такого дефайна может и не быть, как ни странно, так для страховки завел
#define F_CPU 4800000UL
#define LOOP_CYCLES 8
#define us(num) (num/(LOOP_CYCLES*(1/(F_CPU/1000000.0))))

inline __attribute__((gnu_inline)) void asm_delay(uint16_t delay){
  uint16_t u=us(delay);
do _NOP(); while(delay--);
}

#define wdelay_us(x)  asm_delay(us(x))
#define wdelay(x) delay(x)


/*****************************************************/
//дальше мелкий вариант i2c на любых ногах
//если работать через функции (закоментировано) то будет переносимость хоть куда

#define IICR  1
#define IICW  0
// на 100КГц примерно по 4 мкс нужно держать уровни SCL - со скоростью сами экспериментируйте, мне не нужно было
#define I2CDelay()  wdelay_us(5)
#define SDA_Pin   0
#define SCL_Pin   1

/*
#define SDA_In()    digitalRead(SDA_Pin)
#define SCL_In()    digitalRead(SCL_Pin)

     void SDA_Hi()  { digitalWrite(SDA_Pin, HIGH); pinMode(SDA_Pin,  INPUT);}
     void SDA_Lo()  { digitalWrite(SDA_Pin, LOW ); pinMode(SDA_Pin, OUTPUT);}
     void SCL_Hi()  { digitalWrite(SCL_Pin, HIGH); pinMode(SCL_Pin,  INPUT);}
     void SCL_Lo()  { digitalWrite(SCL_Pin, LOW ); pinMode(SCL_Pin, OUTPUT);}
*/
#define SDA_In()    (PINB & 0B00000001)
#define SCL_In()    (PINB & 0B00000010)

     inline void SDA_Hi()  { PORTB |= 0B00000001; DDRB &= 0B11111110;}
     inline void SDA_Lo()  { PORTB &= 0B11111110; DDRB |= 0B00000001;}
     inline void SCL_Hi()  { PORTB |= 0B00000010; DDRB &= 0B11111101;}
     inline void SCL_Lo()  { PORTB &= 0B11111101; DDRB |= 0B00000010;}

void I2CInit (void)
{
    SDA_Hi();
    SCL_Hi();
}

void I2CStart (void)
{
  SCL_Hi();
  //while (!SCL_In());
  I2CDelay();
  SDA_Lo();
  I2CDelay();
  SCL_Lo();  
  
}
 
void I2CStop (void)
{
  SCL_Lo();
  SDA_Lo();
  I2CDelay();
  SCL_Hi();
  //while(!SCL_In());
  I2CDelay();
  SDA_Hi();
  I2CDelay();
}

boolean I2CWrite(byte b)
{
  byte i = 1<<7;
  boolean ack=0;

  while(i)
    {
      //I2CDelay();
      if (b & i) SDA_Hi(); else SDA_Lo();
      I2CDelay();
      SCL_Hi();
      I2CDelay();
      SCL_Lo();
      
      i>>=1; 
    }
  SDA_Hi();
  I2CDelay();
  SCL_Hi();
 // while(!SCL_In());

  if ( SDA_In()==0 ) ack = 1;
  I2CDelay();
  SCL_Lo();
  SDA_Hi();
  return ack;
}

byte I2CRead(boolean ack)
{
  byte i=8;
  byte b=0;
  
  while(i--)
  {
   b <<= 1;
   SCL_Lo();
   SDA_Hi();
   I2CDelay();
   SCL_Hi();
   //while(!SCL_In());
   if (SDA_In()) b |= 1;
   
   I2CDelay();
   SCL_Lo();
  }
  if (ack) SDA_Lo();
  else SDA_Hi();
  I2CDelay();
  SCL_Hi();
  //while(!SCL_In());
  I2CDelay();
  SCL_Lo();
  return (b);
}

 

GregoryAT
Offline
Зарегистрирован: 06.01.2015

to:wdrakula

Благодарю за помощь, буду разбираться.

p.s. to All, пост по-прежнему актуален.

С уважением, GregoryAT.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

GregoryAT пишет:

Как вышеуказанное будет "выглядеть" (для пинов A4,A5 (SDA,SCL)) для Ардуино?

Стесняюсь спросить, на какой твой вопрос не получен ответ в моем коде?

Слепой или тупой?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

wdrakula пишет:

Стесняюсь спросить, на какой твой вопрос не получен ответ в моем коде?

Слепой или тупой?

Ответ - афтор мозахист.

GregoryAT
Offline
Зарегистрирован: 06.01.2015

to:wdrakula
Теперь уже я стесняюсь спросить:
//Стесняюсь спросить, на какой твой вопрос не получен ответ в моем коде?
//
Если по поводу приведённого Вами листинга, то я поблагодарил Вас и сообщил что буду разбираться, разве я что-нибудь написал Вам по поводу Вашего кода?
И ещё, кому Вы адресуете вопрос:
Слепой или тупой?
to:mykaida:
От Вас, уважаемый вообще "тишина" (по поводу поста), так Вы ещё
умудряетесь предпринимать попытки оскорблять. Вам заняться нечем?

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

GregoryAT пишет:

to:mykaida:
От Вас, уважаемый вообще "тишина" (по поводу поста), так Вы ещё
умудряетесь предпринимать попытки оскорблять. Вам заняться нечем?

Ну как сказать - Вы (Вы) хотите писать ассемблер на си? Флаг Вам в руки. Зачем?

GregoryAT
Offline
Зарегистрирован: 06.01.2015

from:mykaida

Ну как сказать - Вы (Вы) хотите писать ассемблер на си? Флаг Вам в руки. Зачем?

to:mykaida

Вам оно надо?

p.s.А флаг оставьте при себе.

GregoryAT
Offline
Зарегистрирован: 06.01.2015

to: wdrakula:

Большое спасибо за помощь, то что надо.

С уважением, GregoryAT.