Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Генератор, меандры, точность, опрос...и т.д.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
MakFatum
Здравствуйте!...

приведу кусочек и спрошу потом

Все инициализировал...
дальше сам кучочек программы:

Код
if (!PIND.1) {              //PD0  420Hz
  do {    
       OCR2=0x94;  
         }
  while ((PIND>>1)&0);

                     };


Ну так всё и повторяется дальше для различных частот.
Вопрос 1. Всю программу с вышеприведенным куском эмулировал в протеусе (принтскрин ниже)
Дословно код переводится ведь так???: если на PIND.1 НЛУ, то заносить в регистр сравнения OCR2 число соответствующее частоте до тех пор пока выполняется условие (есть НЛУ на PIND.1 ).
В протеусе почему-то еще не успев нажать кнопку уже выдается частота 420 (хотя следуя программе она должна появиться только при нажатии И удержании кнопки (т.е. НЛУ) на пине), а при отпускании пропасть (этого тоже кстати не происходит). Т.е. ситуация такая: вместо кнопок должны быть переключатели, и пока есть НЛУ - есть соответствующая частота, а когда нет НЛУ - ничего нет.
А у меня просто при кратковременном нажатии она появляется и так не пропадает при отпускании. Где собака...?
Вопрос 2. Дискретность установки частоты у 8-разрядного таймера оставляет желать лучшего даже при 1/8 кдел., т.е. получается допустим 420+-2Гц (иногда и больше) (многовато, нужно хотя бы +- 1Гц). Формула нахождения частоты : fOCn=fclk_/2*N(1+OCRn) почему-то не работает, нахожу не по ней...Как улучшить показатели? 16-разрядный для модулирующих у меня...
Вопрос 3. Самое интересное и самое непонятное пока для меня: Как мне вывести программно в какой-нибудь пин порта модуляцию 2-х частот (то бишь перемножить) логическое "И"???
В лоб не получается... Теории об этом не нашел...

vet
1) Будучи единожды настроен, таймер будет работать (и выдавать импульсы), пока его не выключат. В приведённом коде выключения таймера нет.
Далее,
условие while ((PIND>>1)&0); никогда не сработает, поскольку побитовое И с нолём всегда даст ноль.
PIND.1 так и проверяйте:
while (PIND.1); //в CodeVision
while (PIND&0x02); //другие компиляторы С

2) Возьмите чип с двумя 16-бит таймерами.

3) Насчёт перемножения частот - один таймер выдаёт первую частоту на вывод контроллера, на другой частоте работает второй таймер, в прерывании таймера №2 попеременно разрешается и запрещается сигнал от таймера №1 на ноге контроллера.
MakFatum
Насчет прерываний - спасибо, попробую...
Вообщем что-то опять не то...
ТО, что я написал, не собирается выводить одновременно 2 частоты, потому как сидит в цикле while() если найдет НЛУ на каком-нибудь пине...
не пойму, как исправить конструкцию чтобы в OCR один раз заносилось, и больше рабочая точка туда не возварщалась, пока не измениться состояние ...Вообщем в моем случае постоянно опрашивать совершенно не нужно, так как на деле все частоты один раз устанавливаются и оперативного их изменения не нужно....
как мне покрасивей и рациональней вывести всё это одновременно...?
оператор Switch не подходит...?

кусочек...

Код
if (!PINB.4) {              //PD0  12Hz
        TCCR1A=0b01010000;
        TCCR1B=0b00001101;  
while (!PINB.4) {
      
      OCR1AL=0x28;  
                     };}
else  {
        TCCR1A=0x00;
        TCCR1B=0x00;
      };                            
        
        if (!PIND.1) {              //PD0  420Hz
        TCCR2=0b00011010;  
while (!PIND.1) {
      
       OCR2=0x94;  
                     };}
else  {
        TCCR2=0x00;
      };
WHALE
обьедини свои кнопки через диоды и заведи на вход внешнего прерывания.А в обработчике прерыва-
ния можно через if,если у тебя 2 кнопки.Если кнопок предпалагается больше,то лучше применить шифратор-там и выход на прерывания есть,а анализ кнопок через switch.
MakFatum
Насчет умножения частот-модуляции попробовал в протеусе такое:
Код
while(1){

if((PINB.1)&&(PINB.3)) {
PORTC.5 = 1;
           }
     else
           PORTC.5 = 0;
};


вроде сработало....По крайней мере пачки импульсов идут. ТОлько мой старенький комп повисает на пару минут...

Вот интересно будет на железе проверить..

Нет, прерываниями не пойдет,
там у меня 5 несущих и две модулирующих,..можно ведь все в МК сделать...

Не получается у меня пока стройный алгоритм опроса..
маленький Цикл while() убрал...Частоты Fнем и Fмод. выводятся теперь одновременно.

Код
if (!PINB.4) {              //PD0  12Hz
        TCCR1A=0b01000000;
        TCCR1B=0b00001101;  

      
      OCR1AL=0x28;  
                     };          
        
        if (!PIND.1) {              //PD0  420Hz
        TCCR2=0b00011010;  

      
       OCR2=0x94;  
                     };

Так теперь перед включением у-ва придется заранее устанавливать ключи (т.е. неоперативно и неудобно), а чтобы изменить частоту придется или reset жать или включать-выключать, что также не совсем удобно...

Как мне устроить периодический опрос?...в принципе у меня раз в сек. или даже больше опросил и хватит, чаще не обязательно...
нужно чтобы процессорное время сильно не отнималось (похоже ему тяжело дается умножение)
По еще одному 8-разрядному таймеру в прерывании опрос что-ли?
WHALE
не понял,чем тебя прерывание по нажатию не устроивает?Всего один пин выделяется под это,и время
процца здорово экономится.Можно и по опросу раз в секунду,если есть лишний таймер-в прерывании от таймера вставляешь код опроса кнопок.
MakFatum
Спасибо за помощь!...
Опрос портов делаю по переполнению таймера T0 в прерывании...примерно раз в 0,2 сек.
Вроде все вышло...но столкнулся с проблемой...
1.Следуя нижеприведенному коду при замкнутом ключе (НЛУ на пине) программа заносит в таймер значение константы, а при размыкании частота так и остается,
если я добавляю
Код
else  {
        TCCR2=0x00;
      };

после if для 8-разрядного таймера,
Код
else  {
        TCCR1A=0x00;
        TCCR1B=0x00;
      };

или после if для 16-р таймера (т.е. останавливаю таймеры), то получается какая-то околесица..
частоты не те и самое интересное, когда ставлю первое else после первого if (!PINB.5) на него реагирует и if (!PINB.4), т.е. при размыкании ключа на PINB.4 тоже пропадает сигнал, этого ведь не должно быть...
То же самое когда ставлю это else после "420", на него все остальные реагируют...

Код
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xff;
if (!PINB.5) {                     //PD0  8Hz
        TCCR1A=0b01000000;
        TCCR1B=0b00001101;  
        OCR1AH=0x00;
        OCR1AL=0x3C;  
                     }
                  
if (!PINB.4) {                      //PD0  12Hz
        TCCR1A=0b01000000;
        TCCR1B=0b00001101;  
        OCR1AH=0x00;
        OCR1AL=0x28;  
                     }                  
                                                                  
        if (!PIND.1) {              //PD0  420Hz
        TCCR2=0b00011010;  
        OCR2=0x94;  
                     }
                    
        if (!PIND.2) {              //PD0  480Hz
        TCCR2=0b00011010;    
        OCR2=0x81;  
                     }
                
        if (!PIND.3) {              //PD0  580Hz
        TCCR2=0b00011010;
        OCR2=0x6B;  
                      }
                                                  
        if (!PIND.0) {              //PD0  720Hz
        TCCR2=0b00011010;
        OCR2=0x56;  
                      }
              
        if (!PIND.6) {              //PD0  780Hz
        TCCR2=0b00011010;
        OCR2=0x4F;  
                      }
                                          


}



2. При размыкании того же ключа мне нужно вывести в PB1/OC1A - НЛУ, я пишу
Код
else  {
        PORTB.1=0
        TCCR1A=0x00;
        TCCR1B=0x00;
      };


НО не работает!!! почему?...Сбрасывать в 0 битом FOCn в TCCRn?

