Таймеры/счётчики в AVR
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Таймеры/счётчики в AVR
очень осмысленно
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Эйлер Леонард
- Встал на лапы
- Сообщения: 104
- Зарегистрирован: Пн ноя 04, 2019 09:58:29
- Откуда: г. Нижний Тагил Свердл. обл.
Re: Таймеры/счётчики в AVR
Добрый вечер. В таблице прескалеров AVR (ATmega328P/ATmega2560 напр.) при настройке 16-битных таймеров
есть режим "внешний источник синхронизации Tn_FALLING/Tn_RISING и лапа
на микроконтроллере для подключения этого самого источника синхронизации Tn.
Вопрос - как можно использовать такой прескалер, при каких режимах, с какими прерываниями.
Гуглил про "внешний источник синхронизации Tn_FALLING/Tn_RISING" - информации не очень много.
Может кто накинет простой примерчик.
есть режим "внешний источник синхронизации Tn_FALLING/Tn_RISING и лапа
на микроконтроллере для подключения этого самого источника синхронизации Tn.
Вопрос - как можно использовать такой прескалер, при каких режимах, с какими прерываниями.
Гуглил про "внешний источник синхронизации Tn_FALLING/Tn_RISING" - информации не очень много.
Может кто накинет простой примерчик.
- Eats
- Потрогал лапой паяльник
- Сообщения: 309
- Зарегистрирован: Сб фев 18, 2023 21:51:01
- Откуда: Санкт-Петербург
Re: Таймеры/счётчики в AVR
[uquote="Эйлер Леонард",url="/forum/viewtopic.php?p=4399390#p4399390"]В таблице прескалеров AVR (ATmega328P/ATmega2560 напр.) при настройке 16-битных[/uquote]Не только. В 328-й с 8-битным Т0 это тоже работает. В 2560 не смотрел, ни к чему пока.
Нету там внешнего источника синхронизации! Есть внешний источник тактовой частоты. А синхронизация делается с внутренней тактовой частотой ядра, чтобы пользователь не пытался подать на входы Т0/Т1 частоту выше внутренней.таймеров есть режим "внешний источник синхронизации
Во всех режимах, со всеми прерываниями.Вопрос - как можно использовать такой прескалер, при каких режимах, с какими прерываниями.
Чего там гуглить-то??? Всё расписано в даташите, глава 17 (T0&T1 Prescalers), 15 (8-bit T0) и 16 (16-bit T1). Ну подали тактовую частоту не изнутри, а снаружи, вот и все дела.Гуглил про "внешний источник синхронизации Tn_FALLING/Tn_RISING" - информации не очень много.
Всего доброго.
Евгений.
Евгений.
- Эйлер Леонард
- Встал на лапы
- Сообщения: 104
- Зарегистрирован: Пн ноя 04, 2019 09:58:29
- Откуда: г. Нижний Тагил Свердл. обл.
Re: Таймеры/счётчики в AVR
Вы правы. Сам себя немного запутал. Протеус виноват. Не показывал в режиме реального времени. Взял симулятор полегче SimulIDE и картина прояснилась. Просто тестирую библиотечку (ссылка на мой Google-диск) TimerHelpers.h. Все режимы проверил, а на таком застрял. Оказывается все очень просто.
Страница оригинала Timers and counters
Файла отсюда ->TimerHelpers.zip. Я лишь применил приемы метапрограммирования, строгой типизации ну и ещё там чего.. Вроде как фурычит, да и ничего в коде менять не надо при изменении микроконтроллера. Применимо для ATmega328P/ATmega2560. AtmelStudio -std=c++14.
Код: Выделить всё
/* ATmega328P/ATmega2560 AtmelStudio -std=c++14 */
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include "E:\lib\src\AVR\GPIO.h"
#include "E:\AVR_PWM\Timers328(test)\src\TimerHelpers.h"
// Частота регулируется предделителем. Режим 1
// для F_CPU 16000000
// clk/1 - 31,4 kHz,
// clk/8 - 3,9 kHz, 16000000/8 = 2000000 Hz
// clk/64 - 490 Hz, 16000000/64 = 250000 Hz
// clk/256 - 122 Hz, 16000000/256 = 62500 Hz
// clk/1024 - 30 Hz 16000000/1024 = 15625 Hz
TimerHelper16<1, PRESCALE::Tn_RISING, (PORT::SET_A_ON_COMPARE | PORT::SET_B_ON_COMPARE)> timer1;
GPIO<BOARD::OC1A> OC1A; // PinB1
GPIO<BOARD::OC1B> OC1B; // PinB2
GPIO<BOARD::T1> T1; // PinD5
int main(void){
// Порты на вывод
OC1A.output();
OC1B.output();
T1.input();
T1.high();
timer1.setMode<TimerControlRegister::TCCR_1A, TimerControlRegister::TCCR_1B>();
TCNT1 = 0; // 256 max
OCR1A = 200;
OCR1B = 200;
while (1) { }
return 0;
}
Файла отсюда ->TimerHelpers.zip. Я лишь применил приемы метапрограммирования, строгой типизации ну и ещё там чего.. Вроде как фурычит, да и ничего в коде менять не надо при изменении микроконтроллера. Применимо для ATmega328P/ATmega2560. AtmelStudio -std=c++14.
- Вложения
-
- TEST-2.png
- (33.45 КБ) 88 скачиваний
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Таймеры/счётчики в AVR
[uquote="ARV",url="/forum/viewtopic.php?p=4332500#p4332500"]очень осмысленно[/uquote]
Приветствую.
Вроде как в стандарте писали про битовые поля. Что если размер битового поля не влезает в int то оно приводится к uint.
Приветствую.
Вроде как в стандарте писали про битовые поля. Что если размер битового поля не влезает в int то оно приводится к uint.
Ставим плюсы: )
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
Проблема заключается в том, что меняя переменную fG частота на ножке PB0 остается одной и той же(244Гц), хотя я и меняю значение переменной, участвующей в расчете значения регистра сравнения OCR1A. Формула расчета тоже довольно простая, взята из даташита. На данный момент я бы хотел решить 2 проблемы:
1) Возможность задания частоты переменной fG.
2) Возможность задания выхода частоты с МК переменной nG.
PS: значение переменных nG и fG будут менятся по SPI(код еще не написал), интересен сам принцип подобной организации задержек.
1) Возможность задания частоты переменной fG.
2) Возможность задания выхода частоты с МК переменной nG.
PS: значение переменных nG и fG будут менятся по SPI(код еще не написал), интересен сам принцип подобной организации задержек.
Спойлер
Код: Выделить всё
#include <tiny2313.h>
#include <math.h>
#include <io.h>
#include <delay.h>
#define F_CPU (8000000)
#define VFG_TIMER_MAX (65535)
#define VFG_PIN0 PORTB0
#define VFG_PIN1 PORTB1
#define VFG_PIN2 PORTB2
#define VFG_DDR DDRB
#define VFG_PORT PORTB
float fG=100;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
//void Tim1Init(void);
//void SetUpTim1A(double Foc);
void Tim1Init(void)
{
VFG_DDR = (1<<VFG_PIN0); // set pin as OUTPUT
TCCR1A = (1<<COM1A0); //toggle on compare
TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10); // set timer CTC mode
TIMSK = (1<<OCIE1A);
//SetUpTim1A(0);
#asm("sei")
}
void SetUpTim1A(float Foc) //set value OCR1A register
{
float TimDiv, OCRnx_calc=0;
unsigned int ret_OCRnx=0;
unsigned char ClockSelect=0;
unsigned char i=0;
for(i=0;i<=4;i++) {
TimDiv=(F_CPU/(2*Foc*N[i])-1);
OCRnx_calc = ceil((TimDiv/Foc) - 1);
if(OCRnx_calc >= 0 && OCRnx_calc<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
ret_OCRnx = (unsigned int)OCRnx_calc;
OCR1A = ret_OCRnx;
TCCR1B = (1<<WGM12) | ClockSelect;
}
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
VFG_PORT ^= (1<<VFG_PIN0);
}
void main(void)
{
unsigned char nG;
Tim1Init();
#asm("sei")
while(1)
{
fG=200;
SetUpTim1A(fG);
delay_ms(50);
}
}- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
warptred12, у тебя обновление регистров не там записано, или в ветвление их внеси или из цикла убери...
а флоаты там действительно нужны? как-никак 75% флеша поели....
Добавлено after 3 minutes 28 seconds:
да, и строка OCRnx_calc = ceil((TimDiv/Foc) - 1); не нужна...
хватит и OCRnx_calc = TimDiv; наверно... если я правильно понял замысел
а флоаты там действительно нужны? как-никак 75% флеша поели....
Добавлено after 3 minutes 28 seconds:
да, и строка OCRnx_calc = ceil((TimDiv/Foc) - 1); не нужна...
хватит и OCRnx_calc = TimDiv; наверно... если я правильно понял замысел
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
Ivanoff-iv писал(а):warptred12, у тебя обновление регистров не там записано, или в ветвление их внеси или из цикла убери...
а флоаты там действительно нужны? как-никак 75% флеша поели....
Добавлено after 3 minutes 28 seconds:
да, и строка OCRnx_calc = ceil((TimDiv/Foc) - 1); не нужна...
хватит и OCRnx_calc = TimDiv; наверно... если я правильно понял замысел
Код: Выделить всё
#include <tiny2313.h>
#include <math.h>
#include <io.h>
#include <delay.h>
#define F_CPU (8000000)
#define VFG_TIMER_MAX (65535)
#define VFG_PIN0 PORTB0
#define VFG_PIN1 PORTB1
#define VFG_PIN2 PORTB2
#define VFG_DDR DDRB
#define VFG_PORT PORTB
unsigned int fG=100;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
void Tim1Init(void)
{
VFG_DDR = (1<<VFG_PIN0); // set pin as OUTPUT
TCCR1A = (1<<COM1A0); //toggle on compare
TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10); // set timer CTC mode
TIMSK = (1<<OCIE1A);
//SetUpTim1A(0);
#asm("sei")
}
void SetUpTim1A(unsigned int Foc) //set value OCR1A register
{
unsigned int TimDiv;
unsigned char ClockSelect=0;
unsigned char i=0;
for(i=0;i<=4;i++) {
TimDiv=(F_CPU/(2*Foc*N[i])-1);
if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
OCR1A = TimDiv;
TCCR1B = (1<<WGM12) | ClockSelect;
}
}
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
VFG_PORT ^= (1<<VFG_PIN0);
}
void main(void)
{
unsigned char nG;
Tim1Init();
#asm("sei")
while(1)
{
fG=200;
SetUpTim1A(fG);
delay_ms(50);
}
}- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
есть 2 варианта
1) если при вводе недопустимо маленькой частоты (например 0) нужно остановить генерацию то нужно вынести за пределы цикла (просто перенести закрывающую цикл скобку на 3 строки вверх)2) если при вводе недопустимо маленького значения его нужно проигнорировать, то обновление регистров надо внести в условие, но поставить надо до брейка, а не после.
Добавлено after 5 minutes 30 seconds:
второй вариант вашего кода совсем негоден - там условие не выполнится никогда, т.к. переменная просто переполнится
1) если при вводе недопустимо маленькой частоты (например 0) нужно остановить генерацию то нужно вынести за пределы цикла (просто перенести закрывающую цикл скобку на 3 строки вверх)
Спойлер
примерно так... поправил ф-ю не пытаясь её оптимизировать.Код: Выделить всё
void SetUpTim1A(float Foc) //set value OCR1A register
{
float TimDiv, OCRnx_calc=0;
unsigned int ret_OCRnx=0;
unsigned char ClockSelect=0;
unsigned char i=0;
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*Foc*N[i])-1);
OCRnx_calc = TimDiv; //ceil((TimDiv/Foc) - 1);
if(OCRnx_calc >= 0 && OCRnx_calc<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
ret_OCRnx = (unsigned int)OCRnx_calc;
OCR1A = ret_OCRnx;
TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
}Добавлено after 5 minutes 30 seconds:
второй вариант вашего кода совсем негоден - там условие не выполнится никогда, т.к. переменная просто переполнится
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=4424542#p4424542"]есть 2 варианта
1) если при вводе недопустимо маленькой частоты (например 0) нужно остановить генерацию то нужно вынести за пределы цикла (просто перенести закрывающую цикл скобку на 3 строки вверх)2) если при вводе недопустимо маленького значения его нужно проигнорировать, то обновление регистров надо внести в условие, но поставить надо до брейка, а не после.
Добавлено after 5 minutes 30 seconds:
второй вариант вашего кода совсем негоден - там условие не выполнится никогда, т.к. переменная просто переполнится[/uquote]
ваш вариант помог, спасибо, а как мне в прерывании дергать другими ножками в зависимости от переменной ng?
1) если при вводе недопустимо маленькой частоты (например 0) нужно остановить генерацию то нужно вынести за пределы цикла (просто перенести закрывающую цикл скобку на 3 строки вверх)
Спойлер
примерно так... поправил ф-ю не пытаясь её оптимизировать.Код: Выделить всё
void SetUpTim1A(float Foc) //set value OCR1A register
{
float TimDiv, OCRnx_calc=0;
unsigned int ret_OCRnx=0;
unsigned char ClockSelect=0;
unsigned char i=0;
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*Foc*N[i])-1);
OCRnx_calc = TimDiv; //ceil((TimDiv/Foc) - 1);
if(OCRnx_calc >= 0 && OCRnx_calc<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
ret_OCRnx = (unsigned int)OCRnx_calc;
OCR1A = ret_OCRnx;
TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
}Добавлено after 5 minutes 30 seconds:
второй вариант вашего кода совсем негоден - там условие не выполнится никогда, т.к. переменная просто переполнится[/uquote]
ваш вариант помог, спасибо, а как мне в прерывании
Код: Выделить всё
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
VFG_PORT ^= (1<<VFG_PIN0);
}- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
а как надо дёргать?
nG это номер ноги или маска?
задействован весь порт?
обнулять неиспользуемые ноги надо? (в момент переключения ноги там ведь и 1 может остаться)
Добавлено after 3 minutes 15 seconds:
ПС:
1) не цитируй прошлое сообщение, ответ итак подразумевает, что он следует за прошлым сообщением.
2) не цитируй всё сообщение, допустимо выделять только главную мысль (иногда допустимо выделять г.м. и в прошлом сообщении)
за полное цитирование могут забанить.
nG это номер ноги или маска?
задействован весь порт?
обнулять неиспользуемые ноги надо? (в момент переключения ноги там ведь и 1 может остаться)
Добавлено after 3 minutes 15 seconds:
ПС:
1) не цитируй прошлое сообщение, ответ итак подразумевает, что он следует за прошлым сообщением.
2) не цитируй всё сообщение, допустимо выделять только главную мысль (иногда допустимо выделять г.м. и в прошлом сообщении)
за полное цитирование могут забанить.
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
я хочу чтобы в зависимости от значения переменной nG частота генерировалась на определенной ножке контроллера, напрмер: при nG=0, мы генерируем частоту заданную пременной fG на ножке PB0, при этом все остальные ножки отключаются, при nG=1 на ножке PB1 и тд.
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{unsigned char msc=(1<<nG);
VFG_DDR = msc;
VFG_PORT = (VFG_PORT^msc)&(msc);
}
Добавлено after 1 minute 3 seconds:
nG придётся сделать глобальной
(локальное в майн её объявление убери)
Добавлено after 11 minutes 1 second:
для экономии времени в прерывании желательно маску msc вычислять за его пределами, например написать ф-ю её обновления (ф-ю переключатель пина) и вызывать её.
Добавлено after 3 minutes 23 seconds:
тогда это будет выглядеть так:
{unsigned char msc=(1<<nG);
VFG_DDR = msc;
VFG_PORT = (VFG_PORT^msc)&(msc);
}
Добавлено after 1 minute 3 seconds:
nG придётся сделать глобальной
(локальное в майн её объявление убери)
Добавлено after 11 minutes 1 second:
для экономии времени в прерывании желательно маску msc вычислять за его пределами, например написать ф-ю её обновления (ф-ю переключатель пина) и вызывать её.
Добавлено after 3 minutes 23 seconds:
тогда это будет выглядеть так:
Спойлер
Код: Выделить всё
void set_out_pin (char num){
nG=1<<num;
VFG_DDR = nG;
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
VFG_PORT = (VFG_PORT^nG)&(nG);
}
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
При симуляции в протеусе, напряжение есть только на выводе PB0, но на пинах, заданных переменной nG - напряжения нет, но на их выводах есть частота. Это протеус шалит или так и должно быть ?
Так же при задании переменной fG частот 0, 1, 2, 3 на выходе получается частоты 4, 5, 4.5, 14 Гц соответственно, а должны быть частоты 0, 1, 2, 3 Гц. Может быть у вас будут какие нибудь мысли по этому поводу. Откорректированный код прикрепляю ниже.
Так же при задании переменной fG частот 0, 1, 2, 3 на выходе получается частоты 4, 5, 4.5, 14 Гц соответственно, а должны быть частоты 0, 1, 2, 3 Гц. Может быть у вас будут какие нибудь мысли по этому поводу. Откорректированный код прикрепляю ниже.
Код: Выделить всё
#include <tiny2313.h>
#include <math.h>
#include <io.h>
#include <delay.h>
#define F_CPU (8000000)
#define VFG_TIMER_MAX (65535)
#define VFG_PIN0 PORTB0
#define VFG_PIN1 PORTB1
#define VFG_PIN2 PORTB2
#define VFG_DDR DDRB
#define VFG_PORT PORTB
unsigned int fG=100;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
void Tim1Init(void)
{
TCCR1A = (1<<COM1A0); //toggle on compare
TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10); // set timer CTC mode
TIMSK = (1<<OCIE1A);
//SetUpTim1A(0);
#asm("sei")
}
void SetUpTim1A(unsigned int Foc) //set value OCR1A register
{
unsigned int TimDiv, OCRnx_calc=0;
unsigned int ret_OCRnx=0;
unsigned char ClockSelect=0;
unsigned char i=0;
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*16*Foc*N[i])-1);
OCRnx_calc = TimDiv;
if(OCRnx_calc >= 0 && OCRnx_calc<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
ret_OCRnx = (unsigned int)OCRnx_calc;
OCR1A = ret_OCRnx;
TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
}
void UpdateTim1A(unsigned int freq) //хранение старого значения
{
static unsigned int fG_old = 0;
if (fG_old != freq)
{
SetUpTim1A(freq);
fG_old = freq;
}
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
unsigned char msc=(1<<nG);
VFG_DDR = msc;
VFG_PORT = (VFG_PORT^msc)&(msc);
}
void main(void)
{
static unsigned int fG_old = 0;
Tim1Init();
UpdateTim1A(fG);
#asm("sei")
for(;;) {
if (fG_old != fG) { //проверка, не изменилось ли старое значение
SetUpTim1A(fG);
fG_old = fG;
}
nG=0; //номер генератора
fG=4; //частота генератора
SetUpTim1A(fG);
delay_ms(50);
}
}- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
в коде приберись, должно заработать...
Добавлено after 59 seconds:
длинные портянки стоит заворачивать в спойлер, так проще потом ориентироваться на странице
Добавлено after 59 seconds:
длинные портянки стоит заворачивать в спойлер, так проще потом ориентироваться на странице
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
-
warptred12
- Открыл глаза
- Сообщения: 76
- Зарегистрирован: Чт июн 01, 2023 11:30:34
Re: Таймеры/счётчики в AVR
Спасибо за помощь, столько проблем помогли решить 
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
Спойлер
Код: Выделить всё
#include <tiny2313.h>
#include <math.h>
#include <io.h>
#include <delay.h>
#define F_CPU (8000000)
#define VFG_TIMER_MAX (65535)
#define VFG_DDR DDRB
#define VFG_PORT PORTB
float fG=0;
unsigned char nG;
const unsigned int N[]={1,8,64,256,1024};
//void Tim1Init(void);
//void SetUpTim1A(double Foc);
void Tim1Init(void)
{
TCCR1A = (1<<COM1A0); //toggle on compare
TCCR1B = (1<<WGM12); // set timer CTC mode
TIMSK = (1<<OCIE1A);
//SetUpTim1A(0);
}
void SetUpTim1A(float Foc) //set value OCR1A register
{
static float Old=0;
unsigned long int TimDiv;
unsigned char i, ClockSelect=0;
if (Old==Foc) return; //проверим нужно ли обновлять.
Old=Foc;
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*Foc*N[i])-1);
if(TimDiv<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
OCR1A = TimDiv;
TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
}
void set_out_pin (char num){
nG=1<<num;
VFG_DDR = nG;
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
VFG_PORT = (VFG_PORT^nG)&(nG);
}
void main(void)
{
Tim1Init();
set_out_pin(0);
#asm("sei")
while(1)
{
fG=200;
SetUpTim1A(fG);
delay_ms(50);
}
}Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Re: Таймеры/счётчики в AVR
Извините, за глупый вопрос - я с АВР-ами не работал, но тут есть множество народу, которые на них собаку сгрызли. И, надеюсь, меня могут направить в нужную сторону, чтобы я смог решить маленькую задачку, не изучая эти древние микроконтроллеры досконально.
Так вот, есть робот на старой ArduinoNANO. Среда ардуина считает его как ATmega328P. Хочу снять механические характеристики - зависимость скорости от "приложенного напряжения". Напряжение устанавливается функциейНу и по схеме они подключены к A9-A10. Частота ШИМ настраивается записью в TCCR1B - это первый таймер?
Так, теперь как измерить скорость? у моторов есть два датчика холла которые объединены исключающим ИЛИ и заведены на D2, D3 (левый/правый) и один из дачиков заведен отдельно на D4, D5 (тоже левый/правый). Можно ли при таком включении задействовать какой из таймеров с захватом, чтобы измерить периоды импульсов (хотя бы одного колеса!). В самом роботе тахометры дают просто прерывание по перепаду уровня и просто считается расстояние (не скорость!).
схема включения
Ожидаемая частота импульсов: максимальные обороты моторов около 30 тысяч в минуту, т.е. 500 оборотов в секунду и магнитный диск имеет 6 полюсов - т.е. 3000 отсчетов в секунду.
Беглый просмотр даташита мне оптимизма насчет таймера 0 и 2 не дал. Похоже, единственная надежда на один канал захвата таймера 1...
Так вот, есть робот на старой ArduinoNANO. Среда ардуина считает его как ATmega328P. Хочу снять механические характеристики - зависимость скорости от "приложенного напряжения". Напряжение устанавливается функцией
Код: Выделить всё
const uint8_t MOTOR_RIGHT_PWM = 10;
const uint8_t MOTOR_LEFT_PWM = 9;
analogWrite(MOTOR_RIGHT_PWM, pwm);Так, теперь как измерить скорость? у моторов есть два датчика холла которые объединены исключающим ИЛИ и заведены на D2, D3 (левый/правый) и один из дачиков заведен отдельно на D4, D5 (тоже левый/правый). Можно ли при таком включении задействовать какой из таймеров с захватом, чтобы измерить периоды импульсов (хотя бы одного колеса!). В самом роботе тахометры дают просто прерывание по перепаду уровня и просто считается расстояние (не скорость!).
схема включения
Ожидаемая частота импульсов: максимальные обороты моторов около 30 тысяч в минуту, т.е. 500 оборотов в секунду и магнитный диск имеет 6 полюсов - т.е. 3000 отсчетов в секунду.
Беглый просмотр даташита мне оптимизма насчет таймера 0 и 2 не дал. Похоже, единственная надежда на один канал захвата таймера 1...
Re: Таймеры/счётчики в AVR
Можно использовать захват, если в качестве формирования периода ШИМ не выбран режим с использованием регистра ICR1.
В Вашем случае выражение определения скорости вращения
S[1/мин]=(60/6)*Fo*Nx/nox, где
Fo- частота тактирования таймера 1
Nx- число периодов измеряемой скорости за время измерения
nox- число периодов частоты тактирования за время прохождения Nx. Определив числитель константой, нужно просто определить nox.
Например
Fo=16000000
Nx=1
p_pwm=3333 период ШИМ
начальное значение ICR1=1253
конечное значение ICR1=3253
число полных периодов p_pwm=1
nox= -1253+3333+3253=5333
S[1/мин]=160000000/5333~30'001,8
В Вашем случае выражение определения скорости вращения
S[1/мин]=(60/6)*Fo*Nx/nox, где
Fo- частота тактирования таймера 1
Nx- число периодов измеряемой скорости за время измерения
nox- число периодов частоты тактирования за время прохождения Nx. Определив числитель константой, нужно просто определить nox.
Например
Fo=16000000
Nx=1
p_pwm=3333 период ШИМ
начальное значение ICR1=1253
конечное значение ICR1=3253
число полных периодов p_pwm=1
nox= -1253+3333+3253=5333
S[1/мин]=160000000/5333~30'001,8