| Автор |
Съобщение |
|
the_bull
Ранг: Новодошъл
Регистриран на: Съб Авг 18, 2007 11:39 am Мнения: 137 Местоположение: Русе
|
 Проблем на честотомер с Атмега32
Здравейте, от известно време се мъча с направата на честотомер елемнтарен, който да мери честота в диапазона до 10 кHz. Използвам Атмега32 на 4 MHz. Измерването го правя като броя входните импулси с таймер/брояч 1 който пък нулирам през определен период с таймер 2. Теоритично би трябвало да измерва честота до 65 kHz като калибрирам системата и като знам, че брояа ми е 16 битов. Работя с микро С за АВР на микроелектроника. Но имам много гаден проблем и не мога да хвана къде греша. Това ми е сорса държа да подчертая че съм доста начинаещ и може би това не е най добрия метод за направа на честотомер. Ето това ми е сорса:  |  |  |  | Код: /*// LCD module connections sbit LCD_RS at PORTA5_bit; sbit LCD_EN at PORTA4_bit; sbit LCD_D4 at PORTA3_bit; sbit LCD_D5 at PORTA2_bit; sbit LCD_D6 at PORTA1_bit; sbit LCD_D7 at PORTA0_bit;
sbit LCD_RS_Direction at DDA5_bit; sbit LCD_EN_Direction at DDA4_bit; sbit LCD_D4_Direction at DDA3_bit; sbit LCD_D5_Direction at DDA2_bit; sbit LCD_D6_Direction at DDA1_bit; sbit LCD_D7_Direction at DDA0_bit; // End LCD module connections*/
// LCD module connections sbit LCD_RS at PORTD2_bit; sbit LCD_EN at PORTD3_bit; sbit LCD_D4 at PORTD4_bit; sbit LCD_D5 at PORTD5_bit; sbit LCD_D6 at PORTD6_bit; sbit LCD_D7 at PORTD7_bit;
sbit LCD_RS_Direction at DDD2_bit; sbit LCD_EN_Direction at DDD3_bit; sbit LCD_D4_Direction at DDD4_bit; sbit LCD_D5_Direction at DDD5_bit; sbit LCD_D6_Direction at DDD6_bit; sbit LCD_D7_Direction at DDD7_bit; // End LCD module connections
unsigned int count,oldCount,count1,Rh; char txt[8],txt2[8]; const char _THRESHOLD = 16; char counter,flag;
void Timer2Overflow_ISR() org IVT_ADDR_TIMER2_OVF {
if (counter >= _THRESHOLD) { count1 = ((TCNT1H<<8)+TCNT1L); //count=count1;//-(count1*0.044); oldCount = count1; //Rh=565.3-(oldCount*0.07675); count1 = 0; counter = 0; TCNT1H=0; TCNT1L=0;
} else counter++; // increment counter } void main() { SREG_I_bit = 1; // Interrupt enable TOIE2_bit = 1; // Timer2 overflow interrupt enable TCCR2 = 0x07; // Start timer with 1024 prescaler TCCR1A = 0x00; //Setup TC1 to count PB1 TCCR1B = 0x07; Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off Lcd_Out(1, 1, "Frecuncy:"); Lcd_Out(2,15,"Hz"); while (1) { count = ((TCNT1H<<8)+TCNT1L); //Rh=565.3-(oldCount*0.07675); WordToStr(count, txt2); Lcd_Out(1, 10, txt2); WordToStr(oldCount, txt); Lcd_Out(2,1,txt);
} }
|  |  |  |  |
Проблема ми е следния. Това нещо работи и измерва, но примерно аз му подавам 6600 Hz то през голяма част от времето показва тази стойност, но на моменти показва примерно 6900 Hz. Прави го напълно произволно и най лошото е че не съм сигурен софтуерен ли е проблема или в хардуера ми. Склонен съм да мисля че е софтуерен защото на няколко пъти го бях укротил да си показва честотата колкото е. И само като добавя 1 сметка която трябва да имам започваха сривовете. Някой ако може да помогне със съвети или покаже къде греша в подхода. Да подчертая също че проблема не е в генератора от който подавам сигнал, прави го при 2 различни генератора. Също така генераторите ги контролирам с честотомер и няма подобен проблем. Всичко идва от моето устройство.
Сорса е сглобяван с фрагменти от example на микро С така, че голяма част от него е ползван като готов такъв. Ако може някой да ми обясни и как точно функционират прекъсванията. Аз знам доста за това какво представляват и как да ги използвам но не разбирам защо микро С то не ми позволява да ги влагам във функции и може би греша нещо спрямо тях.
|
| Чет Мар 24, 2011 6:39 pm |
|
 |
