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

NDG

Members
  • Постов

    5
  • Зарегистрирован

  • Посещение

Информация

  • Город
    Москва

Электроника

  • Стаж в электронике
    Не связан с электроникой

Посетители профиля

Блок последних пользователей отключён и не показывается другим пользователям.

Достижения NDG

Новичок

Новичок (1/14)

  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. Вот кусочек кода из другой моей разработки - реально работающей на объекте: ISR (PCINT0_vect) //Обработчик прерывания PCIE { flag_PCINT = true; //Устанавливаем флаг прерывания ДЛЯ ПРОГРАММЫ } int main(void) { Init_mail(); while (1) { if (flag_PCINT == true) { if (start_flag == false) { Button_Block; Rele; Wait; //Если состояние PORTB1 LOW, то реле не сработало if (!Port_HIGH) led_error (2); else Contact; Wait; //Если состояние PORTB1 HIGH, то контактор не сработал if (Port_HIGH) led_error (2); else { start_flag = true; flag_PCINT = false; } //Сбрабываем флаги } else if (start_flag == true) { Rele; Wait; LED_Off; start_flag = false; flag_PCINT = false; } }
  2. По фронту можно отловить только INT0 на РВ0, а у меня используется PCIE. Это прерывание не настраивается, а только сигнализирует об изменении уровня. На это прерывание завязаны все оставшиеся порты РВ1-РВ5. Именно поэтому накладывается маска PCMSK. В случае если ловим прерывание с нескольких портов, через сдвиг, определяем кто именно вызвал прерывание, и далее что делать . Ну, а если с одного, то через маску проверяем, что изменилось - LOW -> HIGH или наоборот, и далее что делать.
  3. Неделя мозгового штурма и задача решена. Не знаю как это правильно объяснить, но проблема кроется в обработчике прерываний и используемом режиме ШИМ. Выяснилось, что обработчику прерывания требуется несколько дополнительных тактов, в течение которых теряются значения счётчиков . Поэтому грубую работу в лоб пришлось разделить на части создание пресета скважности - обработка прерывания - расчёт значения пресета в соответствии с состоянием РВ2 РВ3 РВ4 - установка OCRA0 значением из пресета. Вот как то так.
  4. Спасибо откликнувшимся. Выводы PB0 и PB1 это единственные ноги на которые аппаратно завязан выход ШИМ. На РВ0 так же завязан INT0, поэтому использовать это прерывание не возможно. Поэтому решил использовать PCIE, который реагирует на изменение состояния порта - поэтому PB4 PB3 PB2 переведены на вход в состояние Pull-Up, что бы слушать шину. Как только на любой из трех ног измениться состояние с LOW на HIGH, включается обработчик прерывания, в котором считывается, через PINB, состояние выводов. Далее выборка и... проблема - значение OCR0A поменялось, а скважность нет. Причём если запихнуть это без SWITCH в обработчик - работает, добавит здесь же условия IF() - работает. Но это же обработчик прерывания - негоже здесь время занимать. Есть мысль, что всё завязано на двойной буферизации. Да в Proteus файле я закоротил кнопки - это для эксперимента, забыл убрать.
  5. Прошу помощи сообщества в решении такой проблемы. Имеем Attiny13 задачей которой стоит формирование ШИМ сигнала, скважность задаём состояние входов PB4 PB3 PB2. Загвоздка в том, что не могу заставить тиньку сменить скважность, несмотря на то, что на прерывание по состоянию входов реагирует, значения в OCR0A заносит. Маленькое замечание в железе не делал, только в Proteus. Код: #define F_CPU 9600000 #include <avr/io.h> #include <avr/eeprom.h> #include <avr/interrupt.h> volatile bool SetMode_flag = false; volatile char Select_Mode = 0; //------------------------------------------------- void PWM_init() { //Порты PB0 и PB1 устанавливаем на выход, остальные на вход DDRB = 0b00000011; //Входные порты PINB0 и PINB1 в HIGH, остальные в Pull-UP PORTB = 0b00111111; //Разрешаем прерывания PCINT1 - по изменению вывода GIMSK |= (1<<PCIE); //Накладываем маску на выводы PCMSK |= (1<<PINB4) |(1<<PINB3) |(1<<PINB2); //Запрещаем все прерывания пo совпадению и переполнению TIMSK0 = 0x00; //Устанавливаем режим работы таймера в режиме ШИМ с фазовой коррекцией TCCR0A |= (1<<COM0A1) |(1<<COM0B1) |(0<<WGM01) |(1<<WGM00); TCCR0B |= (1<WGM02); //Предделитель частоты уставливаем clk\1024 или приблизительно 18Гц // Fclk_I/O //Fpcpwm = -------- (N предделитель 1, 8, 64, 256, 1024) // N *510 TCCR0B |= (1<<CS02) |(0<<CS01) |(1<<CS00); //Обнуляем счётный регистр TCNT0 = 0x00; } //------------------------------------------------- ISR (PCINT0_vect) { SetMode_flag = true; // Устанавливаем флаг события Select_Mode = (PINB >> 2); //Сохраняем значение со сдвигом младших разрядов } //------------------------------------------------- int main(void) { PWM_init(); sei(); while (1) { if (SetMode_flag) { switch ( Select_Mode ) { case 0: OCR0A = 0; break; // ШИМ выключен case 1: OCR0A = 40; break; //Скважность 15% case 2: OCR0A = 80; break; //Скважность 30% case 3: OCR0A = 120; break; //Скважность 45% case 4: OCR0A = 150; break; //Скважность 60% case 5: OCR0A = 180; break; //Скважность 75% case 6: OCR0A = 210; break; //Скважность 90% case 7: OCR0A = 255; break; //Включен постоянно default: break; } SetMode_flag = false; //Сбрасывем флаг } } } main.cpp PWM neew.pdsprj
×
×
  • Создать...