Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
05.05.2011, 15:42
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
Re: Алгоритм частотомера
MisterDi, от кого-кого, а от тебя не ожидал... Чему-то плохому молодого человека учишь...
Ну ладно, так приблизительно
PHP код:
|
#include ‹mega8.h›
#define FREQ_OSC 8000000
#define F_TMR0 1000000
#define F_TMR0_WORK 10 // 0.1 секунда на измерение, это 10 Герц
#define COUNTER_TMR0 F_TMR0/F_TMR0_WORK // количество тиков таймера
#define COUNTER_OVF COUNTER_TMR0/256 // количество переполнений таймера
#define COUNTER_DIFF (unsigned char)(COUNTER_TMR0-(COUNTER_OVF*256))// разница
#define COUNTER_REAL (unsigned char)(256-COUNTER_DIFF)// дополнение
//----------------------------------------------------------------------------
#define F32L 3100
#define F32H 3300
#define F44L 4300
#define F44H 4500
#define F48L 4700
#define F48H 4900
#define F96L 9500
#define F96H 9700
#define F192L 19000
#define F192H 19300
//--------------------
#define Freg32() {PORTC.0=1;PORTC.1=0;PORTC.2=0;PORTC.3=0;PORTC.4=0 ;}
#define Freg44() {PORTC.0=0;PORTC.1=1;PORTC.2=0;PORTC.3=0;PORTC.4=0 ;}
#define Freg48() {PORTC.0=0;PORTC.1=0;PORTC.2=1;PORTC.3=0;PORTC.4=0 ;}
#define Freg96() {PORTC.0=0;PORTC.1=0;PORTC.2=0;PORTC.3=1;PORTC.4=0 ;}
#define Freg192() {PORTC.0=0;PORTC.1=0;PORTC.2=0;PORTC.3=0;PORTC.4=1 ;}
//--------------------
volatile unsigned int iCounterOvf;
volatile unsigned char cKORR;
volatile unsigned char bFlagEnd,bFlagReady;
volatile unsigned int iFreq;
//-------------------------------------------------
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
if(bFlagEnd == 0)
{
iCounterOvf++;
if(iCounterOvf == COUNTER_OVF)
{
bFlagEnd=1;
TCNT0=COUNTER_REAL+cKORR;
}
}
else
{
iCounterOvf=0;
bFlagEnd=0;
//0.1 c
iFreq=TCNT1;
TCNT1=0;
cKORR=TCNT0;
bFlagReady=1;
}
}
//-------------------------------------------------
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00;
DDRC=0x7F;
// Port D initialization
// Func7=Out Func6=Out Func5=In Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=T State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xDF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
TCCR0=0x02;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: T1 pin Rising Edge
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x07;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
if( bFlagReady)
{
bFlagReady=0;
if(iFreq › F32L && iFreq ‹ F32H)
{
Freg32();
}
if(iFreq › F44L && iFreq ‹ F44H)
{
Freg44();
}
if(iFreq › F48L && iFreq ‹ F48H)
{
Freg48();
}
if(iFreq › F96L && iFreq ‹ F96H)
{
Freg96();
}
if(iFreq › F192L && iFreq ‹ F192H)
{
Freg192();
}
}
}
}
|
|
|
|
|
05.05.2011, 16:01
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.02.2008
Адрес: Днепр. Украина
Сообщений: 3,294
Сказал спасибо: 442
Сказали Спасибо 1,048 раз(а) в 706 сообщении(ях)
|
Re: Алгоритм частотомера
Цитата:
|
MisterDi, от кого-кого, а от тебя не ожидал...
|
Каюсь, ленивый стал, не додумал как правильнее. К тому же я с мегами активно не работал.
__________________
misterdi<@>i.ua
|
|
|
|
05.05.2011, 18:06
|
|
Вид на жительство
Регистрация: 05.04.2008
Адрес: Украина, Ахтырка
Сообщений: 302
Сказал спасибо: 148
Сказали Спасибо 31 раз(а) в 30 сообщении(ях)
|
Re: Алгоритм частотомера
Сообщение от urry
|
MisterDi, от кого-кого, а от тебя не ожидал... Чему-то плохому молодого человека учишь...
Ну ладно, так приблизительно
PHP код:
|
#include ‹mega8.h›
#define FREQ_OSC 8000000
#define F_TMR0 1000000
#define F_TMR0_WORK 10 // 0.1 секунда на измерение, это 10 Герц
#define COUNTER_TMR0 F_TMR0/F_TMR0_WORK // количество тиков таймера
#define COUNTER_OVF COUNTER_TMR0/256 // количество переполнений таймера
#define COUNTER_DIFF (unsigned char)(COUNTER_TMR0-(COUNTER_OVF*256))// разница
#define COUNTER_REAL (unsigned char)(256-COUNTER_DIFF)// дополнение
//----------------------------------------------------------------------------
#define F32L 3100
#define F32H 3300
#define F44L 4300
#define F44H 4500
#define F48L 4700
#define F48H 4900
#define F96L 9500
#define F96H 9700
#define F192L 19000
#define F192H 19300
//--------------------
#define Freg32() {PORTC.0=1;PORTC.1=0;PORTC.2=0;PORTC.3=0;PORTC.4=0 ;}
#define Freg44() {PORTC.0=0;PORTC.1=1;PORTC.2=0;PORTC.3=0;PORTC.4=0 ;}
#define Freg48() {PORTC.0=0;PORTC.1=0;PORTC.2=1;PORTC.3=0;PORTC.4=0 ;}
#define Freg96() {PORTC.0=0;PORTC.1=0;PORTC.2=0;PORTC.3=1;PORTC.4=0 ;}
#define Freg192() {PORTC.0=0;PORTC.1=0;PORTC.2=0;PORTC.3=0;PORTC.4=1 ;}
//--------------------
volatile unsigned int iCounterOvf;
volatile unsigned char cKORR;
volatile unsigned char bFlagEnd,bFlagReady;
volatile unsigned int iFreq;
//-------------------------------------------------
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
if(bFlagEnd == 0)
{
iCounterOvf++;
if(iCounterOvf == COUNTER_OVF)
{
bFlagEnd=1;
TCNT0=COUNTER_REAL+cKORR;
}
}
else
{
iCounterOvf=0;
bFlagEnd=0;
//0.1 c
iFreq=TCNT1;
TCNT1=0;
cKORR=TCNT0;
bFlagReady=1;
}
}
//-------------------------------------------------
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00;
DDRC=0x7F;
// Port D initialization
// Func7=Out Func6=Out Func5=In Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=T State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xDF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
TCCR0=0x02;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: T1 pin Rising Edge
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x07;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
if( bFlagReady)
{
bFlagReady=0;
if(iFreq › F32L && iFreq ‹ F32H)
{
Freg32();
}
if(iFreq › F44L && iFreq ‹ F44H)
{
Freg44();
}
if(iFreq › F48L && iFreq ‹ F48H)
{
Freg48();
}
if(iFreq › F96L && iFreq ‹ F96H)
{
Freg96();
}
if(iFreq › F192L && iFreq ‹ F192H)
{
Freg192();
}
}
}
}
|
|
Даааа, супер! Вы молодец! Спасибо
Сегодня попробую код, можете расписать словами по каком принципу работает?
Я недавно начал заниматься программированием, не очень хорошо разбираюсь...
Ели вьехал как работает прерывание )
|
|
|
|
05.05.2011, 20:17
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
Re: Алгоритм частотомера
С помощью таймера -0 отбиваем временные интервалы по 0.1 секунда, а 16 битный таймер 1 используем в режиме счета внешних импульсов - подаем их на ногу Д5. За 0.1 секунду для частоты 192 к выдаст число 19200, макс число 65535. В начале измерения обнуляем, в конце считываем.
0 таймер - всего 8 разрядный, будут переполнения для 100 мс. Подаем на 0 таймер 1 мегагерц, узнаем количество импульсов, которые должны пройти для достижения 0.1с - 1000000/10 = 100000, делим их на 256, узнаем количество переполнений таймера N, затем от 100000 отнимаем 256*N - разница, которую должны записать в последний раз, чтобы посчитало точно. Чтобы не мучить большими цифрами, допустим, нам нужно посчитать 300 - итого 1 переполнение и еще кусочек 300 - 256 =44.
Сначала записываем 0, досчитало до 255, пошло переполнение, сработало прерывание и нужно посчитать еще 44 импульса.
Поскольку прерывание у нас по переполнению, записать нужно 256 - 44 . Вот 300 импульсов и получится.
Но срабатывание прерывания тоже занимает время - подставив эти значения в таймер, увидим, что реальное время больше на время входа в прерывание и его нужно компенсировать. И ясно насколько, потому, что пока мы доходим до точки прерывания, 0 таймер продолжает считать.
И это значение 0 таймера (сколько он проскочил от 0 вправо) добавляем, уменьшая его время счета именно настолько, насколько нужно.
TCNT0=COUNTER_REAL+cKORR;
мы забираем при срабатывании
cKORR=TCNT0;
Неточным будет только первое измерение, где мы не знаем еще значение
cKORR
|
|
|
|
05.05.2011, 22:37
|
|
Вид на жительство
Регистрация: 05.04.2008
Адрес: Украина, Ахтырка
Сообщений: 302
Сказал спасибо: 148
Сказали Спасибо 31 раз(а) в 30 сообщении(ях)
|
Re: Алгоритм частотомера
Сообщение от urry
|
С помощью таймера -0 отбиваем временные интервалы по 0.1 секунда, а 16 битный таймер 1 используем в режиме счета внешних импульсов - подаем их на ногу Д5. За 0.1 секунду для частоты 192 к выдаст число 19200, макс число 65535. В начале измерения обнуляем, в конце считываем.
0 таймер - всего 8 разрядный, будут переполнения для 100 мс. Подаем на 0 таймер 1 мегагерц, узнаем количество импульсов, которые должны пройти для достижения 0.1с - 1000000/10 = 100000, делим их на 256, узнаем количество переполнений таймера N, затем от 100000 отнимаем 256*N - разница, которую должны записать в последний раз, чтобы посчитало точно. Чтобы не мучить большими цифрами, допустим, нам нужно посчитать 300 - итого 1 переполнение и еще кусочек 300 - 256 =44.
Сначала записываем 0, досчитало до 255, пошло переполнение, сработало прерывание и нужно посчитать еще 44 импульса.
Поскольку прерывание у нас по переполнению, записать нужно 256 - 44 . Вот 300 импульсов и получится.
Но срабатывание прерывания тоже занимает время - подставив эти значения в таймер, увидим, что реальное время больше на время входа в прерывание и его нужно компенсировать. И ясно насколько, потому, что пока мы доходим до точки прерывания, 0 таймер продолжает считать.
И это значение 0 таймера (сколько он проскочил от 0 вправо) добавляем, уменьшая его время счета именно настолько, насколько нужно.
TCNT0=COUNTER_REAL+cKORR;
мы забираем при срабатывании
cKORR=TCNT0;
Неточным будет только первое измерение, где мы не знаем еще значение
cKORR
|
Ваш код четко работает!!! Вы конечно профессионал =) Спасибо Вам огромное! Буду его подробно изучать.
Я даже не мог представить что образцовый сигнал для определения частоты можно сделать всего 10Гц Респект Вам!
А Вы не разжуете по поводу понятия "маска" либо "наложить маску".
Может это и глупый вопрос, но честно не совсем понимаю...
Вот флаги знаю где полезны и как их применять знаю
|
|
|
|
05.05.2011, 23:31
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.02.2008
Адрес: Днепр. Украина
Сообщений: 3,294
Сказал спасибо: 442
Сказали Спасибо 1,048 раз(а) в 706 сообщении(ях)
|
Re: Алгоритм частотомера
Маска - элемент для работы с отдельными битами в числе (байте/слове/двойном слове). Применяется для того, чтобы либо узнать состояние соответствующего бита, либо изменить значение какого-то бита в числе.
Одно из основных достоинств - возможность выполнять операции проверки/ сброса/ установки сразу к нескольким битам числа.
Чаще всего маски применяются для работы с битовыми полями регистров периферийных устройств.
Маска - это число используемое для выбора бит при выполнении операций сброса/установки. Чаще всего для записи масок используют двоичную или шестнадцаетеричную форму записи.
Обычно для того, чтобы установить какой-либо бит используют операцию логического ИЛИ с заданным числом. Например для установки битов 1 и 2 (напомню, что счет битов идет от 7 до 0) можно выполнить операцию вида:
Код:
|
PortX |= 6;
PortX |= 0b00000110; |
Для сброса бит применяют операцию логического И с маской у которой сбрасываемые разряды равны 0.
Код:
|
PortX &= 0xF9;
PortX &= 0b11111001; |
Признаком хорошего тона и надежного программирования считается определение масок через #define для того, чтобы при изменении например конфигурации портов ввода-вывода не искать операции с масками по всему тексту для выполнения корректировки.
__________________
misterdi<@>i.ua
Последний раз редактировалось MisterDi; 05.05.2011 в 23:37.
|
|
|
|
07.05.2011, 22:27
|
|
Вид на жительство
Регистрация: 05.04.2008
Адрес: Украина, Ахтырка
Сообщений: 302
Сказал спасибо: 148
Сказали Спасибо 31 раз(а) в 30 сообщении(ях)
|
Re: Алгоритм частотомера
Сообщение от MisterDi
|
Маска - элемент для работы с отдельными битами в числе (байте/слове/двойном слове). Применяется для того, чтобы либо узнать состояние соответствующего бита, либо изменить значение какого-то бита в числе.
Одно из основных достоинств - возможность выполнять операции проверки/ сброса/ установки сразу к нескольким битам числа.
Чаще всего маски применяются для работы с битовыми полями регистров периферийных устройств.
Маска - это число используемое для выбора бит при выполнении операций сброса/установки. Чаще всего для записи масок используют двоичную или шестнадцаетеричную форму записи.
Обычно для того, чтобы установить какой-либо бит используют операцию логического ИЛИ с заданным числом. Например для установки битов 1 и 2 (напомню, что счет битов идет от 7 до 0) можно выполнить операцию вида:
Код:
PortX |= 6;
PortX |= 0b00000110;
Для сброса бит применяют операцию логического И с маской у которой сбрасываемые разряды равны 0.
Код:
PortX &= 0xF9;
PortX &= 0b11111001;
Признаком хорошего тона и надежного программирования считается определение масок через #define для того, чтобы при изменении например конфигурации портов ввода-вывода не искать операции с масками по всему тексту для выполнения корректировки.
|
Добрый вечер! Спасибо Вам огромное! Разьяснили очень подробно
В тайне мечтал получить как раз такое пояснение
Сообщение от artyomugr
|
if( bFlagReady)
|
Еще вопрос по этому куску кода..
Часто встречаю в тексте программы условия без ==0 или ==1
Как их понимать?
И какие есть еще особенности? Видел еще кусок кода с знаком вопроса... это мне вообще не понятно...
Обьясните мне пожалуйста, буду очень благодарен.
С ув. Артем
|
|
|
|
08.05.2011, 01:10
|
|
Временная регистрация
Регистрация: 20.12.2008
Сообщений: 58
Сказал спасибо: 12
Сказали Спасибо 7 раз(а) в 6 сообщении(ях)
|
Re: Алгоритм частотомера
if(bFlagReady) такое выражение читается так: если "bFlagReady" ИСТИНА
Есть еще такое выражение
if(!bFlagReady) читается так: если "bFlagReady" ЛОЖЬ
В языке СИ любое значение не равное нулю является ИСТНИННЫМ Всё, что равно нулю является ЛОЖЬЮ
|
|
|
|
08.05.2011, 10:16
|
|
Вид на жительство
Регистрация: 05.04.2008
Адрес: Украина, Ахтырка
Сообщений: 302
Сказал спасибо: 148
Сказали Спасибо 31 раз(а) в 30 сообщении(ях)
|
Re: Алгоритм частотомера
Сообщение от AlekseyN
|
if(bFlagReady) такое выражение читается так: если "bFlagReady" ИСТИНА
Есть еще такое выражение
if(!bFlagReady) читается так: если "bFlagReady" ЛОЖЬ
В языке СИ любое значение не равное нулю является ИСТНИННЫМ Всё, что равно нулю является ЛОЖЬЮ
|
Спасибо! Теперь все отчетливо понятно
|
|
|
|
08.05.2011, 14:17
|
|
Вид на жительство
Регистрация: 05.04.2008
Адрес: Украина, Ахтырка
Сообщений: 302
Сказал спасибо: 148
Сказали Спасибо 31 раз(а) в 30 сообщении(ях)
|
Re: Алгоритм частотомера
А можно еще глупый вопрос?
Есть у кого формула расчета "частоты" например задержку delay_ms(); перевести в Гц..
И как еще можно просто рассчитать таймер например: есть у нас кварц внешний 8мГц
и надо нам получить прямоугольный сигнал 1кГц. Все время путаюсь в этом....
И поясните как написать код обычного генератора прямоугольных импульсов с применением прерываний...
С ув. Артем
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 20:57.
|
|