Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Общетехнические вопросы

Общетехнические вопросы Общие вопросы аналоговой и цифровой электроники.

Ответ
 
Опции темы Опции просмотра
Старый 17.01.2015, 10:45   #1
Vovka
Senior Member
 
Аватар для Vovka
 
Регистрация: 27.12.2007
Адрес: недалеко от г.Белгорода
Возраст: 50
Сообщений: 1,845
Вес репутации: 2668/81
Vovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond repute
Отправить сообщение для Vovka с помощью ICQ
Question Софтовый I2C, чем лыжи мазать?

MCC18, PIC18F4525, DS1703

DS1703 припаяна к RC3,RC4, хардовый I2C работает!
Отключаю модуль, делаю на софте - в ошибки не вылетает, но стабильно читает ерунду.
В общем вчера убил весь день, перепробовал кучу вариантов из интернета, но софтовый I2C так и не смог запустить
В голове уже полная каша!
Вот последняя версия, переделанная из исходника от хайтека:
Код:
extern volatile unsigned char    OutPortC,OutTrisC;
//--                               76543210
#define I2C_SCL_BIT     0b00001000 // такты
#define I2C_SCL_BIT_   0b11110111
#define I2C_SDA_BIT    0b00010000 // данные
#define I2C_SDA_BIT_   0b11101111
#define I2C_SCL_PORT                PORTC
#define I2C_SCL_PORT_VALUE    OutPortC
#define I2C_SCL_TRIS                TRISC
#define I2C_SCL_TRIS_VALUE    OutTrisC
#define I2C_SDA_PORT                PORTC
#define I2C_SDA_PORT_VALUE    OutPortC
#define I2C_SDA_TRIS                TRISC
#define I2C_SDA_TRIS_VALUE    OutTrisC

//---
#define SCL_IN()                 (I2C_SCL_PORT&I2C_SCL_BIT)
#define SDA_IN()                 (I2C_SDA_PORT&I2C_SDA_BIT)
#define SCL_TRIS_INPUT()    {I2C_SCL_TRIS_VALUE|=I2C_SCL_BIT;  I2C_SCL_TRIS=I2C_SCL_TRIS_VALUE;}
#define SDA_TRIS_INPUT()    {I2C_SDA_TRIS_VALUE|=I2C_SDA_BIT;  I2C_SDA_TRIS=I2C_SDA_TRIS_VALUE;}
#define SCL_TRIS_OUTPUT()  {I2C_SCL_TRIS_VALUE&=I2C_SCL_BIT_; I2C_SCL_TRIS=I2C_SCL_TRIS_VALUE;}
#define SDA_TRIS_OUTPUT()  {I2C_SDA_TRIS_VALUE&=I2C_SDA_BIT_; I2C_SDA_TRIS=I2C_SDA_TRIS_VALUE;}
#define SCL_HIGH()               {I2C_SCL_PORT_VALUE|=I2C_SCL_BIT;  I2C_SCL_PORT=I2C_SCL_PORT_VALUE; SCL_TRIS_INPUT();}
#define SDA_HIGH()               {I2C_SDA_PORT_VALUE|=I2C_SDA_BIT;  I2C_SDA_PORT=I2C_SDA_PORT_VALUE; SDA_TRIS_INPUT();}
#define SCL_LOW()                {I2C_SCL_PORT_VALUE&=I2C_SCL_BIT_; I2C_SCL_PORT=I2C_SCL_PORT_VALUE; SCL_TRIS_OUTPUT();}
#define SDA_LOW()                {I2C_SDA_PORT_VALUE&=I2C_SDA_BIT_; I2C_SDA_PORT=I2C_SDA_PORT_VALUE; SDA_TRIS_OUTPUT();}

// Задержка 1мкс на 40МГц
void i2c_delay1xUS( unsigned char t )
{
 unsigned char Reg_1;
 do
   {
    _asm
     movlw	2
     movwf	Reg_1,1
     decfsz	Reg_1,1,1
     bra	-2
     clrwdt
    _endasm
   } while(--t);
}
void i2c_stop(void)
{
 SCL_LOW();
 SDA_LOW();
 i2c_delay1xUS(1);
 SCL_TRIS_INPUT();
 i2c_delay1xUS(4);
 SDA_HIGH();
 i2c_delay1xUS(5);
 SDA_TRIS_INPUT();
}

void i2c_start(void)
{
 SCL_LOW();
 SDA_HIGH();
 i2c_delay1xUS(1);
 SCL_TRIS_INPUT();
 i2c_delay1xUS(4);
 SDA_LOW();
 i2c_delay1xUS(4);
}