|
marcuka68
Ранг: Ориентиран
Регистриран на: Пет Авг 07, 2009 4:58 pm Мнения: 273
|
Пробвай да видиш какъв резултат дава (а <<  , когато а е от тип char. Честота не съм мерил, но изразът, с който взимаш стойността на двата регистъра на таймера, ми изглежда грешен. А не можеш ли да я вземеш наведнъж: а = TCNT1; ?
|
| Вто Апр 05, 2011 10:35 pm |
|
 |
|
the_bull
Ранг: Новодошъл
Регистриран на: Съб Авг 18, 2007 11:39 am Мнения: 137 Местоположение: Русе
|
Здравей и благодаря за съветите. Проблема мисля се отстрани като направих някой корекции в сорса. Също така преди това бях се заблудил нещо и вместо да работи с външен кварц работеше на вътрешен осцилатор. Сега се е укротило след като всичко му е сетнато както трябва. В случая използвам микроС и в него няма дефиниран този регистър TCNT1 като 16 битов а е разделен на 2 регистъра по 8 бита. Преобразуването си е добре и е коректно. Проблем до някъде е, че права много неща в прекъсването, по принцип не е хубаво ама работи перфектно така. Като се опитам да изнеса някой сметки извън прекъсване стават гафове затова засега смятам в прекъсването. Днес дори мигрирах на 16MHz, че преди това работих на 4. Сега остава да навържа още няколко модула към системата без да се скапе нещо.
|
| Вто Апр 05, 2011 10:51 pm |
|
 |
|
marcuka68
Ранг: Ориентиран
Регистриран на: Пет Авг 07, 2009 4:58 pm Мнения: 273
|
Странно, аз съм имал проблеми с такъв израз, но щом върви, добре е 
|
| Сря Апр 06, 2011 8:35 am |
|
 |
|
radiko
Ранг: Минаващ
Регистриран на: Пет Мар 23, 2012 1:38 pm Мнения: 13
|
 Re: Проблем на честотомер с Атмега32
Колега радвам се че си пуснал тази тема. Това е нещо което ме интересува живо. Мислех и аз да се захващам с експерименти но за щастие се сетих първо да потърся в нета. накратко трябват ми повечко такива честотомери за автоматизиране на едни измервания. Бих се радвал ако ти или някой друг който чете тази тема и се се интересува. Се свърже с ме. за да поработим съвместно по въпроса може би ще се наложи да отворя и нова тема но сега очаквам отзиви тук
|
| Пет Мар 23, 2012 1:52 pm |
|
 |
|
bkulev
Ранг: Популярен
Регистриран на: Сря Яну 25, 2006 12:47 pm Мнения: 305 Местоположение: Varna
|
 Re: Проблем на честотомер с Атмега32
Помисли в/у този израз: "count = ((TCNT1H<<8)+TCNT1L);" Както и да го напишеш на 'C', ако процесора ти е 8 битов реално регистрите ще се прочетат в различно време. И какво ще се случи с крайния резултат, ако точно в момента настъпи пренос от 'L' към 'H'? Приципът е: Операцията по четенето на променлива, която се изменя в прекъсване или от някакъв външен процес, трябва да бъде АТОМИЧНА.
|
| Нед Апр 01, 2012 10:15 am |
|
 |
|
ps66
Ранг: Форумен бог
Регистриран на: Пет Яну 19, 2007 9:16 am Мнения: 1063 Местоположение: путинофили: "иди н***й"
|
 Re: Проблем на честотомер с Атмега32
на човешки помпилатор, най-вероятно винаги ще е count = TCNT1L; (ако някой се чуди ... що? - нека се сети че става въпрос за 8-битова аритметика)
|
| Нед Апр 01, 2012 11:20 am |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
 Re: Проблем на честотомер с Атмега32
А, защо, не непременно. Стандарнтият начин е: -прочита се старшия -прочита се младшия -прочита се старшия -ако двете прочетени стойности на старшия се различават, повтаря се цялата последователност.
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Нед Апр 01, 2012 1:24 pm |
|
 |
|
perlsite
Ранг: Ориентиран
Регистриран на: Пон Апр 17, 2006 1:44 pm Мнения: 291
|
 Re: Проблем на честотомер с Атмега32
Не съм убеден, че това е надежден подход, тъй като между двете четения на старшият байт могат да настъпят промени, при което старшият байт при второто четене отново да е с началната си стойност, но младшия байт вече да е променен...?!
|
| Нед Апр 01, 2012 10:57 pm |
|
 |
|
itso.t
Ранг: Форумен бог
Регистриран на: Чет Фев 03, 2005 2:21 am Мнения: 12765 Местоположение: София
|
 Re: Проблем на честотомер с Атмега32
...старшият байт винаги е с различна стойност = while(1) ? 
|
| Нед Апр 01, 2012 11:03 pm |
|
 |
|
perlsite
Ранг: Ориентиран
Регистриран на: Пон Апр 17, 2006 1:44 pm Мнения: 291
|
 Re: Проблем на честотомер с Атмега32
Прави ми впечатление, че старшият байт се увеличава точно с едно...
|
| Пон Апр 02, 2012 1:53 am |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
 Re: Проблем на честотомер с Атмега32
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Пон Апр 02, 2012 2:25 am |
|
 |
|
the_bull
Ранг: Новодошъл
Регистриран на: Съб Авг 18, 2007 11:39 am Мнения: 137 Местоположение: Русе
|
 Re: Проблем на честотомер с Атмега32
Наистина не е най-добрия вариант за направа на честотомер, но на мен ми свърши работа. Проблема с отскоците не съм много сигурен, но мисля че беше от кофти кварц, и не добре сетнати fuse битове. Когато имаше проблемите работеше на вътрешен осцилатор а мислех, че работи на кварц, и някъде оттам ми се струва че беше този бъг. Това преобразуване, което коментирате при други компилатори не би се наложило.В datasheeta има примерен сорс за 16-битовия таймер и там си има посочен 16-битов регистър от който може да се чете директно стойността. AVR Studioto си го познава, но на микро С то не беше добавян този регистър и затова си реших на бързо проблема по този начин.
|
| Пон Апр 02, 2012 10:36 pm |
|
 |
|
bkulev
Ранг: Популярен
Регистриран на: Сря Яну 25, 2006 12:47 pm Мнения: 305 Местоположение: Varna
|
 Re: Проблем на честотомер с Атмега32
Ако няма друг надежден и бърз начин, то най - сигурният е: Disable Interrupt; count = ((TCNT1H<<8)+TCNT1L); Enable Interrupt; Защото, колега сега може и да не се виждат някакви "отскоци", "несъответствия" или каквото там му викаш, но бъди сигурен ЩЕ ИМА. Друг е въпросът дали ти ще ги забележиш.  Така че както е казал нашия мъдър народ: "Вържи попа, та да е мирно селото"
|
| Вто Апр 03, 2012 4:28 pm |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
 Re: Проблем на честотомер с Атмега32
Е ако са две 8 бита четения (т.е. два отделни цикъла) маскирането на прекъсванията няма да върже попа  .
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Вто Апр 03, 2012 5:07 pm |
|
|