Реклама на сайте DatasheetsDatasheets

KAZUS.RUN - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Книги и журналы
FAQ по электронике

  Datasheets
Поиск SMD
Онлайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Схемы и проекты
Принципиальные схемы
  Программы
Каталог сайтов
Калькуляторы
  Форумы по электронике
Помощь проекту


 
Опции темы

Не работает прерывание I2C

Непрочитано 29.05.2023, 13:18  
worldmasters
Гражданин KAZUS.RUN
 
Регистрация: 21.02.2007
Сообщений: 553
Сказал спасибо: 38
Сказали Спасибо 17 раз(а) в 16 сообщении(ях)
worldmasters на пути к лучшему
По умолчанию Не работает прерывание I2C

Здравствуйте.

Надо подружить по I2C два МК.
PIC24FV32KA302 (мастер)
PIC24FV16KM202 (слейв)

Для мастера написал код инициализации и опроса:

Код:
void I2C_Initialize(void) {
    // Настройка пинов порта I2C
    SDA1_TRIS = 1; // SDA (пин для приема/передачи данных)
    SCL1_TRIS = 1; // SCL (пин для управления тактированием)

    // Настройка модуля I2C
    I2C1CONbits.I2CEN = 0; // Отключение модуля I2C перед настройкой

    // Настройка скорости передачи
    I2C1BRG = 157; //100 кгц при 16мгц частоте циклов

    // Включение модуля I2C
    I2C1CONbits.I2CEN = 1;
}

// Проверка наличия устройства на шине I2C

unsigned char I2C_CheckDevicePresence(unsigned char deviceAddress) {
    // Начало передачи
    I2C1CONbits.SEN = 1;

    // Ожидание окончания стартового условия
    while (I2C1CONbits.SEN) {
        Nop();
    }

    // Отправка адреса устройства и бита записи (0)
    I2C1TRN = (deviceAddress ‹‹ 1) | 0;

    // Ожидание окончания передачи адреса
    while (I2C1STATbits.TRSTAT) {
        Nop();
    }

    // Проверка статуса передачи адреса
    if (I2C1STATbits.ACKSTAT) {
        // Устройство не отвечает
        return 0;
    }

    // Остановка передачи
    I2C1CONbits.PEN = 1;

    // Ожидание окончания условия стопа
    while (I2C1CONbits.PEN) {
        Nop();
    }

    return 1;
}

Для слейва код:

Код:
/* Инициализация I2C*/
void I2C_Initialize(void) {
    // Настройка пинов порта I2C
    SDA1_TRIS = 1; // SDA (пин для приема/передачи данных)
    SCL1_TRIS = 1; // SCL (пин для управления тактированием)

    SSP1STAT = 0;
    SSP1STATbits.SMP = 1; // Фаза выборки данных
    SSP1STATbits.CKE =0;
            
    SSP1CON1 = 0;
    SSP1CON1bits.SSPM = 0b1110; // Режим I2C Slave 7-bit адрес 
    
    I2C2ADD = 0x5D; // Load slave address  

    // Включение прерываний MSSP/I2C
    IFS1bits.SSP1IF = 0; // Сброс флага прерывания
    IEC1bits.SSP1IE = 1; // Включение прерывания 
    IPC4bits.SSP1IP = 6;
    
    // Включение модуля MSSP/I2C
    SSP1CON1bits.SSPEN = 1;
}


И в прерывании обработка:

void __attribute__((interrupt, no_auto_psv)) _MSSP1Interrupt(void) {
    uint8_t tmp = 0;
    uint8_t buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    if (IFS1bits.SSP1IF) {
        //IFS1bits.SSP1IF = 0; // Сброс флага прерывания
        buf[0] = 1;
        if (SSP1STATbits.R_NOT_W == 1) {
            buf[2] = 1;
            // Master read (slave transmit)
            SSP1BUF = TxBuf[TxPos++]; // Load array value
            if (RxPos == BUF_LEN) // Достигнут конец передачи данных
            {
                RxPos = 0;
            }
            SSP1CON1bits.CKP = 1; // Release clock stretch             
        } else if (SSP1STATbits.R_NOT_W == 0) {
            buf[3] = 1;
            // Master write (slave receive)
            // Если принимаются данные
            if (SSP1STATbits.D_NOT_A == 0) {
                buf[4] = 1;
                buf[5] = SSP1BUF;
                tmp = SSP1BUF; // Clear BF
                if (tmp == SSP1ADD) {
                    buf[6] = 1;
                    SSP1CON2bits.ACKDT = 0; // Установка ACK (Acknowledge)                    
                    TxPos = 0;
                    RxPos = 0;
                }
            } else {
                tmp = SSP1BUF; // Clear BF
                if (RxPos ‹ BUF_LEN) {
                    RxBuf[RxPos] = tmp;
                }
            }
            SSP1CON1bits.CKP = 1;
        }
        PutEEPROM(2, buf, 10);
    } 
}

У мастера основной код опроса:

Код:
unsigned char PlayerAdr = 0x5d;
    unsigned long tm = 0;
    while (1) {
        for (unsigned char i = 1; i ‹ 127;i++) {
            if (I2C_CheckDevicePresence(i)) {
                uint8_t dat[]={i,0,2,3};
                PutEEPROM(32, dat, 4);
                while (1) {
                    ActivateSound(GetNoteFreq(DO, OCTAVE_3), 500);
                    PauseTicks(tm, 200000);
                    ActivateSound(GetNoteFreq(MI, OCTAVE_2), 100);
                    PauseTicks(tm, 200000); 
                }
            }
        }
        Nop();
    }
Но почему то не срабатывает прерывание у слейва. По прерыванию он должен был в еепром схранить лог но в еепром пусто. Я делаю вывод что не срабатывает прерывание.
Хотя в анализаторе видно что мастер запросы вроде как отправляет.

Что я не так сделал то??
Миниатюры:
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 0
Размер:	39.5 Кб
ID:	176865  
Реклама:
worldmasters вне форума  
Непрочитано 29.05.2023, 14:54  
j-Roger
Гражданин KAZUS.RUN
 
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 839
Сказал спасибо: 379
Сказали Спасибо 942 раз(а) в 451 сообщении(ях)
j-Roger на пути к лучшему
По умолчанию Re: Не работает прерывание I2C

Сообщение от worldmasters Посмотреть сообщение
По прерыванию он должен был в еепром схранить лог но в еепром пусто. Я делаю вывод что не срабатывает прерывание.
Ну, такой же результат может наблюдаться и при неработоспособности функции записи в EEPROM )

Если не используется "железная" отладка, то можно в интересующих местах программы дергать специально выделенными пинами МК и наблюдать их лог. анализатором (это один из способов вывода отладочной информации).

ИМХО для начала стОит добиться работы I2C слейва не задействуя механизм прерываний - путем опроса флагов модуля I2C прямо в main-e, чтобы main() только этим и занимался. После того как прием заработает как положено, переместить функционал в обработчик прерывания.

И да, речь не идет о симуляторах..
j-Roger вне форума  
Непрочитано 29.05.2023, 16:50  
worldmasters
Гражданин KAZUS.RUN
 
Регистрация: 21.02.2007
Сообщений: 553
Сказал спасибо: 38
Сказали Спасибо 17 раз(а) в 16 сообщении(ях)
worldmasters на пути к лучшему
По умолчанию

Сообщение от j-Roger Посмотреть сообщение
Ну, такой же результат может наблюдаться и при неработоспособности функции записи в EEPROM )
Да функция отлажена и работает. При старте программы вписываю первыми 2 байта. И затем при чтении еепром я эти байты наблюдаю.


Сообщение от j-Roger Посмотреть сообщение
И да, речь не идет о симуляторах..
Да это понятно.

Прерывание все таки работает но почему то в буфере какой то шлак попадается:

сделал уже запись данных при получении в буфер и в еепром.

Код:
tmp = SSP1BUF & 0x00ff; // Clear BF

            if (SSP1STATbits.D_NOT_A == 0) {
                PLAYER_BUSY_O = !PLAYER_BUSY_I;
                if (tmp == I2C2ADD) {
                    SSP1CON2bits.ACKDT = 0; // Установка ACK (Acknowledge)                    
                    TxPos = 0;
                    RxPos = 0;
                    buf[9] = 0xb1b2;
                }

                buf[id++] = tmp;
                if (id › 8) {
                    PutEEPROM(2, (uint8_t*) & buf[0], 20);
                    PLAYER_BUSY_O = 1;
                    id = 1;
                    while (1)Nop();
                }
Уже и менял параметры:

Код:
    SSP1CON2bits.SEN = 0;
    SSP1CON3bits.AHEN = 1;
    SSP1CON3bits.DHEN = 1;
Но все равно записывается разное число но не адрес. Мастер шлет 0x22 всегда. Анализатор это подтверждает.
Что с ним не так то.

Подтяжка стоит 4,7 кОм.

Последний раз редактировалось mike-y-k; 30.05.2023 в 00:23. Причина: 6.6
worldmasters вне форума  
Непрочитано 29.05.2023, 17:46  
j-Roger
Гражданин KAZUS.RUN
 
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 839
Сказал спасибо: 379
Сказали Спасибо 942 раз(а) в 451 сообщении(ях)
j-Roger на пути к лучшему
По умолчанию Re: Не работает прерывание I2C

В документе TB3251 - Using the MSSP in I2C Slave Mode приведены фрагменты кода, по которым можно сверить настройки ( учитывая особенности модуля прерываний конкретного МК ).
P. S.
Не используем PIC24, поэтому ответы на вопросы имеют весьма общий характер.
j-Roger вне форума  
Непрочитано 30.05.2023, 14:37  
worldmasters
Гражданин KAZUS.RUN
 
Регистрация: 21.02.2007
Сообщений: 553
Сказал спасибо: 38
Сказали Спасибо 17 раз(а) в 16 сообщении(ях)
worldmasters на пути к лучшему
По умолчанию

Спасибо. Именно по этому документу и сверяюсь. Но все равно дичь какая то.

Эх..

Кстати по какой то неведомой причине если я ставлю в прерывании код:

Код:
if(!SSP1STATbits.BF)
            return;
То заход дальше этого не происходит вообще. Хотя по идее это же не правильно потому что событие должно происходить когда в буфере естьданные.

Последний раз редактировалось mike-y-k; 30.05.2023 в 21:30. Причина: 6.6
worldmasters вне форума  
 
Опции темы

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

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

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

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не работает прерывание АЦП Alexander_vrn Микроконтроллеры, АЦП, память и т.д 4 22.03.2023 22:53
[Решено] STM32F407VET HAL CAN не работает worldmasters ARM 22 03.02.2022 11:06
I2C между МК, отправка массива чисел bestrating AVR 2 24.03.2013 16:49
Адресация к памяти I2C по адресу Lexil Proteus 2 12.12.2012 12:40
proteus, atmega8, меняю ноги в hex - не работает digitest Микроконтроллеры, АЦП, память и т.д 3 08.10.2009 13:07


Часовой пояс GMT +4, время: 06:35.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.