unsigned char i2c_write(unsigned char d)
{
 char i; unsigned char byte = d;
 for(i=0; i<8; i++) {
   SCL_LOW();
   if(byte&0x80)	{ SDA_HIGH(); } // передать 1
   else		{ SDA_LOW(); }
   byte <<= 1;
   i2c_delay1xUS(1);
   SCL_TRIS_INPUT();
   if(!SCL_IN()) { i2c_delay1xUS(10); if(!SCL_IN()) return 8; }
   i2c_delay1xUS(4);
 }
 return 0;
}

unsigned char i2c_readbyte(unsigned char *d, unsigned char status )
{
 unsigned char i;
 unsigned char byte = 0;
 for(i=0; i<8; i++) {
   SCL_LOW();
   i2c_delay1xUS(5);
   SDA_TRIS_INPUT();
   SCL_TRIS_INPUT();
   if(!SCL_IN()) { i2c_delay1xUS(10); if(!SCL_IN()) return 9; }
   i2c_delay1xUS(4);
   byte = byte << 1;
   if( SDA_IN() ) byte |= 1;
 }
 *d = byte;

 SCL_LOW();
 if ( status ) {SDA_LOW();}
 else		{SDA_HIGH();}
 i2c_delay1xUS(1);
 SCL_TRIS_INPUT();
 i2c_delay1xUS(4);
 return 0;
}
unsigned char i2c_read( unsigned char Adr, unsigned char *pData, unsigned char count )
{
 unsigned char a;
 i2c_stop();	// для профилактики ;)
 i2c_start();
 if( i2c_write( 0xD0 ) ) return 2;	// на передачу
 if( i2c_write( Adr  ) ) return 3;	// адрес в DS1307, куда будем писать
 i2c_restart();
 if( i2c_write( 0xD1 ) ) return 4;	// читаем...

 if( count ) {
   for( a=0; a<count-1; a++ ) { // читаем на 1 бейт меньше с ASK
     if( i2c_readbyte( &pData[a], 1 ) ) return 5;
   }
 }
 a = i2c_readbyte( &pData[a], 0 );// читаем без ASK
 i2c_stop();
 return a;
}
Vovka на форуме   Ответить с цитированием
Старый 17.01.2015, 16:41   #2
ampersant
Senior Member
 
Аватар для ampersant
 
Регистрация: 26.02.2008
Адрес: IgorV
Сообщений: 2,318
Вес репутации: 4442/103
ampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond reputeampersant has a reputation beyond repute
По умолчанию Re: Софтовый I2C, чем лыжи мазать?

Цитата:
Сообщение от Vovka Посмотреть сообщение
MCC18, PIC18F4525, DS1703

Че так сложно то?
Ну и при отсутствии арбитража на SCL (т.е. slave хардовый, и не может удерживать SCL=0) то мастер спокойно может обойтись без Z состояния на ноге SCL. Так тупо и молотит лог 0/1 без Z

а беда скорее всего из-за RMW. Для хардового варианта эти ноги сами себе на уме. В софтовом - надо использовать LAT. Чето я его в приведенном куске не увидел.
ampersant на форуме   Ответить с цитированием
Старый 17.01.2015, 18:45   #3
Vlad&mir
Senior Member
 
Регистрация: 28.01.2009
Адрес: Москва
Сообщений: 1,720
Вес репутации: 4382/93
Vlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond reputeVlad&mir has a reputation beyond repute
По умолчанию Re: Софтовый I2C, чем лыжи мазать?

Вникать неохота, вот этот код ТОЧНО работает:
Код:
#include    <p18cXXX.h>

//-------------------------- i2c for DS1307 --------------------------

#define ds_SCL_bit            LATCbits.LATC0
#define ds_SCL_dir          TRISCbits.TRISC0

#define ds_SDA_bit            LATCbits.LATC1
#define ds_SDA_dir          TRISCbits.TRISC1
#define ds_SDA_sts             PORTCbits.RC1

//--------------------------------------------------------------------

static void ds_i2c_start(void)
{
    Nop(); Nop(); Nop(); Nop();
    ds_SDA_bit = 0;
    ds_SDA_dir = 0;
    Nop(); Nop(); Nop(); Nop();
    ds_SCL_bit = 0;
    Nop(); Nop();
    ds_SDA_dir = 1;
}

