Jump to content

    
Sign in to follow this  
AndreyS

EnergyMicro EFM32GG Cortex-M3

Recommended Posts

Добрый день.

 

Начал разбираться со зверем EFM32GG от EnergyMicro

 

На стадии изучения прерывания (NVIC) от GPIO не могу понять чем отличается прерывание (GPIO) ODD от EVEN (обработчики GPIO_ODD_IRQHandler и GPIO_EVEN_IRQHandler)?

 

Настроил два пина порта A на прерывания по переднему фронту и включил их.

В main'е меняю значение на одной ноге и вываливаюсь в прерывание EVEN. В нем проверяю GPIO->IF на предмет вызова по пину из main и тогда меняю состояние второй ноги. Но при этом почему то вываливаюсь не в EVEN, а в ODD прерывание (в GPIO->IF вижу что сработало прерывание от ноги измененной в EVEN обработчике).

 

Почему? В чем их разница?

 

В документации в качестве примера (похож на мой) сказано что должен быть выход в ODD обработчик. Я включил только его и ниразу в него не вошел.

 

PS. Хотя наверное я понял. Это обработчики четных и нечетных внешних прерываний?

Edited by AndreyS

Share this post


Link to post
Share on other sites

Добрый день.

 

Появился второй вопрос (по сравнению с первым, как мне кажется более существенный).

 

Перешел на изучение I2C.

 

Конкретно работу в режиме передающий мастер.

 

Настроил I2C, включил в CMU синхросигнал, реализовал обработчик прерывания I2C, настроил NVIC. Передаю данные.

 

Вопрос по значениям состояний I2C регистра STATE.

Хочу прочитать значение данных по некому адресу из EEPROM.

После успешного выставления состояния START на шину в регистре должно (по документации) появиться значение 0x57. Но появляется 0x53 (2 бит TRANSMITTER) не возводится. В обработчике прерывания я ожидал 0x57 для продолжения работы, добавил 0x53. Дальше все согласно даташиту отрабатывает и приходит обратно в состояние. Т.е. я передаю 7 битный адрес с признаком записи и он подтверждается EEPROM (приходит ACK) состояние 0x97. Затем я передаю два байта адреса EEPROM (тут они уже идут как данные I2C) и получаю на каждый STATE= 0xD7. После этого посылаю Repeat START и в ответ опять получаю 0x53 (а не 0x57), после этого передаю адрес с признаком чтения данных и после этого вижу на шине осциллографом, что CLK отработало видимо не только передачу адреса, но еще что-то (количество клоков 17 штук). В регистре STATE лежит при этом 0xB3 и есть данные в регистре RXDATA. Видимо сразу за адресом прошел запрос и данных, но я не включал авто подтверждений и по идее должно было прийти сначала состояние 0x93, а уже затем я бы перешел в состояние принять байт. Ну даже если и принял байт, то почему на шине количество клоков не кратно 9 (17 вместо необходимых 18)? И в регистре RXDATA лежит 0xEE (EEPROM пустая и я еще туда ничего не записывал) ожидалось 0xFF.

 

0. Как правильно сбросить прерывание I2C шины?

1. Почему при выставлении START на шину (посыл команды в регистр CMD I2C_CMD_START) в регистре STATE 0x53, вместо 0x57?

2. Почему не выставляется бит TRANSMITTER? Как гарантированно перевести I2C в режим Master Transmitter?

3. Почему после отправки адреса микросхемы с признаком чтение (после RSTART) происходит передача адреса на шину и прием чего, то (клоков на шине 17)? Возвращается STATE не 0x97, а сразу 0xB3, Почему так?

Инициализация I2C шины.

    /* Настройка I2C */
    // Настройка GPIO I2C
    /* Pin PD14 is configured to Open-drain with pull-up and filter */
    GPIO->P[3].MODEH = (GPIO->P[3].MODEH & ~_GPIO_P_MODEH_MODE14_MASK) | GPIO_P_MODEH_MODE14_WIREDANDPULLUPFILTER;
    /* Pin PD15 is configured to Open-drain with pull-up and filter */
    GPIO->P[3].MODEH = (GPIO->P[3].MODEH & ~_GPIO_P_MODEH_MODE15_MASK) | GPIO_P_MODEH_MODE15_WIREDANDPULLUPFILTER;
    // Включаем 3 альтернативное рассположение (там в ките висит EEPROM)
    I2C0->ROUTE = (I2C0->ROUTE & ~_I2C_ROUTE_LOCATION_MASK) | I2C_ROUTE_LOCATION_LOC3;
    // Разрешение шины на GPIO
    I2C0->ROUTE |= I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN;
    // Настраиваем частоту рабоыт I2C 100кГц
    //  div = ((14000000 - (4 * freq)) / (n * freq)) - 1;
    // freq= 100000 частота I2C
    I2C0->CLKDIV;
    // Настраиваем режим работы I2C
    I2C0->CTRL=(I2C_CTRL_CLHR_STANDARD | I2C_CTRL_EN ) & ~I2C_CTRL_SLAVE;// | I2C_CTRL_AUTOSN;// | I2C_CTRL_AUTOACK;
    // Определяем прерывания I2C
    I2C0->IFC = _I2C_IFC_MASK;
    I2C0->IEN = I2C_IEN_MSTOP|I2C_IEN_NACK|I2C_IEN_ACK|I2C_IEN_RSTART|I2C_IEN_BUSHOLD|I2C_IEN_ST
