Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с IrDA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
d7d1cd
Привет всем. Возникла у меня задача написать самозагрузчик флешь памяти по инфракрасному порту. Микроконтроллер MSP430F249, однако сам передатчик IrDA подключен к выводам 19 (TX) и 15 (RX), то есть ни к одному из модулей USCI доступа нет.
Подскажите, возможно ли организовать обмен, не используя прерывания и таймер? Планируется написать программу самозагрузки, которая будет выполняться из RAM.
rezident
Цитата(d7d1cd @ Dec 15 2013, 18:21) *
Подскажите, возможно ли организовать обмен, не используя прерывания и таймер?

Вообще без использования таймера или каких-то временных отметок - нельзя. Точнее можно, то нужно писать на ASM и очень сильно постараться, чтобы выдержать времянки циклов и скомпенсировать все задержки при переходах. Если же все же задействовать функционал TimerA, к пинам которого у вас подключен трансивер IRDA, то можно реализовать аппаратно-программный UART. См. принцип реализации в application note Implementing IrDA With The MSP430 или MSP430C112 IrDA SIR Encoder/Decoder.
P.S. а чего это вы через полтора+ года вернулись к тому, с чего начинали? Разве нельзя было изменить схему и подключить трансивер IrDA к выводам USCI, коль уж и кристалл вы уже поменяли?
d7d1cd
Спасибо за подсказки. Изменить схему подключения к сожалению нельзя (хотя очень хочется). Я пишу на ассемблере. Думаю, что выдержать временные циклы будет не так сложно, ведь известно сколько тактов занимает та или иная инструкция, а частота тактирования мне известна. Есть другой камень преткновения: физический принцип работы инфракрасного канала. Мне необходимо организовать обмен на скорости 9600 бит/с, без проверки на четность/нечетность, 1 стоп-бит.
Подскажите, правильно ли я рассуждаю.
1. Чтобы передать байт, надо кроме 8 бит данных передавать старт и стоп биты.
2. Старт бит - это 1, стоп бит - это 0.
3. Передача 1 по инфракрасному каналу - это отсутствие импульса, передача 0 это наличие импульса.
4. Длительность импульса должна быть 3/16 от времени, приходящегося на передачу 1 бита на скорости 9600.
5. Длительность передачи 1 бита: 1 / 9600 = 0,0001 с; длительность импульса: 0,0001 * 3 / 16 = 0,00002 с.
6. Импульс должен произойти в любом месте отрезка времени передачи бита.
rezident
Цитата(d7d1cd @ Dec 16 2013, 22:12) *
Подскажите, правильно ли я рассуждаю.

Почти правильно.
Уровни UART не просто определяются как лог.1. и лог.0, а именуются MARK (неактивный уровень, лог.1 на выходе UART) и SPACE (активный, лог.0 на выходе UART). SPACE в IrDA передается импульсом, MARK - отсутствием импульса. START-бит передается как SPACE, т.е. наличием импульса. Иначе как вы определите начало символа? STOP-бит передается уровнем MARK (отсутствием импульса).
Последний пункт у вас неверный. Импульс должен передаваться не в любом месте битового интервала, а строго посередине его.
Насчет легкости реализации. Учитывайте, что если вы не будете использовать аппаратные возможности TimerA, то вам придется делать polling (опрос входа) RX как минимум 16*9600=153600 раз/с. Т.е. с учетом циклов и переходов MCLK у вас (навскидку/грубо) должен быть не менее 4МГц и кратен битовой частоте передачи/приема.
d7d1cd
Цитата(rezident @ Dec 16 2013, 23:16) *
Последний пункт у вас неверный. Импульс должен передаваться не в любом месте битового интервала, а строго посередине его.

В указанном документе MSP430C112 IrDA SIR Encoder/Decoder я узнал, что инфракрасный импульс должен передаваться не строго посередине битового интервала, а должен начаться строго посередине этого интервала.
Чем больше я думаю о реализации своего "чисто программного" обмена, тем больше понимаю, что не так уж это просто rolleyes.gif.

Хочу следовать Вашему совету и использовать таймер А. У таймера будут прерывания. Так как я планирую выполнять полную перезапись флешь памяти, то использовать вектора прерываний нельзя. Значит надо делать постоянный опрос флага прерывания таймера. Правильно? Или же можно перенести таблицу прерываний в RAM (где то читал, что так можно сделать на некоторых МК)?
rezident
Цитата(d7d1cd @ Dec 18 2013, 19:48) *
В указанном документе MSP430C112 IrDA SIR Encoder/Decoder я узнал, что инфракрасный импульс должен передаваться не строго посередине битового интервала, а должен начаться строго посередине этого интервала.

Да, это так. Согласен.
Цитата(d7d1cd @ Dec 18 2013, 19:48) *
У таймера будут прерывания. Так как я планирую выполнять полную перезапись флешь памяти, то использовать вектора прерываний нельзя. Значит надо делать постоянный опрос флага прерывания таймера. Правильно?

Не обязательно. Прерывания должы быть запрещены лишь во время записи/стирания Flash. А между циклами записи/стирания - пожалуйста. Приняли по прерываниям в буфер, запретили прерывание, записали буфер во Flash, разрешили прерывание и т.д. Вот только переписывать сектор с векторами прерываний при таком раскладе не рекомендуется. При неудачном стечении обстоятельств можно получить нерабочий кристалл, который только через BSL можно будет стереть.
Цитата(d7d1cd @ Dec 18 2013, 19:48) *
Или же можно перенести таблицу прерываний в RAM (где то читал, что так можно сделать на некоторых МК)?

В сериях MSP430F5xxx/6xxx есть аппаратная поддержка ремапа векторов прерываний в ОЗУ. У других серий можно реализовать программную эмуляцию ремапа, но опять же в обоих случаях сектор с векторами прерываний переписывать не стоит.
d7d1cd
Цитата(rezident @ Dec 18 2013, 20:36) *
Не обязательно. Прерывания должны быть запрещены лишь во время записи/стирания Flash. А между циклами записи/стирания - пожалуйста. Приняли по прерываниям в буфер, запретили прерывание, записали буфер во Flash, разрешили прерывание и т. д. Вот только переписывать сектор с векторами прерываний при таком раскладе не рекомендуется. При неудачном стечении обстоятельств можно получить нерабочий кристалл, который только через BSL можно будет стереть.

Переписывать сектор с векторами, наверное, все-таки надо. Ведь при штатном режиме работы таймер используется для других целей и у этих целей будет свой обработчик прерывания, который находится во флешь, а при загрузочном режиме обработчик прерывания находится в RAM...

Скажите, а чем плох метод циклического опроса флага наличия прерывания таймера? И имеет ли он право на существование?
rezident
Цитата(d7d1cd @ Dec 18 2013, 22:28) *
Скажите, а чем плох метод циклического опроса флага наличия прерывания таймера? И имеет ли он право на существование?

Не плох. Имеет. Когда основаная задача только одна и состоит она в том, чтобы следить за состоянием флага прерывания sm.gif Хотя в простом загрузчике (без шифрования потока) по сути это так и есть.
d7d1cd
Спасибо за подсказки. Буду пока изучать таймер. Но тема не закрыта. Как говорится, to be continued...
Dog Pawlowa
Цитата(d7d1cd @ Dec 21 2013, 19:28) *
Но тема не закрыта.

У кого как. В связи с появлением люминесцентных ламп, излучающих в ИК диапазоне я тему закрыл.
Выкладываю исходник "как есть".
Там какие-то мои макросы управления портами, спросите если будет интересно.
Да, одна неприятная особенность этого всего - необходимость работы вложенных прерываний, поэтому прочитайте про новые лампы еще раз и хорошенько подумайте..


Код
#define MaxBoudrate    115200

#define Boudrate    38400

#define    IrdaPeriod    (XT2CLK/Boudrate)        //32
#define    MinIrdaPeriod    (XT2CLK/MaxBoudrate)        //32

#define IrdaPulse    (MinIrdaPeriod*3/16)                //6


unsigned int irda_rx_mask=1;
unsigned int irda_tx_mask=1;
unsigned int irda_rx_data;
unsigned int irda_tx_data;

#define LastRxMask 0x200
#define LastTxMask 0x400

char irda_rx_byte;
char irda_rx_flag;


void SendByteViaIrda(char B)
{ OffFunction(IrdaRxInterrupt);
    irda_tx_data =    (((unsigned int)B)<<2)|0xFC01;
    TACTL = TASSEL_2 + TACLR + MC_0;        // Timer A counts SMCLK clocks continuos Stop
    TACCR2= IrdaPeriod-IrdaPulse-1;            // TA2 active    
    irda_tx_mask=1;
    TACCTL1 = 0;                                                // disable interrupt for receiving
    TACCTL0 = CCIE+CCIFG;                                // enable interrupt for transmittion
    TACCTL2 = OUTMOD_3;
    TACTL    |= MC_1;                                            // timer start to "UP" mode

    for (;;)
    {    if (irda_tx_mask>LastTxMask)    
        {    TACCTL0=0;
            InitIrdaReceiveMode();
            return;
        }
    }
}

#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA_modul0(void)
{    if (irda_tx_mask<=LastTxMask)
            irda_tx_mask=irda_tx_mask<<1;    
    else TACCTL0=0;                                            // no more interrupts
    
    if (irda_tx_data & irda_tx_mask)        OffFunction(CCTL2);
    else                    OnFunction(CCTL2);
}

void TimerAConfiguration(void)
{    __bic_SR_register OSCOFF;        
    TACTL = TASSEL_2 + TACLR + MC_0;    //    Timer A counts SMCLK clocks
    TACCTL0 = 0;                                            //    module 0 configuration, enable interrupt later
    TACCR0    = IrdaPeriod;                            //    period of timer overflow
    TACTL    |= MC_1;                                        //    timer start to "UP" mode
}



void InitIrdaReceiveMode(void)
{    P2IFG=0;
    P2IES=0x80;
    P2IE=0x80;
    TACCR0=IrdaPeriod-1;            // period
    TACCR1=IrdaPeriod/2;            // change mask
    TACCR2=IrdaPeriod+2;            // never happens
    irda_rx_data=0xffff;
    irda_rx_mask=0x0001;
    TACTL = TASSEL_2 + TACLR + MC_0;
    TACCTL1=CCIE;
    irda_rx_byte=0;
    P2IFG=0;
    P2IE=0x80;
}


#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA_modul2(void)
{        irda_rx_mask=irda_rx_mask<<1;
        if (irda_rx_mask==LastRxMask)
            {    irda_rx_byte=(char)(irda_rx_data>>1);
                TACTL = TASSEL_2 + TACLR + MC_0;
                irda_rx_data=0xffff;
                irda_rx_mask=0x0001;
                irda_rx_flag=1;
            }        
        TACCTL1 &= ~(unsigned int)CCIFG;    
}


#pragma vector=PORT2_VECTOR
__interrupt void IrdaRxPulse(void)
{ irda_rx_data&=~irda_rx_mask;
    TACTL|=    MC_1;    
    P2IFG=0;
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.