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

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

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

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

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

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

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

 
Опции темы
Непрочитано 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.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
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.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
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.RU
 
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
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, время: 13:20.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot