Перейти к содержанию
    

Показывайте схему. Показывайте разводку. Вероятнее всего проблема в неправильной разводке земли, либо в висящем в воздухе без подтяжки входе Reset, либо не на все ноги завели земли/питания.

 

Схема: http://electronix.ru/forum/index.php?act=a...st&id=54636

(В схеме С8 с R12 нужно поменять местами)

Плата:

 

Все неиспол. выводы сделал выходами и записал туда нули:

void Init_Ports (void) {
    DDRB  = (1<<DDB5)|(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0);
    PORTB = (1<<PB4)|(1<<PB2);

    DDRC  =  (1<<DDC5)|(1<<DDC4)|(1<<DDC3)|(1<<DDC2)|(1<<DDC0);
    PORTC =  (1<<PC1);

    DDRD  = (1<<DDD7)|(1<<DDD6)|(1<<DDD5)|(1<<DDD4)|(1<<DDD3)|(1<<DDD1)|(1<<DDD0);
    PORTD = (1<<PD2)|(1<<PD1);
}

 

---

На четвертой картинке "подсветил" именно землю на плате:

 

---

При этом я обратил внимание, что траблы именно с лампой где стоят дневного типа лампочки.. Сейчас попробую посмотреть на питающее напряжение в моменты вкл/откл такой нагрузки.

post-41215-1305274996_thumb.jpg

post-41215-1305275002_thumb.jpg

post-41215-1305275007_thumb.jpg

post-41215-1305275135_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Схема:
У вас AVcc в воздухе. По разводке - c1 далековато от ног процессра. Подключите AVcc, не забудьте на него тоже емкость повесить.

 

И очень мне не понравилась земля на конденсаторы кварца петлей через всю плату. Ее бы тут же вокруг кварца (вниз по картинке) обвести и максимально близко к земляным ногам процессора на земляную дорожку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У вас AVcc в воздухе. По разводке - c1 далековато от ног процессра. Подключите AVcc, не забудьте на него тоже емкость повесить.

 

И очень мне не понравилась земля на конденсаторы кварца петлей через всю плату. Ее бы тут же вокруг кварца (вниз по картинке) обвести и максимально близко к земляным ногам процессора на земляную дорожку.

 

Спасибо, сейчас все поправлю!

 

AVCC куда подключать? К +питания процессора? У меня в схеме не используется АЦП, AVCC обязательно подключать?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня в схеме не используется АЦП, AVCC обязательно подключать?
Читаем даташит:
AVCC is the supply voltage pin for the A/D Converter, Port C (3..0), and ADC (7..6). It should be externally connected to VCC, even if the ADC is not used. If the ADC is used, it should be connected to VCC through a low-pass filter. Note that Port C (5..4) use digital supply voltage, VCC.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ААААА:) теперь все работает даже с тремя лампами! :)

Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно чтобы считал до ICR1.

Самое простое решение для данной задачи:

FastPWM со счетом до ICR1. При 8мгц - легко получить 125кгц. И без всяких прерываний.

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Inverted
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xE2;
TCCR1B=0x19;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x3F;
OCR1AH=0x00;
OCR1AL=0x1F;
OCR1BH=0x00;
OCR1BL=0x1F;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Самое простое решение для данной задачи:

FastPWM со счетом до ICR1. При 8мгц - легко получить 125кгц. И без всяких прерываний.

 

Самое простое решение (без прерываний) подсказал Сергей Борщ. используется режим "сброс по совпадению" вот с такой фишечкой:

TCCR1A |= (1 << FOC1A);

 

 

Сегодня пробую EEPROM на ATMega8. Вот код функций чтения и записи в энергонезависимую память:

void EEPROMWrite(INT16U uiAddress, INT08U ucData) {

    while(EECR & (1<<EEWE))                                     // Wait for completion of previous write /
;
    EEAR = uiAddress;                                           // Set up address and data registers /
    EEDR = ucData;
    EECR |= (1<<EEMWE);                                         // Write logical one to EEMWE /
    EECR |= (1<<EEWE);                                          // Start eeprom write by setting EEWE /
}


INT08U EEPROMRead(INT16U uiAddress) {

    while(EECR & (1<<EEWE))                                     // Wait for completion of previous write /
;
    EEAR = uiAddress;                                           // Set up address register /
    EECR |= (1<<EERE);                                          // Start eeprom read by writing EERE /
    return EEDR;                                                // Return data from data register /
}

 

Не получается вычитывать записанные данные. В программе делаю вот так:

...
            for(i=0; i<8; i++) {
                EEPROMWrite(i, (INT08U)tmp2);
                tmp2 >>= 8;
            }


            for (i=0; i < 8; i++) 
                UARTTransmitByte ( EEPROMRead(i) );
            
...

Все четко работает. Но если заремить строку EEPROMWrite(i, (INT08U)tmp2);, то получаю вместо записанной и сохраненной информации 0xFFы...

Где я ошибся? Спасибо!

 

 

---

Я все понял! :))))))))0 Кто догадается в чем дело было?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Самое простое решение (без прерываний) подсказал Сергей Борщ.
На самом деле dimka76 прав - в режиме Fast PWM можно ограничить период значением ICR1. А выходы настроить дергаться в противофазе. Тогда не нужен будет FOC1A, вся настройка сведется к трем строчкам.

Я все понял! :))))))))0 Кто догадается в чем дело было?
EEPROM стиралась вместе ко старым кодом перед записью новой прошивки?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все четко работает. Но если заремить строку EEPROMWrite(i, (INT08U)tmp2);, то получаю вместо записанной и сохраненной информации 0xFFы...

 

Я все понял! :))))))))0 Кто догадается в чем дело было?

Ну наверно в этом:

tmp2 >>= 8;

А если заремить, то читались, видимо, ранее правильно записанные данные.

Правда, я сей (или сёв?) не знаю и могу только предположить, что при сдвиге на 8 в регистре оказываются единицы.

Это по поводу загадки.

А по делу на всякий пожарный напомню, что между запись EEWE д. б. после EEMWE в теч. не более 4-х тактов. Если у Вас в программе разрешены прерывания, условие может нарушиться

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

EEPROM стиралась вместе ко старым кодом перед записью новой прошивки?

Да, именно так:)

 

А по делу на всякий пожарный напомню, что между запись EEWE д. б. после EEMWE в теч. не более 4-х тактов. Если у Вас в программе разрешены прерывания, условие может нарушиться

То есть лучше кусочек который пишет значения в ЕЕПРОМ, заключить в:

    
__disable_interrupt(); 
...
__enable_interrupt();

?

 

 

Подскажите, как программно выполнить ресет? Вот у меня в программе есть место где по сути дела алгоритм должен просто начать выполняться с самого начала, как выполнить ресет программно? Спасибо!

АТMega8, IAR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть лучше кусочек который пишет значения в ЕЕПРОМ, заключить в:

    
__disable_interrupt(); 
...
__enable_interrupt();

?

Это небезопасно, т.к. этим кодом можно несанкционированно разрешить прерывания там, где они запрещены. Лучше так:

char temp = SREG;
__disable_interrupt();
...
SREG = temp;

 

Про ресет тут целая тема на нескольких страницах была. В кратце: если аппаратно надо сбросить, то только с помощью WatchDog это можно сделать, если просто програмно перепрыгнуть куда-либо, то как-то так:

unsigned short Addr = (unsigned short)main;
((void(*)(void))Addr)();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть лучше кусочек который пишет значения в ЕЕПРОМ, заключить в:
Лучше всего воспользоваться средствами компилятора:

#include <stdint.h>  // И не нужно придумывать свои типы вроде UINT8U
__eeprom uint8_t My_data[8];

void test()
{

    for(uint_fast8_t i = 0; i < sizeof(My_data) / sizeof(My_data[0]); ++i)
          My_data[i] = i;

    for(uint_fast8_t i = 0; i < sizeof(My_data) / sizeof(My_data[0]); ++i)
          UARTTransmitByte(My_data[i]);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это небезопасно, т.к. этим кодом можно несанкционированно разрешить прерывания там, где они запрещены. Лучше так:

char temp = SREG;
__disable_interrupt();
...
SREG = temp;

 

Если используете gcc (он же WinAVR), то в util/atomic.h есть средства для работы с атомарными блоками. Можно использовать такую конструкцию

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
// тут код блока с атомарным доступом
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...