3. Не пойму до конца функции FOCn в TCCRn? Написано: ПРинудительное изменение состояния вывода OCn (режимы Normal, CTC). Если я записываю туда 0, то просто не будет генерироваться прерывание и происходить сброс таймера, а программирование COMn1:COMn0 будет доступно? (управление выводом ОСn???)

Спасибо...
MakFatum
Может где в синтаксисе ошибка?...
пробовал после размыкания в else сбрасывать пин в 0 записью 1 в FOCn TCCRn и COMn1,
сбрасываться-то сбрасывается, только опять почему-то начинают реагировать на эту запись все остальные ключи, котороые расположены в подпрограмме ниже!!
...У меня ошибка где-то в самом написаний условий if и else!
Помогите советом, не знаю даже где копать....

Спасибо...
MakFatum
собрал значит, ключи зацепил, частоты генерит, но не умножает (в протеусе все нормально)...
и по-моему греется...ну 45-50 Град., это нормально или не очень?...
...попробую на нормальном осциллографе посмотреть, а то дома убитый C1-94..
cо своим косяком в СИ так и не разобрался...
если после 1-го условия ставлю else (останавливаю таймер, сбрасываю вывод в "0"), ниже разположенные условия тоже почему-то реагируют....
defunct
Цитата(MakFatum @ Apr 1 2006, 18:51) *
собрал значит, ключи зацепил, частоты генерит, но не умножает (в протеусе все нормально)...
и по-моему греется...ну 45-50 Град., это нормально или не очень?...

МК так греется? Это не нормально. Скорее всего уже у него что-то спалено. Проверьте потребление по току без индикаторов и прочего, "голый" МК. Если он еще в порядке, то потребление будет не больше указанного в даташите и греться он не будет.

У меня была ситуация когда выгорели защитные диоды в МК по вине того, что на щупе осциллографа присутствовала фаза, так вот после этого МК начал греться хотя работоспособность полностью сохранилась (кроме одного к пина). Хорошо этим пином был PA1 и, отключив весь порт (отсоедив AVcc), можно было продолжать использовать МК в нормальном режиме. После этого с опаской отношусь к старым советским осциллографам.
MakFatum
Нашел ошибку...
по невнимательности порта А (на котором ключи весели) настроил на выход,
PORTA=0xFF;
DDRA=0xFF;

а требовался вход

Исправил, проверил, теперь не греется...
В связи с этим вопрос: что могло в результате моих неумелых действий случиться с портом А?
опрос по крайней мере работает...сейчас проверил...частоты переключаются...значит с портом все в порядке?

Так и не понял, почему на железе не работает умножение...

while(1){

if((PIND.7)&&(PIND.5)) {
PORTC.5 = 1;
}
else
PORTC.5 = 0;

на пине PINC.5 - 5 вольт и осциллограммы не видно...
...может быть из-за нерабочего пина?...
попробовать на другой пин выдать?

и еще, немножко оффтоп....
Подскажите какой-нибудь цифровой осциллограф, не сильно крутой и навороченный, для дома...(марку и фирму желательно)...
И еще...покольку в нашем городе великая проблема достать хоть какой-нибудь МК, не могли бы вы посоветовать интернет-магазин радиокомпонентов с доставкой по СНГ?...
буду очень благодарен...
WHALE
У тебя-же эти выходы натроены на выход,соответственно чтение пинов некорректно.Самый простой вы-
ход-если есть незадействованные порты,настрой их на чтение и заведи свои выходы в парралеь и на
них.
MakFatum
а протеусе почему все тогда путем?...
или лучше ему не доверять полностью?...
WHALE
А 100% полагаться ни на какой симулятор нельзя sad.gif Проверь в AVR-Studio,уверен,там не прокатит.
Или сразу в железе.
MakFatum
Цитата(WHALE @ Apr 2 2006, 15:58) *
У тебя-же эти выходы натроены на выход,соответственно чтение пинов некорректно.Самый простой вы-
ход-если есть незадействованные порты,настрой их на чтение и заведи свои выходы в парралеь и на
них.

Подождите,...а что если в DDRx "1",т.е. на выход, и в PORTx динамически выводить то "0", то один "1", PINx на эти изменения не будет реагировать?,т.е. PINx читаем только тогда, когда DDRx установлен на чтение?...
вот это значит упущение мое..., про это не читал нигде...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.