static void ds_i2c_stop(void)
{
    ds_SDA_bit = 0;
    ds_SDA_dir = 0;
    Nop(); Nop(); Nop(); Nop();
    ds_SCL_bit = 1;
    ds_SCL_dir = 0;
    Nop(); Nop();
    ds_SDA_dir = 1;
}

//--------------------------------------------------------------------

static unsigned char ds_i2c_write(unsigned char Value)
{
 unsigned char cnt;

    for(cnt = 0; cnt < 8; cnt++)
     {
        if(Value & 0x80) {ds_SDA_dir = 1;}
                   else  {ds_SDA_bit = 0; ds_SDA_dir = 0;}
        Nop();

        ds_SCL_bit = 1;

        Value <<= 1;

        ds_SCL_bit = 0;
     }

    ds_SDA_dir = 1;

    Nop(); Nop();

    ds_SCL_bit = 1;

    cnt = ds_SDA_sts;

    ds_SCL_bit = 0;

    return  1 - cnt;
}

//----------------------------------------------------------------

static unsigned char ds_i2c_read(unsigned char NO_ACK) // если  NO_ACK <> 0, выставлять ACK ! 
{
 unsigned char cnt;
 unsigned char result;

    ds_SDA_dir = 1;

    for(cnt = 0; cnt < 8; cnt++)
     {
        result  <<= 1;

        ds_SCL_bit = 1;
        
        result |= ds_SDA_sts;

        ds_SCL_bit = 0;
     }

    if(NO_ACK)
     {
        ds_SDA_bit = 0;
        ds_SDA_dir = 0;
     }

    ds_SCL_bit = 1;

    Nop(); Nop();

    ds_SCL_bit = 0;

    return  result;
}

//----------------------------------------------------------------
//----------------------------------------------------------------

void DS1307_OPEN(void)
{
    ds_i2c_stop();
}

//----------------------------------------------------------------

unsigned char READ_FROM_DS1307(unsigned char DS_Addr, void * RAM_Addr, unsigned char ByteCount)
{
  unsigned char cnt;

    cnt = 0;

    ds_i2c_start();

    if(ds_i2c_write(0xD0))
     {
        ds_i2c_write(DS_Addr);

        ds_i2c_stop();

        ds_i2c_start();

        ds_i2c_write(0xD1);

        cnt = ByteCount;

        while(cnt)
         {
            cnt--;

          *((unsigned char *) RAM_Addr) = ds_i2c_read(cnt);

            RAM_Addr += 1;
         }

     }

    ds_i2c_stop();

    return ByteCount;
}

//----------------------------------------------------------------

unsigned char WRITE_TO_DS1307(unsigned char DS_Addr, void * RAM_Addr, unsigned char ByteCount)
{
  unsigned char cnt;

    cnt = 0;

    ds_i2c_start();

    if(ds_i2c_write(0xD0))
     {
        ds_i2c_write(DS_Addr);

        for(cnt = 0; cnt < ByteCount; cnt++)
         {
            ds_i2c_write(*((unsigned char *) RAM_Addr));

            RAM_Addr += 1;
         }
     }

    ds_i2c_stop();

    return cnt;
}

//----------------------------------------------------------------
//----------------------------------------------------------------
P.S.
На линию SDA нужен подтягивающий резистор, на линию SCL - нет.
Vlad&mir вне форума   Ответить с цитированием
Старый 17.01.2015, 19:35   #4
Vovka
Senior Member
 
Аватар для Vovka
 
Регистрация: 27.12.2007
Адрес: недалеко от г.Белгорода
Возраст: 50
Сообщений: 1,845
Вес репутации: 2668/81
Vovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond reputeVovka has a reputation beyond repute
Отправить сообщение для Vovka с помощью ICQ
Thumbs up Re: Софтовый I2C, чем лыжи мазать?

Начал уже исправлять по совету ampersant, даже отладку сделал: подключился свободными битами к выводам SDA и SCL и по таймеру писал лог и выкидывал в USART , заодно и прогру rs232.exe доработал, чтобы принятые байты можно было писать в файл для анализа

Но все танцы "испортил" Vlad&mir: его код заработал!

Ладно, как-нибудь мой код добью, но это потом, если появится время и желание...

Спасибо всем!
Vovka на форуме   Ответить с цитированием
Старый 18.01.2015, 12:50   #5
Bill
Senior Member
 
Аватар для Bill
 
Регистрация: 26.02.2007
Адрес: Челябинск
Возраст: 67
Сообщений: 2,215
Вес репутации: 1898/80
Bill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant futureBill has a brilliant future
По умолчанию Было такое дело дело когда-то.

