Китайская Arduino Uno работа тамера-счетчика T0 в режиме Normal 32 или 64 kHz
- Войдите на сайт для отправки комментариев
Здраствуйте уважаемые форумчане!!!
На днях столкнулся с такой проблемой а именно решил запилить парочку практических работ по работе с таймерами в режимах Normal, СTC, Fast PWM, Phase Correct PWM, Phase and Frequency Correct PWM.
Итак режим Normal
#include <avr/io.h> #include <avr/interrupt.h> #define F_CPU 16000000UL ISR(TIMER0_OVF_vect){ // Прерывание по переполнению if( PINB & ( 1 << PB0 ) ){ // Условие если на выходе 1 PORTB &= ~( 1 << PB0 );} // То сбросить бит else { // Иначе PORTB |= ( 1 << PB0 );} // Установить бит } int main(void) { DDRB = (1<<PB0); // Настройка порта на выход TCCR0B |= (0<<CS12) | (0<<CS11) | (1<<CS10); // Настройка претделителя таймера T0 TIMSK0 |= (1 << TOIE1); // Разрешение прерываний по переполнению таймера TCNT0 = 0; // Выставляем начальное значение счетчика sei(); // Глобальное разрешение прерывания while (1); // Бесконечный цикл return 0; }
Компилирую в AVRStudio 5, загружаю hex файл в Arduino Uno с помощью Xloadera (http://russemotto.com/xloader/) проверяю с помощью осцилографа частоту на на ножке
Проверяю все настройки предделитель не включен по расчетной формуле 64 кГц, складывается такое ощущение что включен делитель, проверяю fuse-bit у Atmega328p с помощью AVRISP MK2
Вроде бы все норм смущает только значение Extended, на форумах пишут что значение должно быть
Low Fuse 0xFF
High Fuse 0xDE
Extended Fuse 0x05
Меняю extended прошиваю, читаю снова значение меняется на старое причем если прошить и проверить запись то пишет итс ОКей читаешь востонавливает обратно
Может здесь задача здесь и тривиальная но все таки хотелось бы знать пути решения, может и проблем ни каких нет вообще и он должен работать с такой частотой 32 кГц
russmakse, Вы падаете в прерывание 16E6/255 раз в секунду. При каждом входе вы можете либо опустить, либо поднять лапу. Стало быть полный цикл получается за два входа. Итого 32кГц
По частоте Вам уже объяснили, я бы хотел добавить по строкам 6-9.
Вам ведь там нужно просто инвертировать нулевой бит порта B (он же 8-ой цифровой пин Ардуино). Я правильно понял? Если правильно, то так и пишите:
PINB |= (1 << PB0);
всё инвертируется. Зачем так длинно-то?
Я считал так:
Тактовая частота микроконтроллера Fcpu = 16000000 Гц Требуемое время 1/64000 Гц = 0,000015625 с Период тактового сигнала микроконтроллера Tcpu = 1/Fcpu = 1/16000000 Гц= 0,0000000625 с Период тактового сигнала таймера Т0 равен Tt0 = (1/Fcpu)/k = k/Fcpu = 1/16000000 Гц = 0,0000000625 с -- где k это предделитель. n = t/Tto = 0,000015625 с/ 0,0000000625 с = 250 TCNT0 = 256 - n = 256-250 = 6 - это начально значение я не заморачивался взял ноль
Вы могли бы чуть подробней, спасибо заранее, клинит мальца
Ну, Вы посчитали параметры таймера для того, чтобы он выдал прерывание через время равное периоду! Так? А сами в течение этого времени держите HIGH, а потом в течение ещё такого же времени держите LOW. Вот и получается что Вы вдвое увеличили период или, что тоже самое, вдвое уменьшиили частоту.
russmakse, что за изврат? Зачем переводить герцы в микросекунды? Просто разделите F_CPU/ 256 и ещё раз на 2 . Вот и весь расчёт.
клинит мальца
Если "мальца" - клинит, нужно любрикант использовать. Себя ты не бережешь! ;)
======
У тебя кажбый цикл таймера длится 256 тактов, предделитель ты выключил.
На каждое переполнение ты ПЕРЕКЛЮЧАЕШЬ 0 и 1, то есть цикл таймера - у тебя ПОЛпериода.
62.5 нс * 256 = 16 мкс - у тебя ПОЛ периода (0 и 1 по очереди), А весь период - 32 мкс, что дает 31.25 КГц.
Частота появления переполнений - 62.5 КГц, но сигнал, что ты старательно строил, в ДВА раза ниже.
Спасибо большое, самое сложное искать ошибки которых нет, пояснение ЕвгенийП все поставило на свои места. dimax согласен изврат, ЕвгенийП согласен можно проще с инверсией
клинит мальца
Если "мальца" - клинит, нужно любрикант использовать. Себя ты не бережешь! ;)
Под**б защитан=))