ART;

 

Инициация передачи данных

    if (I2C0->STATE & I2C_STATE_BUSY)
      {
        I2C0->CMD=I2C_CMD_ABORT;
    }
    I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
    if (I2C0->IF & I2C_IF_RXDATAV)
    {
        I2C0->RXDATA;
    }
    I2C0->IFC = _I2C_IFC_MASK;
    I2C0->CMD=I2C_CMD_START;

 

Обработчик прерывания

// обработчик IIC прерывания
void I2C0_IRQHandler(void)
{
    dword SMB0STA;
    SMB0STA=I2C0->IF;
    I2C0->IFC=SMB0STA;
    SMB0STA=I2C0->STATUS;
    SMB0STA=I2C0->STATE;
    if (!iic.cycle)
    {// выход на шину
        if ((SMB0STA==MTM_START) || (SMB0STA==MTM_RSTART))
        {
            I2C0->TXDATA=*(byte *)(&iic);

            //SMB0DAT=*(byte *)(&iic);        // передаем адрес с признаком
            //IIC_CLR_START
            iic.cycle++;
            iic.ptr=0;
        }
        else
            IIC_GET_ERR_
    }
    else
    {
        if (iic.work==_WRITE)
        {// цикл записи
            switch (iic.cycle)
            {
                case 1 :
                    if (SMB0STA==MTM_SLAW_ACK)
                    {
                        if (iic.len--)
                        {
                            I2C0->TXDATA=iic.dat[iic.ptr++];
                            iic.cycle++;
                        }
                        else
                            IIC_STOP_
                    }
                    else
                        IIC_GET_ERR_
                    break;
                case 2 :
                    if (SMB0STA==MTM_DATA_ACK)
                    {
                        if (iic.len--)
                            I2C0->TXDATA=iic.dat[iic.ptr++];
                        else
                        {
                            if (!iic.len_rd)
                                IIC_STOP_
                            else
                            {
                                iic.work=_READ;
                                iic.len=iic.len_rd;
                                iic.ptr=0;
                                iic.cycle=0;                                
                                IIC_START
                            }
                        }
                    }
                    else
                        IIC_GET_ERR_
                    break;

                default :
                    break;
            }
        }
        else
        {// цикл чтения
            switch (iic.cycle)
            {
                case 1 :
                    if (SMB0STA==MRM_SLAR_ACK)
                    {
                        if (iic.len)
                        {
                            iic.cycle++;
                            if (--iic.len) IIC_SEND_ACK
                            else IIC_SEND_NACK
                        }
                        else
                            IIC_STOP_
                    }
                    else
                        IIC_GET_ERR_
                    break;
                case 2 :
                    if (SMB0STA==MRM_DATA_ACK)
                    {
                        iic.dat[iic.ptr++]=(byte)(I2C0->TXDATA);
                        if (--iic.len)
                            IIC_SEND_ACK
                        else
                            IIC_SEND_NACK
                    }
                    else
                    {
                        if (SMB0STA==MRM_DATA_NACK)
                        {
                            iic.dat[iic.ptr++]=(byte)(I2C0->TXDATA);
                            IIC_STOP_
                        }
                        else
                            IIC_GET_ERR_
                    }
                    break;

                default :
                    break;
            }
            
        }
    }
}

 

Макросы

#define IIC_START        I2C0->CMD=I2C_CMD_START;    // Посыл START на линию
#define IIC_STOP        I2C0->CMD=I2C_CMD_STOP;        // Посыл STOP на линию
#define IIC_SEND_ACK    I2C0->CMD=I2C_CMD_ACK;        // Посылка подтверждения
#define IIC_SEND_NACK    I2C0->CMD=I2C_CMD_NACK;                // Посылка не подтверждения
#define IIC_ABORT        I2C0->CMD=I2C_CMD_ABORT;    // Сброс шины

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this