Код:
/*
        I2C service routines

        File:        I2CMaster.c

        27-Jan-01 BK        Initial edit
        08-Aug-01 BK        Last  update
*/

#include "vguard.h"     // Project header file
#include "I2Cmaster.h"

/*        Function ptototypes        */

static void     _delay(void),
                _delay2(void);
static void     I2CStart(void);
static void     _txByte(char);
static void     I2C_WrAddr(void);
static void     I2CStop(void);

/*        Global variables definition        */

volatile char           I2C_Flags;      // I2C flags
volatile char           I2C_Slave;      // I2C slave device address
volatile unsigned       I2C_Addr;       // I2C device data address
volatile char           I2C_Buffer[8];  // Buffer

//
//  ** I2CInit        -- the routine to initiate I2C ports
//
void I2CInit(void)
        {
        I2C_Flags       = 0;            // Reset flags
        I2C_Output      |= (SDA_BIT | SCL_BIT);
        I2C_DDR         |= (SDA_BIT | SCL_BIT);
        }
//
// ** I2C_Rd1Byte        -- Read 1st byte from I2C
//
char I2C_Rd1Byte(void)
        {
        I2C_WrAddr();                   // Write the required address info
        I2CStart();                     //
        _txByte(I2C_Slave | 0x01);      // Specify READ mode for the slave device
        return I2C_RdByte(1);           // Read data
        }
//
// ** I2C_RdByte   -- the routine receives 8 data bits
//
char I2C_RdByte(char _flag)
        {
        char    _count = 8, _byte = 0;

        I2C_DDR &= ~SDA_BIT;    // Make SDA line as input
        I2C_Output |= SDA_BIT;  // Enable pull-up resistor
        do      {               // Reception
                _byte <<= 1;
                I2C_Output |= SCL_BIT;  // Set clock to high
                _delay();              //
                if (I2C_Input & SDA_BIT)//
                        _byte |= 0x01;
                I2C_Output &= ~SCL_BIT; // Return clock to low
                _delay();              //
                }
        while (--_count);
        I2C_DDR |= SDA_BIT;     // Make SDA line as output
        _delay();               //
        if (!_flag)              // For the last received byte send NACK signal
                I2C_Output |= SDA_BIT;
        else                    // otherwise send ACK signal
                I2C_Output &= ~SDA_BIT;
        I2C_Output |= SCL_BIT;  // Set clock to high
        _delay();
        I2C_Output &= ~SCL_BIT; // Return clock to low
        _delay();
        return _byte;
        }
//
// ** I2C_RdLastByte   -- the routine reads the last byte from I2C
//
char I2C_RdLastByte(void)
        {
        char _byte;

        _byte = I2C_RdByte(0);     // Read the data
        I2CStop();                      // Generate STOP condition
        return _byte;                   // and return
        }
//
// ** I2C_Wr1Byte        -- Write 1st byte to I2C
//
void I2C_Wr1Byte(char _byte)
        {
        I2C_WrAddr();           // Write the required address info
        _txByte(_byte);         // Write the data
        }
//
// ** I2C_Wr1LastByte        -- Write only 1 byte to I2C
//
void I2C_Wr1LastByte(char _byte)
        {
        I2C_Wr1Byte(_byte);     // Write the byte
        I2CStop();              // Generate STOP condition
        }
//
// ** I2C_WrLastByte        -- Write last byte to I2C
//
void I2C_WrLastByte(char _byte)
        {
        _txByte(_byte);         // Write the data
        I2CStop();              // Generate STOP condition
        }
//
// ** I2C_WrAddr        -- Write the Slave and Slave data addresses to I2C
//
static void I2C_WrAddr(void)
        {
        I2CStart();                     // Generate START bit
        _txByte(I2C_Slave);             // Send the slave device address
        if (I2C_Flags & FLASH_BIT )     // Flash memory access
                _txByte(I2C_Addr>>8);   // then send the flash data address high
        _txByte(I2C_Addr);              // then low
        }
