Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Связка Ведущий - Драйвер
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Anub
Я делаю часы с индикацией на ЦСИ. Так как ЦСИ не цифровые пришлось самому сделать под них драйвер с регулированием яркости частоты перерисовки и т д. Ведущий МК отвечает за все остальное в то время как драйвер только отрисовывает цифры. Обмен между МК происходит по средствам пакетной передачи. Но с недавних пор я столкнулся с крайне неприятной проблемой - временами индикаторы тухнут, а это прямо говорит о том что драйверная функция потребила что то несъедобное, так как иначе появились бы нули. Вот как это выглядит
http://rutube.ru/tracks/1028588.html?v=c5e...bfe97242aa66f18
Функция получения пакета вроде бы как давно проверена, много раз ее использовал, вот она
Код
interrupt [USART_RXC] void usart_rx_isr(void)
{
    char data = UDR;

    if (!rx_done) {
        if (data == ':') fbp = 1;
            if (fbp) {
            rx_buffer[rx_wr_index++] = data;
            if (data =='/') {
                rx_done = 1;
                fbp = 0;
                rx_wr_index = 0;
                activeCommand(rx_buffer);
            }
            else if (rx_wr_index>=RX_BUFFER_SIZE) {
                     rx_wr_index = 0;
                     rx_buffer_overflow = 1;
                 }
        } else;
    } else rx_data_overrun = 1;

}

      void activeCommand(char c[])
{      
    USHORT a, b, d, e;
    a=rx_buffer[1];
    b=rx_buffer[2];
    d=rx_buffer[3];
    e=rx_buffer[4];
    fi=a-48;      //Так как преобразование идет в ASCII код приходится доводить значение
    se=b-48;
    th=d-48;
    fo=e-48;
          
    rx_done = 0;
}

Шлю команду по прерыванию каждую секунду так
Код
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{  
    PORTB=0x00;
    TCNT1=57723;//57723
    if (S!=59){
        S++;
    } else {
        S=0;
        M++;
    }
    if (M==60){
        M=0;
        H++;
    }
    if (H==24){
        H=0;
    }
      
        SetCountCommand[1]=M/10+48;
        SetCountCommand[2]=M%10+48;
        SetCountCommand[3]=S/10+48;
        SetCountCommand[4]=S%10+48;
        
        puts(SetCountCommand);          
}

Как видно из вышеприведенного все это прекрасно работает за исключением только того бага. Что это может быть и как это лечить?
rezident
Опреация деления (хоть и целочисленного), выполняемая в прерывании, это не есть хорошо sad.gif Замените деление умножением на "волшебное" число и сдвигами. А нахождение остатка от деления вычитанием и сдвигами.
SysRq
Зачем rx_done стаивть в 1, если вы ее тут же в activeCommand ставите в 0?
Зачем передавать массив rx_buffer[] в activeCommand, если далее в ней массив c[] не используется?
В SetCountCommand конец строки '\0' есть (предположительно следом за '/')?
777777
Цитата(rezident @ Sep 20 2008, 01:43) *
Опреация деления (хоть и целочисленного), выполняемая в прерывании, это не есть хорошо sad.gif Замените деление умножением на "волшебное" число и сдвигами. А нахождение остатка от деления вычитанием и сдвигами.

Я думаю, компилятор и сам догадается это сделать.
rezident
Цитата(777777 @ Sep 21 2008, 23:32) *
Я думаю, компилятор и сам догадается это сделать.
А откуда у компилятора такая догадливость? Любая программа ничуть не умнее программиста ее написавшего. wink.gif И тот же компилятор это тоже программа.
Для примера вот в такой программке для вычисления значения y затрачивается в 1,5-2 раза меньше тактов, чем для вычисления x. Хотя на первый взгляд операций во втором выражении больше. При этом всякие аппаратные умножители конечно же отключены, иначе выигрыш получается еще больше smile.gif
Код
unsigned int x, y;
unsigned long z=65489;
x=z/10;
y=(z*0xCCCD)>>19;
777777
Цитата(rezident @ Sep 21 2008, 22:39) *
А откуда у компилятора такая догадливость? Любая программа ничуть не умнее программиста ее написавшего. wink.gif И тот же компилятор это тоже программа.

Разумеется, но человек, писавший его, знает, что деление на константу лучше заменить умножением на обратную ей.
Цитата(rezident @ Sep 21 2008, 22:39) *
Для примера вот в такой программке для вычисления значения y затрачивается в 1,5-2 раза меньше тактов, чем для вычисления x.
Код
unsigned int x, y;
unsigned long z=65489;
x=z/10;
y=(x*0xCCCD)>>19;

Ну, еще бы! Ведь в этом примере результат вычисления 'y' всегда равен нулю. smile.gif
rezident
Цитата(777777 @ Sep 22 2008, 12:40) *
Разумеется, но человек, писавший его, знает, что деление на константу лучше заменить умножением на обратную ей.
А чем для библиотечной функции константа отличается от переменной? И какие именно компиляторы настолько умные, как вы описываете?
Цитата(777777 @ Sep 22 2008, 12:40) *
Ну, еще бы! Ведь в этом примере результат вычисления 'y' всегда равен нулю. smile.gif
Опс! Ошибочка была. Поправил.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.