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

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

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

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

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

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


 
Опции темы
Непрочитано 29.05.2023, 13:18  
worldmasters
Гражданин KAZUS.RU
 
Регистрация: 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.RU
 
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 731
Сказал спасибо: 363
Сказали Спасибо 807 раз(а) в 379 сообщении(ях)
j-Roger на пути к лучшему
По умолчанию Re: Не работает прерывание I2C

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

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

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

И да, речь не идет о симуляторах..
j-Roger вне форума  
Непрочитано 29.05.2023, 16:50  
worldmasters
Гражданин KAZUS.RU
 
Регистрация: 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.RU
 
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 731
Сказал спасибо: 363
Сказали Спасибо 807 раз(а) в 379 сообщении(ях)
j-Roger на пути к лучшему
По умолчанию Re: Не работает прерывание I2C

В документе TB3251 - Using the MSSP in I2C Slave Mode приведены фрагменты кода, по которым можно сверить настройки ( учитывая особенности модуля прерываний конкретного МК ).
P. S.
Не используем PIC24, поэтому ответы на вопросы имеют весьма общий характер.
j-Roger вне форума  
Непрочитано 30.05.2023, 14:37  
worldmasters
Гражданин KAZUS.RU
 
Регистрация: 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, время: 14:06.


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