//
// ** _txByte   -- the routine transmits 8 data bits
//
static void _txByte(char _byte)
        {
        char    _count;

        I2C_Output &= ~SCL_BIT; // Set clock to low
        _count = 8;
        I2C_DDR |= SDA_BIT;     // Make SDA line as output
        do      {               // Transmission
                _delay();
                if (_byte & (1<<7))
                        I2C_Output      |= SDA_BIT;
                else
                        I2C_Output      &= ~SDA_BIT;
                _byte <<= 1; _NOP(); _NOP();
                I2C_Output |= SCL_BIT;  // Set clock to high
                _delay();               //
                I2C_Output &= ~SCL_BIT; // Return clock to low
                }
        while (--_count);
        _delay();              //
        I2C_DDR &= ~SDA_BIT;    // Make SDA line as input
        _byte   = 0;
        I2C_Output |= SCL_BIT;  // Set clock to high
        _delay();              //
        if (I2C_Input & SDA_BIT)// For ACK high
                _byte = 0xFF;
        I2C_Output &= ~SCL_BIT; // Return clock to low
//        return _byte;
        }
//
// ** I2CStart        -- the function asserts start condition
//
static void I2CStart(void)
        {
        I2C_Output      |= SDA_BIT;                // Make sure SDA is high
        I2C_DDR         |= SDA_BIT;                // Return SDA line to output state
        I2C_Output      &= ~SCL_BIT;                // Set SCL low
        _delay();                                //
        I2C_Output      |= SCL_BIT;                // Set SCL high
        _delay();                                //
        I2C_Output      &= ~SDA_BIT;                // SDA goes low during SCL high
        _delay();                                //
        I2C_Output      &= ~SCL_BIT;                // Set SCL low
        }
//
// ** I2CStop        -- the function asserts stop condition
//
static void I2CStop(void)
        {
        I2C_DDR         |= SDA_BIT;                // Return SDA line to output state
        I2C_Output      &= ~SCL_BIT;                // Force SCL
        I2C_Output      &= ~SDA_BIT;                // and SDA low
        _delay();                                // Half period delay
        I2C_Output      |= SCL_BIT;                // Set SCL high
        _delay();                                // Quarter period delay
        I2C_Output      |= SDA_BIT;                // Set SDA high
        _delay();                                // Half period delay
        }
//
// ** _delay2       -- I2C clock half period delay
//
static void _delay2(void)
        {
        _delay();
        _delay();
        }
//
// ** _delay        -- I2C clock quarter period delay
//
static void _delay(void)
        {
        char    _count = 9;
        while (--_count);
        }
//
// ** I2C_RdBlock       -- the routine reads a data block (8 bytes)
//                      from a I2C slave device to I2C buffer
//
void I2C_RdBlock(void)
        {
        char    *_cp = I2C_Buffer,      // a pointer to buffer
                _cnt = 6;               // and byte counter

        *_cp++  = I2C_Rd1Byte();        // Read the 1st byte
        do      {
                *_cp++ = I2C_RdByte(1); // Read all others excluding the last byte
                }
        while (--_cnt);
        *_cp    = I2C_RdLastByte();     // Read the last byte
        }

//
// ** I2C_WrBlock       -- the routine writes a data block (8 bytes)
//                      to a I2C slave device to I2C buffer
//
void I2C_WrBlock(void)
        {
        char    *_cp = I2C_Buffer,      // a pointer to buffer
                _cnt = 6;               // and byte counter

        I2C_Wr1Byte(*_cp++);            // Write the 1st byte
        do      {
                _txByte(*_cp++);         // Write all others excluding the last byte
                }
        while (--_cnt);
        I2C_WrLastByte(*_cp);           // Write the last byte
        }
Bill вне форума   Ответить с цитированием
Старый 22.05.2017, 12:55   #6
Виктория В
Junior Member
 
Аватар для Виктория В
 
Регистрация: 22.09.2014
Возраст: 37
Сообщений: 9
Вес репутации: 100/0
Виктория В will become famous soon enoughВиктория В will become famous soon enough
Отправить сообщение для Виктория В с помощью Skype™
По умолчанию Re: Софтовый I2C, чем лыжи мазать?

Здравствуйте, может бы у кого нибудь есть рабочий код для ds1307 pic16f877 asm ??? моя почта wik19801@yandex.ru . Буду очень благодарна !
Виктория В вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с DS1820. Чем лыжи мазать? fol Общетехнические вопросы 131 26.11.2016 14:27
I2C и EEPROM что-то у меня не так Aries Продукция MICROCHIP 19 23.07.2010 11:23
i2c pic18F14K50 + PCA9535 + TIC154(PCF8535) - толи лыжи... master19 Продукция MICROCHIP 10 26.02.2010 18:10
Софтовый I2C, удавалось добиватся скорости в этом случае 400 кГц и выше ? alexdos Продукция MICROCHIP 9 10.07.2009 15:17
софтовый I2C spectre Продукция MICROCHIP 5 14.11.2008 18:07


Часовой пояс GMT +3, время: 17:49.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot