ШИМ более чем 8 бит
- Войдите на сайт для отправки комментариев
Чт, 28/02/2013 - 14:24
Добрый день, коллеги!
Подскажите, pls, можно ли штатными средствами программирования Ардуины переключить ея ШИМ в режиме более чем 8-и разрядов? (Нужно хотя бы 16...)
Ogogon.
Можно попытаться программно сделать 16-ти битный ШИМ, а аппаратно только 10 бит и то только на 16-ти битном таймере.
Гм... А почему только десять?
Из умной книжки Евстифеева следует Божий План Спасения:
Разрешаются соотв. прерывания, в регистр сравнения записывается значение, задается пре-делитель для таймера T1 и он исправно дергает сигналом в момент совпадения значения с заданным числом.
Кто отгрызает биты от шестнадцати?
Ogogon.
Вы не верно понимаете о чем идет речь в этой книге. Никто ничего не отгрызает. Разрядность таймера и разрядность ШИМа - это совершенно разные вещи. Еще раз вам повторяю на дуине аппаратно на 16-ти битном таймере можно запустить максимум 10-ти битный ШИМ ,больше только программно.
Вот пример 16-ти битного ШИМа на 13 выводе, естественно со своими "недостатками"...
01
volatile uint16_t pwm = 30;
02
char
fadeAmount = 1;
03
04
void
setup
()
05
{
06
cli();
07
DDRB |= 1<<5;
08
PORTB &= ~(1<<5);
09
TCCR1A = 0;
10
TCCR1B = 1;
11
TIMSK1 = 3;
12
sei();
13
}
14
15
void
loop
()
16
{
17
pwm += fadeAmount;
18
if
(pwm == 0 || pwm == 6000) fadeAmount = -fadeAmount;
19
OCR1AH = highByte(pwm);
20
OCR1AL = lowByte(pwm);
21
delay(1);
22
}
23
24
ISR(TIMER1_COMPA_vect)
25
{
26
PORTB &= ~(1<<5);
27
}
28
29
ISR(TIMER1_OVF_vect)
30
{
31
if
(pwm > 30) PORTB |= 1<<5;
32
}
Извините пожалуйста, Максим, но я не совсем понимаю, что я не верно понимаю...
Милейший г-н Евстифеев рисует нам следующую картину мира:
Имеет быть 16-битный счетчик TCNT1. Рядом с ним стоят два 16-битных регистра сравнения ORC1A и ORC1B и без передышки сравнивают.
Значения TCNT1 непрерывно бегут вверх и когда они совпадают со значением регистра сравнения, Ардуина (точнее говоря Atmel ATMega) рефлекторно дергает ногой. На каждый регистр сравнения своей. Потом счетчик переполняется, генерирует прерывание, обнуляется и бежит с самого начала. (А. В. Евстифеев "Микроконтроллеры AVR семейств Tiny и Mega фирмы ATMEL" 5-е издание, Москва, Издательский дом «Додэка XXI», 2008. Стр. 279-300)
Если я игнорирую (или еще лучше не разрешаю) прерывание по переполнению, то эта музыка будет вечной. И еще двухканальной. Можно сказать стерео.
Вряд ли популярный автор решил разыграть читателей. Впрочем, подозревать Вас в обмане у меня тоже нет никаких оснований.
Не затруднит ли Вас объяснить, где я заблуждаюсь?
Ogogon.
Вы не верно понимаете значения слов аппаратный и программный.
То о чем вы пишите - это и есть программный способ.
Подредактировал пример выше под ваше описание.
Но и я походу ошибался (а может и нет), вроде как можно сгенерить аппаратно 16-битный ШИМ, но только на одной ноге - OC1A (дуина 9).

