Технический форум по робототехнике.
eugmai86 » 05 мар 2011, 16:59
Доброго времени суток.
Я новичек и столкнулся с задачей реализовать аппаратный шим на выводе PD5 tiny 2313. Я нашел пример описания шим на OC1A(PB3) однако весь порт B у меня занят под семисегментный индикатор.
использую CVAVR пишу на С.
Заранее спасибо за развернутый ответ)
boez » 05 мар 2011, 17:32
А где развернутый вопрос?
Где пример-то?
eugmai86 » 05 мар 2011, 17:55
Пример описания:
void init_pwm (void)
{
TCCR1A=(1<<COM1A1)|(1<<WGM10); //На выводе OC1A единица, когда OCR1A==TCNT1, восьмибитный ШИМ
TCCR1B=(1<<CS10); //Делитель= /1
OCR1A=0x00; //Начальная скорость нулевая
}
Этот код мне в принципе понятен, однако ШИМ будет выводиться на ногу МК которая у меня занята и освободить я ее не могу. Зато имеется свободная нога OC0B (PD5) 8 битный таймер счетчик, на эту ногу мне нужно вывести шим.
То что по моему должно работать:
void init_pwm (void)
{
TCCR0A = (0 << COM0A1) | (0 << COM0A0) // OC0A выключен
| (1 << COM0B1) | (0 << COM0B0) // включить OC0B, очистить OC0B on compare match, set OC0B at TOP
| (0 << WGM01) | (1 << WGM00); // PWM, phase correct, 8 bit
TCCR0B = (0 << WGM02) // PWM, phase correct, 8 bit
| (0 << CS02) | (0 << CS01) | (1 << CS00); // No prescaling
OCR0B = 0x00; //начальное значение нулевое
DDRD = (1 << PD5); //PD5 выход шим
}
//теперь для регулирования ШИМ я могу использовать:
OCR0B++;// увеличиваю заполнение сигнала
OCR0B--;// уменьшаю заполнение сигнала
Будет ли верна такая инициализация шим?
boez » 05 мар 2011, 19:56
Да, похоже на правду. Правда (1 << COM0B1) | (0 << COM0B0) в режиме Phase Correct PWM имеют немного другой смысл, но значение верное.
eugmai86 » 05 мар 2011, 22:17
Спасибо, вот попробовал на железе, так сказать. Не работает должным образом. Не знаю на что грешить.
#include <tiny2313.h>
unsigned int pp=100;//переменная для ШИМ скорость нарастания напряжения
//Попрограммы обработки прерываний
interrupt[EXT_INT0]void yvel_pwm(void) //обработка прерываний кнопки "+"
{
pp++;//увеличение при нажатии на кнопку "+" на 1
}
interrupt[EXT_INT1] void ymen_pwm(void)//обработка прерываний кнопки "-"
{
pp--;//уменьшение при нажатии на кнопку "-" на 1
}
//инициализация ШИМ
void init_pwm (void)
{
TCCR0A = (0 << 7) | (0 << 6) // OC0A выключен
| (1 << 5) | (0 << 4) // включить OC0B, очистить OC0B on compare match, set OC0B at TOP
| (0 << 1) | (1 << 0); // PWM, phase correct, 8 bit
TCCR0B = (0 << 2) // PWM, phase correct, 8 bit
| (0 << 2) | (1 << 1) | (0 << 0);
DDRD = (1 << 5); //PD5 выход шим
}
int main (void)
{
GIMSK=0b11000000; //разрешаем прерывание int0 и int1
MCUCR=0b00001111;// прерывание по возрастающему фронту - для кнопки 1 и 2
for (;;)//бесконечный цикл
{
OCR0B = pp;
init_pwm();
}
return(0);
}
Смысл программы в следующем, при возникновении прерывания int0 или int1 значение OCR0B должно меняться, соответственно, и меняется заполнение сигнала открывающего транзистор на выходе шим. Транзистор работает в ррежиме ключа на мотор. Увы, мотор меняет скорость вращения при каждом прерывании хаотично. Буду признателен за подсказку.
avr123.nm.ru » 05 мар 2011, 23:04
eugmai86 писал(а):использую CVAVR пишу на С.
Там есть мастер - его код всегда работает.
boez » 06 мар 2011, 01:59
1. Не надо постоянно переинициализировать таймер в цикле. Одного раза хватит.
2. Есть подозрение, что там дребезг на кнопках и переменная pp увеличивается много раз. Рекомендую для начала попробовать в прерываниях не инкрементировать переменную, а выставлять ее в фиксированное значение, скажем 25% и 75%. Если станет работать устойчиво - надо будет делать антидребезг.
Я обычно вообще не пользуюсь прерываниями для опроса кнопок, там большие скорости не нужны, можно и из цикла опрашивать.
eugmai86 » 06 мар 2011, 12:31
Спасибо, буду пробовать.
eugmai86 » 06 мар 2011, 16:53
Программа корректно заработала в таком варианте:
#include <tiny2313.h>
unsigned char pp=100;//переменная для ШИМ скорость нарастания напряжения
//Попрограммы обработки прерываний
interrupt[EXT_INT0]void yvel_pwm(void) //обработка прерываний кнопки "+"
{
pp=pp+2;//увеличение при нажатии на кнопку "+" на 1
}
interrupt[EXT_INT1] void ymen_pwm(void)//обработка прерываний кнопки "-"
{
if (pp>1)
{
pp=pp-2;
}
else
{
pp=2;//уменьшение при нажатии на кнопку "-" на 1
}
}
//инициализация ШИМ
void init_pwm (void)
{
TCCR0A = (0 << 7) | (0 << 6) // OC0A выключен
| (1 << 5) | (0 << 4) // включить OC0B, очистить OC0B on compare match, set OC0B at TOP
| (0 << 1) | (1 << 0); // PWM, phase correct, 8 bit
TCCR0B = (0 << 2) // PWM, phase correct, 8 bit
| (0 << 2) | (1 << 1) | (0 << 0);
DDRD = (1 << 5); //PD5 выход шим
}
int main (void)
{
init_pwm();
GIMSK=0b11000000; //разрешаем прерывание int0 и int1
MCUCR=0b00001111;// прерывание по возрастающему фронту - для кнопки 1 и 2
for (;;)//бесконечный цикл
{
#asm("sei");
OCR0B = pp;
}
return(0);
}
Закрывайте, спасибо