Реклама на сайте DatasheetsDatasheets

KAZUS.RUN - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Книги и журналы
FAQ по электронике

  Datasheets
Поиск SMD
Онлайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Схемы и проекты
Принципиальные схемы
  Программы
Каталог сайтов
Калькуляторы
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы

WinAvr Atmega L297 L298

Непрочитано 08.03.2011, 17:28  
Sho_otnik
Частый гость
 
Аватар для Sho_otnik
 
Регистрация: 01.01.2011
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Sho_otnik на пути к лучшему
По умолчанию WinAvr Atmega L297 L298

Ребят схожу с ума:
Разрабатываю контроллер ШД с указанной связкой в теме.
Требуется получить определенное кол-во импульсов (здесь 10) с определенным периодом (здесь 1 с) на PB3. Таймер настроен на 250 (TCNT=0x06) тактов с делителем на 8 (TCCR0=(0‹‹CS00)|(1‹‹CS01)|(0‹‹CS02), переменная count_T - флаг для обсчета временного интервала. Проблема стоит в том, что проверка нуля на линии PB3 совсем не проходит (if (bit_is_0(PINB,3)) {sig_clock(freq_in,step_in,count_T); }), как не пробовал. Пробовал делать без проверки, просто запускал функцию sig_clock - ведет себя мягко говоря странно. подозреваю, что где-то конкретный косяк в таймере или в возвращении count_T.
Я уже измучился, если идей не будет совершу самое жестокое сделаю все на _ms_delay(freq_f). Помогите)

Код:
#define F_CPU 4000000UL 
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹util/atomic.h›

#define bit_is_0(reg, bit) (!(reg & (1‹‹(bit))))

volatile unsigned int count_T=0;

ISR(TIMER0_OVF_vect){
count_T++;
TCNT0=0x06;     
};

void sig_clock(volatile unsigned int freq_f, volatile unsigned int step_f, volatile unsigned int count_f)
{
   ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  for (unsigned int a=0;a‹step_f;a++){
            if (count_f==freq_f) {
                PORTB^= _BV(PB1);
                step_f--;
                count_f=0;
            }
        }
	}	
}

int main(void){ 
volatile unsigned int freq_in=0;
volatile unsigned int step_in=0;

DDRB=0x07; 
PORTB=0x09;

TIMSK=(1‹‹TOIE0);
TCCR0=(0‹‹CS00)|(1‹‹CS01)|(0‹‹CS02); 
TCNT0=0x06; 

sei();
  
freq_in=1000; //период 1000 мс
step_in=10;	 //кол-во импульсов

while(1){
	  
    
if (bit_is_0(PINB,3)) {sig_clock(freq_in,step_in,count_T); }
 
}
};
Реклама:

Последний раз редактировалось Sho_otnik; 08.03.2011 в 17:49.
Sho_otnik вне форума  
Непрочитано 09.03.2011, 19:42  
sspivak
Прохожий
 
Регистрация: 29.03.2010
Сообщений: 3
Сказал спасибо: 4
Сказали Спасибо 1 раз в 1 сообщении
sspivak на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

А для чего строчки
step_f--;
count_f=0;
в процедуре sig_clock? Сложилось впечатление, что Вы пытаетесь изменить step_in и count_T соответствено. Так не получится.
sspivak вне форума  
Непрочитано 09.03.2011, 20:24  
avtoneru
Прописка
 
Регистрация: 17.10.2010
Сообщений: 113
Сказал спасибо: 2
Сказали Спасибо 20 раз(а) в 12 сообщении(ях)
avtoneru на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Sho_otnik, если не трудно - можете выложить то же самое с комментариями, что в какой строчке делаете ... разгадывать ход мысли без них - можно, но можно и не угадать. Конечно, если Вас не затруднит .
avtoneru вне форума  
Сказали "Спасибо" avtoneru
Sho_otnik (10.03.2011)
Непрочитано 10.03.2011, 17:16  
Sho_otnik
Частый гость
 
Аватар для Sho_otnik
 
Регистрация: 01.01.2011
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Sho_otnik на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Задача стоит тривиальная, задаем с клавиатуры кол-во импульсов и период, нажимаем кнопку и с ножки выходят заданное кол-во и с определенным периодом прямоугольные импульсы. Не получается нифига.

Код:
#define F_CPU 4000000UL 
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹util/atomic.h›

#define bit_is_0(reg, bit) (!(reg & (1‹‹(bit)))) //макрос проверки 0 на линии порта

volatile unsigned int count_T=0; //объявляем count_T как "летучую" переменную

ISR(TIMER0_OVF_vect){ //выполняем действие по переполнению таймера0
//count_T++; // переменная для определения периода импульса, т.е. 
//если нам нужно получить период в 200 мс, нам нужно, чтобы 
//count_T=200 :)
//TCNT0=0x06; //таймер настроен на 250 тактов, т.е. на частоте 4Мгц
//переполнение будет осуществлятся через 500 мкс    
};

void sig_clock(volatile unsigned int freq_f, volatile unsigned int step_f, volatile unsigned int count_f) //функция выдачи определенного кол-ва
//импульсов с определенным периодом.
{
   ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { //атомарный блок, где
//запрещены прерывания, чтобы во время выполнения данной функции
//переменаня count_T в таймере не обрабатывалась
  for (unsigned int a=0;a‹step_f;a++){ //цикл для установления кол-ва
//импульсов.
            if (count_f==freq_f) { //условие для определения периода, если
//мы задали период freq_f=200 мс, то следственно условие будет
//истинным, только тогда, когда count_T=200.
                PORTB^= _BV(PB1); //изменяем состояние пина PB1 (получаем
//возрастающий фронт, на следующем цикле через 200мс спадающий)
                step_f--; //дискрементируем переменную step_f для отсчета
//кол-ва импульсов.
                count_f=0;//сбрасываем в 0 count_f, для того чтобы условие
//определения периода смогло выполнится снова.
            }
        }
	}	
}

int main(void){ 
volatile unsigned int freq_in=0; //переменная для определения периода
volatile unsigned int step_in=0; //переменная кол-ва импульсов 
DDRB=0x07; 
PORTB=0x09;

TIMSK=(1‹‹TOIE0);
TCCR0=(0‹‹CS00)|(1‹‹CS01)|(0‹‹CS02); //таймер с предделителем 8 
TCNT0=0x06; //начинаем считать с 6, чтобы кол-во тактов до переполнения было 250

sei();
  
freq_in=1000; //период 1000 мс
step_in=10;	 //кол-во импульсов

while(1){
	  
    
if (bit_is_0(PINB,3)) {sig_clock(freq_in,step_in,count_T); }//реализация
//кнопки, когда кнопка нажата вызываем функцию sig_clock
 
}
};
Sho_otnik вне форума  
Непрочитано 10.03.2011, 17:26  
kison
Почётный гражданин KAZUS.RUN
 
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Сообщение от Sho_otnik Посмотреть сообщение
Задача стоит тривиальная, задаем с клавиатуры кол-во импульсов и период
И где клавиатура?

Сообщение от Sho_otnik Посмотреть сообщение
нажимаем кнопку и с ножки выходят заданное кол-во и с определенным периодом прямоугольные импульсы.
Один раз выходить должны или повторяться если кнопку не отпустили?
kison вне форума  
Сказали "Спасибо" kison
Sho_otnik (10.03.2011)
Непрочитано 10.03.2011, 17:36  
Sho_otnik
Частый гость
 
Аватар для Sho_otnik
 
Регистрация: 01.01.2011
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Sho_otnik на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

клавиатуры в коде нет, это "вырезка"
Один раз выходить
Sho_otnik вне форума  
Непрочитано 10.03.2011, 18:08  
kison
Почётный гражданин KAZUS.RUN
 
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Ну тогда и цифры дайте - минимальный/максимальный период, необходимый коэффицент заполнения.
kison вне форума  
Сказали "Спасибо" kison
Sho_otnik (10.03.2011)
Непрочитано 10.03.2011, 18:14  
Sho_otnik
Частый гость
 
Аватар для Sho_otnik
 
Регистрация: 01.01.2011
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Sho_otnik на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Период: 1КГц (1мс) - 0,1Гц (10 с) (точнее 9999 мс)
Кол-во импульсов от 1 до 10000 (точнее 9999)

Т.е. подразумевается использовать 2 4-ёх разрядных индикатора. Вводим частоты и кол-во. Реализовываем программно с помощью массива, потом считаем, примерно так значения частоты и кол-ва:
Код:
freq_in=step[0]*1000+step[1]*100+step[2]*10+step[3];
step_in=step[4]*1000+step[5]*100+step[6]*10+step[7];
Sho_otnik вне форума  
Непрочитано 10.03.2011, 19:12  
sspivak
Прохожий
 
Регистрация: 29.03.2010
Сообщений: 3
Сказал спасибо: 4
Сказали Спасибо 1 раз в 1 сообщении
sspivak на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Переменная count_T у вас будет считать от 0 до 65535, а не от 0 до 200, как Вы того хотите (при условии, что Вы разкомментируете код в обработчике прерывания). Вы пишите count_f=0, но это не обнулит Вашу глобальную переменную count_T. Вы передаете в функцию только значение переменной count_T, а не ее саму. Для того чтобы функция могла изменить внешнюю переменную, нужно передавать указатель на эту переменную.
sspivak вне форума  
Непрочитано 10.03.2011, 19:38  
kison
Почётный гражданин KAZUS.RUN
 
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: WinAvr Atmega L297 L298

Вот накидал на скорую руку.
Код:
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#include ‹stdint.h›

#define OUT_PORT    PORTB
#define OUT         PB3

typedef volatile struct
{
    uint8_t fl_work     :1; // флаг индицирующий включенный вывод
    uint8_t fl_start    :1; // флаг старта вывода
    uint8_t fl_tick     :1; // тик таймера, можно использовать для синхронизации чего попало
                            // например опроса клавы и динамической индикации
} flags_t;

uint16_t volatile PERIOD;
uint16_t volatile IMP_COUNT;


flags_t flags;


ISR(TIMER0_OVF_vect)
{
static uint16_t st_inv_count;   // счетчик изменений вывода
static uint16_t st_period;       // период
static uint16_t st_time;         // таймер изменения

    if(flags.fl_work)   // проверим идет ли уже вывод
        {
        // вывод запущен
        if(st_time == 0) // проверим не пора ли изменить состояние выхода
            {
            // пора изменить
            OUT_PORT ^= (1‹‹OUT);       // собственно изменение на противоположное 
            st_inv_count--;                // на одно изменение меньше осталось
            if(st_inv_count == 0)       // не все ли вывели?
                {
                // все, больше не нужно
                flags.fl_work = 0;      // вывод закончен
                }
                else
                {
                // вывели не все
                st_time = (st_period ›› 1)-1;  // в таймер время до следующего изменения 
               
                } // if(st_inv_count == 0)
            }
            else
            {
            // еще подождем изменять, время не пришло
            st_time--;
            } // if(st_time == 0)
        }
        else
        {
        // вывод не запущен
        if(flags.fl_start)  // может нужно запустить?
            {
            // нужно запустить
            OUT_PORT ^= (1‹‹OUT);               // первое изменение на противоположное
            st_inv_count = (IMP_COUNT ‹‹ 1)-1;  // счетчик изменений
            st_period = PERIOD;                 // сохраним период
            st_time = (st_period ›› 1);         // время до следующего изменения на одно меньше половины периода
            flags.fl_start = 0;                 // старт отработан
            flags.fl_work = 1;                  // начался вывод
            } // if(flags.fl_start)
        } // if(flags.fl_work)
    // Тут перевзводим таймер
    // если нужен минимальный джиттер, то надо принять меры по его минимизации 
    // по простому же
    TCNT0 += 6;
    flags.fl_tick = 1;
} // ISR(TIMER0_OVF_vect)

 

                                                                                                                                                                                                                                                                                                                                                                                       
int main(void)
{
DDRB |= (1‹‹OUT);
TIMSK=(1‹‹TOIE0);
TCNT0 = 6;
TCCR0=(0‹‹CS00)|(1‹‹CS01)|(0‹‹CS02);

PERIOD = 5; // период в попугаях
IMP_COUNT = 4; // счетчик импульсов
sei();

while(1)
{
flags.fl_start = 1;
while(flags.fl_start){}; //ждем начала
// изменим период, это не повлияет на уже начатый вывод
PERIOD += 1;
IMP_COUNT += 1;
while(flags.fl_work){}; // ждем окончания вывода
// и повторим с новыми значениями периода и числа импульсов
}

}

Последний раз редактировалось kison; 10.03.2011 в 20:03.
kison вне форума  
Сказали "Спасибо" kison
Sho_otnik (10.03.2011)
 
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подниму тему WinAVR vs IAR oleg110592 Микроконтроллеры, АЦП, память и т.д 5 24.10.2015 14:06
Глюки WinAVR KBH-I Коллекция глюков 19 07.06.2011 01:16
Помогите с массивами в WinAvr Sho_otnik Микроконтроллеры, АЦП, память и т.д 7 07.01.2011 11:56
WinAVR не нравится символ '\' vovan_zh Микроконтроллеры, АЦП, память и т.д 10 10.09.2010 20:48
помогите начинающему по WinAVR umkamaks Микроконтроллеры, АЦП, память и т.д 4 05.05.2010 21:01


Часовой пояс GMT +4, время: 12:13.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.