Даташит, раздел 15.9.3 "Fast PWM Mode" (в 15.9.4 "Phase Correct PWM Mode" - то же самое):
"The PWM resolution for fast PWM can be fixed to 8-, 9-, or 10-bit, or defined by either ICR1 or
OCR1A. The minimum resolution allowed is 2-bit (ICR1 or OCR1A set to 0x0003), and the maximum
resolution is 16-bit (ICR1 or OCR1A set to MAX)."
В 15.9.5 "Phase and Frequency Correct PWM Mode" написаны пости те же самые буквы, правда уже без фиксированных разрешений 8, 9, 10 бит.
НО...
Здесь есть одно большое "но":
Максимальная частота даже в режиме быстрого ШИМ'а - 16000000/N/(1+TOP) = 244 Гц.
Ниже - пожалуйста, выше - ни-ни...
НО...
Здесь есть одно большое "но":
Максимальная частота даже в режиме быстрого ШИМ'а - 16000000/N/(1+TOP) = 244 Гц.
Ниже - пожалуйста, выше - ни-ни...
Прошу прощения, Вы не расшифруете членов выражения?
Почему 16000000? Что есть N и ТОР?
Ogogon.
В общем, "добил" этот вопрос, я был не прав и вас ввел в заблуждение - можно организовать и аппаратный 16-битный ШИМ на обоих выводах таймера OC1A(D9) и OC1В(D10), единственный недостаток описанный выше это частота 244 Гц. Пример:
01
void
setup
()
02
{
03
cli();
04
DDRB |= 1<<1 | 1<<2;
05
PORTB &= ~(1<<1 | 1<<2);
06
TCCR1A = 0b00000010;
07
//TCCR1A = 0b10100010;
08
TCCR1B = 0b00011001;
09
ICR1H = 255;
10
ICR1L = 255;
11
sei();
12
Serial
.begin(9600);
13
}
14
15
void
loop
()
16
{
17
if
(
Serial
.available())
18
{
19
char
c =
Serial
.read();
20
uint16_t pwm =
Serial
.parseInt();
21
if
(c ==
'A'
)
22
{
23
pwm ? TCCR1A|=1<<7 : TCCR1A&=~(1<<7);
24
OCR1AH = highByte(pwm);
25
OCR1AL = lowByte(pwm);
26
}
27
if
(c ==
'B'
)
28
{
29
pwm ? TCCR1A|=1<<5 : TCCR1A&=~(1<<5);
30
OCR1BH = highByte(pwm);
31
OCR1BL = lowByte(pwm);
32
}
33
}
34
}
В сериал-монитор вводите A100, A65000 или B150, B12300 и т.д. и на соответствующих выводах (9 или 10) генерится 16-битный ШИМ с заданной скважностью.
Прошу прощения, Вы не расшифруете членов выражения?
Почему 16000000? Что есть N и ТОР?
16000000 - тактовая частота МК
TOP - разрядность
N - предделитель
16бит - TOP = 65535,
без пределителя - N = 1,
получаем:
16000000/1/(1+65535) = 244
И вот еще пример, в котором и разрядность ШИМа можно менять
01
void
setup
()
02
{
03
cli();
04
DDRB |= 1<<1 | 1<<2;
05
PORTB &= ~(1<<1 | 1<<2);
06
TCCR1A = 0b00000010;
07
//TCCR1A = 0b10100010;
08
TCCR1B = 0b00011001;
09
ICR1H = 255;
10
ICR1L = 255;
11
sei();
12
Serial
.begin(9600);
13
Serial
.println(
"PWM resolution: 16-bit"
);
14
Serial
.println(
"PWM frequency: 244 Hz"
);
15
Serial
.println(
"PWM duty OC1A(D9): 0"
);
16
Serial
.println(
"PWM duty OC1B(D10): 0"
);
17
Serial
.println();
18
}
19
20
void
loop
()
21
{
22
if
(
Serial
.available())
23
{
24
char
c =
Serial
.read();
25
uint16_t pwm =
Serial
.parseInt();
26
if
(c ==
'A'
)
27
{
28
pwm ? TCCR1A|=1<<7 : TCCR1A&=~(1<<7);
29
OCR1AH = highByte(pwm);
30
OCR1AL = lowByte(pwm);
31
Serial
.print(
"PWM duty OC1A(D9): "
);
32
Serial
.println(pwm);
33
}
34
if
(c ==
'B'
)
35
{
36
pwm ? TCCR1A|=1<<5 : TCCR1A&=~(1<<5);
37
OCR1BH = highByte(pwm);
38
OCR1BL = lowByte(pwm);
39
Serial
.print(
"PWM duty OC1B(D10): "
);
40
Serial
.println(pwm);
41
}
42
if
(c ==
'R'
)
43
{
44
Serial
.println();
45
Serial
.print(
"PWM resolution: "
);
46
Serial
.print(pwm);
47
Serial
.println(
"-bit"
);
48
pwm = pow(2, pwm);
49
ICR1H = highByte(pwm);
50
ICR1L = lowByte(pwm);
51
Serial
.print(
"PWM frequency: "
);
52
Serial
.print(16000000/(pwm+1UL));
53
Serial
.println(
" Hz"
);
54
Serial
.println();
55
}
56
}
57
}
Разрядность задается вводом в сериал символа R и количества бит: R2, R3, R4, .... R14, R15, R16
Maksim, а что делают строчки 28 и 36 в скетче? Непонятны символы знак вопроса и двоеточие.
Это проверка на 0 ,если ее убрать, то ШИМ нельзя будет отключить полностью.
Можно написать так:
if
(pwm > 0) TCCR1A |= 1<<5;
else
TCCR1A &= ~(1<<5);
или так
if
(pwm == 0) TCCR1A &= ~(1<<5);
else
TCCR1A |= 1<<5;
Спасибо, буду знать.
Будет ли работать для ардуино мега 2560, как управлять - как вводить в сериал "А100", и почему от 100 до 65000 и от 150 до 12300. заранее спасибо.
как собрать тоже самое на 120Гц?
разобрался....
Подскажите пожалуйста, таким образом можно только на 2х выходах разрядность повысить?
Мне бы еще на 3,5,6,11 ногах того же хотелось.
Подскажите пожалуйста, таким образом можно только на 2х выходах разрядность повысить?
Мне бы еще на 3,5,6,11 ногах того же хотелось.
в атмега328 один 16ти разрядный таймер с двумя каналами ШИМ, т.е. Можно иметь аппаратно только два 16бит канала ШИМ. Остальное только программно или используя другой МК
На меге 12 аппаратных каналов 16 бит
программно это c помощью map() имеется ввиду?
программно это c помощью map() имеется ввиду?
Программно делается выставлением low и high из программы по аппаратному таймеру. Тоесть пишем обработчик прерывания таймера, внутри него делаем расчет исходя из заданной скважности когда на каком пине надо поставить low, когда high
В аппаратном варианте установки low и high делаются автоматически без участия кода программы
Подскажите пожалуйста, таким образом можно только на 2х выходах разрядность повысить?
Я дико извиняюсь, но Вы твердо уверены что оно Вам надо? Я конечно понимаю, перфекционизм и максимализм, но такие задачи не каждый день наблюдаются, и очень вероятно, что Вы не тем путем идете.
Может уже говорили, но на Леонардо счётчик 4 10-битный, те два выхода шим 10-бит
Спасибо Вам axill, теперь понятно чего и как.
Привет maksim. Я проверил твою програмку на осциллографе(INSTRUSTAR ISDS205A) и для вывода ардуино d10 получил такой же график как и для D9 при диапазоне на 16битах от 150 до 65535. Причём для d9 и d10 в диапазоне от 1600 до 65535 регулировка ШИМ сигнала идёт корректно. В диапазоне 0-1600 сигнал ШИМ неравномерно распределяется по периоду повторения. Почему у вас написано что регулировка происходит в диапазоне A100, A65000 или B150, B12300??? можем списаться по почте?(oleg_komarov_1996@mail.ru)