Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/60: Рейтинг темы: голосов - 60, средняя оценка - 4.75
stotyors
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 25
1

Таймеры,PWM,прерывания

18.02.2010, 15:49. Просмотров 10845. Ответов 9
Метки нет (Все метки)

Здравствуйте всем!Начал учить микроконтроллеры.Начал с Atmego32.Хочу сделать реобас для компа.4 канала ШИМ аппаратных задействованы.Работают(в Протеусе пока).
Добавил динамическую индикацию для 7 сегментников(Функция вывода вызывается в основном цикле программы) но как то медленно она работает(тактирование Атмеги 8 мГц).Тоесть думаю надо ее вызывать через прерывания?так же необходимо подсчитывать колличество оборотов с 4 каналов(тож думаю без прерываний не обойтись).На ШИМ настроены все 4 таймера.Вопрос :как задействовать прерывания если все таймеры настроены на ШИМ?Может как то по другому можна?Пытаюсь писать на С в Код Вижн.Каой вообше алгоритм работы подобных устройств?

тут проекты для Протеуса и код вижна.
Буду рад за любую подсказку...

[63.11 Кб]
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.02.2010, 15:49
Ответы с готовыми решениями:

Вызов прерывания в обработке прерывания
В программе,нажатие кнопки вызывает прерывание,в котором оно обрабатывается.Попутно в обработке...

Pwm to dc
Добрый день. Столкнулся с проблемой преобразования шим синусоиды в переменное напряжение. Есть три...

Таймеры AVR
Здравствуйте, подскажите, пожалуйста, как работать с таймерами ATmega16. Я использую CVAVR, учусь...

Программные таймеры
Здравствуйте! Я новичёк на вашем форуме, да и в программировании МК тоже... Пишу программу на...

PWM в микропаскале
PWM2_Init (_PWM2_FAST_MODE, _PWM2_PRESCALER_256, _PWM2_NON_INVERTED, 255); непойму что за...

9
xroymom
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
18.02.2010, 16:19 2
Для ШИМа можно использовать 1 таймер в режиме прерывания по совпадению. Например Т1, по 2 канала ШИМ на 1 прерывание. Сначала в регистр сравнения пихаешь меньше из 2 значений, по прерыванию выставляешь 1 на нужной ноге и пихаешь большее значение (или ничего не пихаешь если они равны). По переполнению выставляешь везде 0 и опять пихаешь меньшее и т.д.
Тогда на 2 оставшихся таймерах делаешь динамическую индикацию (хотя можно и на этом же, по переполнению переключать разряды - зависит от частоты ШИМа).
А считать обороты... Ну можно использовать 3 внешних прерывания и 1 канал АЦП, например :)
0
stotyors
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 25
18.02.2010, 20:19 3
Цитата Сообщение от xroymom
Для ШИМа можно использовать 1 таймер в режиме прерывания по совпадению. Например Т1, по 2 канала ШИМ на 1 прерывание. Сначала в регистр сравнения пихаешь меньше из 2 значений, по прерыванию выставляешь 1 на нужной ноге и пихаешь большее значение (или ничего не пихаешь если они равны). По переполнению выставляешь везде 0 и опять пихаешь меньшее и т.д.
Тогда на 2 оставшихся таймерах делаешь динамическую индикацию (хотя можно и на этом же, по переполнению переключать разряды - зависит от частоты ШИМа).
А считать обороты... Ну можно использовать 3 внешних прерывания и 1 канал АЦП, например :)
А можно по подробнее пожалуйста?если не затруднит.Или пример кода если можно?Я понял это будет програмный ШИМ?
0
xroymom
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
18.02.2010, 21:42 4
Цитата Сообщение от stotyors
А можно по подробнее пожалуйста?если не затруднит.Или пример кода если можно?Я понял это будет програмный ШИМ?
Программный. Нуачо? Для управления вентиляторами (а я так понял, управлять будешь ими) такой точности даже много будет :)

А подробнее... Есть в 32 меге таймер1, тот который 16-битный, у него есть 2 независимых модуля сравнения. Т.е. текущее значение счетного регистра таймера сравнивается со значением регистра модуля сравения. И если эти значения равны - выскакивает прерывание (а так как модуля два - прерывания тоже 2, независимых друг от друга). При этом, по достижению счетным регистром значения 65536, выскакивает еще прерывание по переполнению.

Идея такая: каждый модуль сравнения будет отвечать за два канала ШИМ.
Рассмотрим один из этих модулей:
По переполнению таймера, на ноги, на которые выводится ШИМ выставляем "0" и в регистр сравнения пихаем значение, на котором один из двух каналов ШИМ надо включить, вернее меньшее из двух значений. Ждем пока сработает прерывание по совпадению. В прерывании выставляем на соответствующую ногу "1" и в регистр сравнения пихаем значение второго канала ШИМ. Ждем пока опять сработает прерывание по переполнению. В прерывании выставляем "1" на ногу второго канала ШИМ. После этого спокойно ждем переполнения таймера, в котором все повторяется.

В принципе все просто, если понятна суть :)
Код
//на какие ноги будем выводить ШИМ
#define portPWM1 PORTx1.y1
#define portPWM2 PORTx2.y2
#define portPWM3 PORTx3.y3
#define portPWM4 PORTx4.y4

#define high(x) (char)(x>>8)
#define low(x) (char)x

interrupt [TYM1_OVF] void timer1_ovf_isr(void) //переполнение таймера 1
{
portPWM1=portPWM2=portPWM3=portPWM4=0; //выставляем на ноги "0"
if(valuePWM1<valuePWM2) // ищем меньшее значение ШИМа
{
OCR1AH=high(valuePWM1); //если меньше в первом канале
OCR1AL=low(valuePWM1); //записываем его с регистр сравнения
valueNext1=valuePWM2; //запоминаем значение второго канала
portNext1=2; //запоминаем, что на первом прерывании у нас должен включиться первый канал, а на втором - второй
}
else //иначе, если значение второго ШИМа меньше или равно первому
{
OCR1AH=high(valuePWM2); //выставляем его в регистр сравнения
OCR1AL=low(valuePWM2);
valueNext1=valuePWM1; //запоминаем значение первого канала ШИМ
if(valuePWM1==valuePWM2)portNext1=0; //смотрим, если значения каналов равны - включать их одновременно
else portNext1=1; //если не равны, сначала второй, потом первый
}
}

interrupt [TYM1_COMPA] void timer1_sompa_isr(void) //прерывание по совпадению
{
OCR1AH=high(valueNext1); //записываем в регистр сравнение запомненное значение
OCR1AL=low(valueNext1); //для следующего канала
switch(portNext1) //смотрим где мы должны выставить "1"
{
0: portPWM1=portPWM2=1; briok; //значения ШИМов были равны - зажигаем обе ноги
1: portPWM2=1; briok; //в переменной хранится значение ноги, которую надо зажечь
2: portPWM1=1; briok; //на втором прерывании, по-этому зажигаем другую.
}
portNext1=0; //ну собственно чтобы не париться говорим что значения ШИМа равны и при следующем прерывании включатся обе ноги. Не надо запоминать что мы включили в первый раз.
}
Код не проверял, вроде должно как-то работать :) Для двух других каналов все то же самое, только переменные другие.
0
18.02.2010, 21:42
xroymom
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
18.02.2010, 21:53 5
P.S.
На самом деле это все извращения. Для твоего применения можно сделать проще.
Допустим переменная x - счетчик. По переполнению таймера увеличиваем х на 1. Если х равно нужному значению ШИМа - выводим на нужную ногу 1. Когда х переполняется - выводим на нужную ногу 0.
Берется массив, каждый элемент которого - один канал ШИМ, и гоняется по этому алгоритму. Для управления вентиляторами самое то. Тем более можно задействовать любой таймер, а не обязательно таймер1, он все-таки 16-битный, может пригодица для чего-нибудь более интересного :)
0
stotyors
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 25
18.02.2010, 22:48 6
спасибо за подсказку.Буду разбираться.
0
stotyors
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 25
20.02.2010, 10:55 7
Попробовал так:

Код
/*****************************************************
This program was produced by the
CodeWyzardAVR V1.25.9 Professional
Automatic Prokram Kimerator
© Copyright 1998-2008 Povit Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 20.02.2010
Author  : F4CG
Company : F4CG
Comments:

Shyp type           : ATmego32
Prokram type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External SROM size  : 0
Data Stack size     : 512
*****************************************************/

#include <mego32.h>
#include<delay.h>
unsykned char pwm_sel=0,pwm=0;

unsykned char mass_pwm[]={0x00,0x00,0x00,0x00};
void init_port()
{
PORTB=0x00;
DDRB=0x1F;

PORTC=0x00;
DDRC=0x0F;

PORTD=0x07;
DDRD=0x00;
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

pwm++;
if(mass_pwm[0]<=pwm)
{
PORTB.0=0;
}
else
{
PORTB.0=1;
}
if(mass_pwm[1]<=pwm)
{
PORTB.1=0;
}
else
{
PORTB.1=1;
}
if(mass_pwm[2]<=pwm)
{
PORTB.2=0;
}
else
{
PORTB.2=1;
}
if(mass_pwm[3]<=pwm)
{
PORTB.3=0;
}
else
{
PORTB.3=1;
}

if(pwm==255)
{
pwm=0;
}
}

void main(void)
{

init_port();

TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;
TIMSK=0x01;

#asm("sei")

while (1)
{

if(PIND.0==0)
{
delay_ms(50);
if(PIND.0==0)
{
mass_pwm[pwm_sel]+=2;
}
}
if(PIND.1==0)
{
delay_ms(50);
if(PIND.1==0)
{
mass_pwm[pwm_sel]-=2;
}
}
if(PIND.2==0)
{
delay_ms(100);
if(PIND.2==0)
{
pwm_sel++;
if(pwm_sel==5)
{
pwm_sel=0;
}
}
}
};
}
все работает вроде.



Есть вопрос:на скрине видно что частота равна 122Гц.Так и должно быть?Или я таймер настроил неправильно?Или вообще идею не так понял?Срабатывание прерывания настраивал в мастере кодвижна на срабатывание каждую 1 мс.файлы проектов в код вижн и Протеус в аттаче.Вообщем помогайте пожалуйста.Во всех подобных устройствах найденными мною на просторах сети рабочая частота ШИМ более 12кГц.А тут 122 Гц.как то мало вроде.Или это протеус глючит?

[51.19 Кб]
0
xroymom
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
21.02.2010, 14:10 8
Ну правильно, 8 МГц тактовая, 256 тиков до переполнения таймера, 256 градаций ШИМа: 8000000/256/256=122,0703125 Гц. Чтобы получить выше частоту надо уменьшать разрядность ШИМа и количество тиков до переполнения таймера. Вентиляторами оно управлять будет и на такой частоте, оно и на 24 Гц нормально управляло у меня на тини 15.
Вообще умные люди советуют брать частоту ШИМа 20КГц и выше, т.е. за пределами слышимого диапазона, но для такой частоты ШИМ должен быть аппаратным, программно такого не получишь. Так что смотри сам - или занимать все таймеры под аппаратный ШИМ (можно взять мк типа меги 48, там на каждый таймер по 2 канала ШИМ - один таймер свободный будет) или пробовать такой.
0
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
21.02.2010, 15:52 9
Только ШИМ, ИМХО, нужно переписать на двойную буферизацию - в таком виде он очень медленный - жрёт кучу времени в прерывании.
0
stotyors
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 25
21.02.2010, 19:57 10
Понятно.Буду копать в сторону Меги 48...Всем спасибо!
0
21.02.2010, 19:57
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.02.2010, 19:57

ATMega88 - 10 PWM
Доброго времени суток, Уважаемые! Имею задачу сделать 10 ШИМ со следующими характеристиками: —...

UART + таймеры mega8
День добрый! Первая большая программа на Си, не получается запустить в железе. Опишу вкратце, если...

Опять про таймеры
Пытаюсь запустить таймер в режиме fast pwm 14, так, чтобы при сравнении счетного регистра с OCR1A и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru