Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Antifritz
Прорезались зубы
Сообщения: 222
Зарегистрирован: Чт июл 08, 2010 01:03:40
Откуда: Украина, Киев

Re: Вопросы по С/С++ (СИ)

Сообщение Antifritz »

Поставьте в Протеусе частоту контролера 10000Hz и увидите то, что принципе, программа работает правильно, а вот задержку стоит сделать побольше и последний светодиод не загорается потому, что сразу после того как он был включен идет проверка и PORTB=0b10000000 заменяется на PORTB=0b00000001, проверку нужно делать еще до сдвига:
if(PORTB==0b10000000)
PORTB=0b00000001;
else
PORTB<<=1;
и так далее.
Аватара пользователя
Hispanus
Грызет канифоль
Сообщения: 262
Зарегистрирован: Сб мар 26, 2011 14:17:14
Откуда: Оренбург

Re: Вопросы по С/С++ (СИ)

Сообщение Hispanus »

Antifritz Спасибо :)
У радио нет будущего. Летательные аппараты тяжелее воздуха невозможны. Скоро выяснится, что рентгеновские лучи - мистификация.

[i]Лорд Кельвин, физик, 1899 г.[/i]
Лютик
Нашел транзистор. Понюхал.
Сообщения: 161
Зарегистрирован: Вт мар 25, 2008 22:10:23
Откуда: Минск

Re: Вопросы по С/С++ (СИ)

Сообщение Лютик »

наткнулся на неплохой мануал http://www.romanblack.com/one_sec.htm в котором используется Брезенгемский алгоритм, позволяющий получить период в 1 секунду(и др.) с любой частотой осцилятора.

Код: Выделить всё

// PERIOD sets the pin toggle freq; toggle PERIOD = (xtal / 4 / freq / 2) 
#define PERIOD 10000   // (xtal 4Mhz) TMR0 1MHz, 10000 = 100Hz toggle (50Hz output)

#define PER_COUNTS ((PERIOD / 100) - 1)  // don't edit this!
#define PER_REMAINDER (PERIOD - (PER_COUNTS * 100))  // don't edit this!

unsigned int pcount;    // used in interrupt to count PER_COUNTS
//----------


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void interrupt()
{
  //----------
  // this is the TMR0 overflow interrupt.
  // Note! TMR0 has a 3 tick write latency, writes must be -3
  //----------
  // check if time to toggle the output pin
  if(!pcount)
  {
    asm {
      movlw 0x01      ; // mask for pin 0
      xorwf GPIO,f    ; // toggle PIC pin GPIO.0
    }
    pcount = (PER_COUNTS+1);    // how many delays to make total
    TMR0 -= (PER_REMAINDER-3);  // first delay will be ==remainder
  }
  // else make a normal delay
  else
  {
    TMR0 -= (100-3);       // make another 100 tick delay
  }
  pcount--;
  //----------
  // clear the TMR0 overflow flag and exit
  INTCON.T0IF = 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//=======================
//   MAIN
//=======================
void main ()
{
  //----------
  // PIC 12F675  setup ports
  ANSEL = 0;            // ADC off
  CMCON = 0x07;         // comparators off
  GPIO =   0b00000000;  // clear GPIO
  TRISIO = 0b00000000;  // All outputs
  WPU =    0b00000000;  // pin pullups; 1 = pullup on (for button)

  //----------
  // timer setup etc
  OPTION_REG = 0b00001000;    // TMR0 on, 1:1 prescale
  pcount = 0;
  INTCON = 0b10100000;  // GIE on, T0IE on (turn interrupt on)

  //----------
  // main run loop here
  while(1)
  {
    continue;   // loop and do nothing, just let the interrupt happen
  }
}
//----------



для генерации 1ой секунды с моим 20МГц PIC16F628A кварцем(тело основного цикла, инициализацию и прочее я опустил(TMR0(прескалер 1:1) и TMR1(прескалер 1:1) включены, как и прерывания от них)):

Код: Выделить всё

#define PERIOD 5000000
#define PER_COUNTS ((PERIOD / 100) - 1)  // don't edit this!
#define PER_REMAINDER (PERIOD - (PER_COUNTS * 100))  // don't edit this! 

static void interrupt Int(void)
{
if(T0IF)
{
  if(!pcount)
  {
   sec++;
    pcount = (PER_COUNTS+1);
    TMR0 -= (PER_REMAINDER-3);
  }
  else
  {
    TMR0 -= (100-3);
  }
   pcount--;
   T0IF = 0;
}
if(TMR1IF)
{
   TMR1H = 0xFF;     // preset for timer1 MSB register
   TMR1L = 0xE7;     // preset for timer1 LSB register
   LCDIF=1;
   TMR1IF=0;
}
}


Но вот беда- часы уходят за 6 часов на секунд 20(вперед), хотя должны идти точно =). Вопрос- чтото я делаю не так? А также, надо ли учитывать такты(машиные циклы) на выполнение сравнения "if(T0IF)", "if(!pcount)", инкрементирования переменной sec, в общем операции ДО сброса флага прерывания T0IF или я чтото неправильно понимаю :cry:
Аватара пользователя
Antifritz
Прорезались зубы
Сообщения: 222
Зарегистрирован: Чт июл 08, 2010 01:03:40
Откуда: Украина, Киев

Re: Вопросы по С/С++ (СИ)

Сообщение Antifritz »

Как по мне здесь бОльшую погрешность будет давать неидеальность кварца. По идее, при использовании других кварцев, даже на такую же частоту погрешность тоже должна изменится.
Лютик
Нашел транзистор. Понюхал.
Сообщения: 161
Зарегистрирован: Вт мар 25, 2008 22:10:23
Откуда: Минск

Re: Вопросы по С/С++ (СИ)

Сообщение Лютик »

судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца добиться желаемого значения
Аватара пользователя
БАТАРЕЙКУС
Потрогал лапой паяльник
Сообщения: 346
Зарегистрирован: Сб фев 07, 2009 19:21:25

Re: Вопросы по С/С++ (СИ)

Сообщение БАТАРЕЙКУС »

доброе время суток мужыки.
пытаюсь изучать Си для pic. подскажите пожайлусто как создать поект для компилятора MCC18.
по описанию из книги ,, применение микроконтроллеров pic 18,, нечё неполучается, мож вы подскажите как быть.
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Лютик писал(а):Но вот беда- часы уходят за 6 часов на секунд 20(вперед), хотя должны идти точно =). Вопрос- чтото я делаю не так? А также, надо ли учитывать такты(машиные циклы) на выполнение сравнения "if(T0IF)", "if(!pcount)", инкрементирования переменной sec, в общем операции ДО сброса флага прерывания T0IF или я чтото неправильно понимаю :cry:

вот блин расстроился:)
6часов*60мин*60сек=21600
20сек/21600 сек= 0.0009259*100%=0.09259% погрешность.
Возьми да добавь погрешность к своему значению 5000000*1.0009259=5004629.6 ну последнюю шестерку можно либо округлить либо прибавлять 1 каждые 6 из 10 циклов.
А еще есть вариант с помощью конденсаторов кварца отрепетировать точную частоту кварца.
В поисках истины человек развивается.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Лютик писал(а):судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца добиться желаемого значения

интересное предложение это что означает программно менять частоту кварца??
Вы, наверно, хотели сказать что подобрать значение,которое подходит для этой частоты кварца.
Последний раз редактировалось vitalik_1984 Ср июл 20, 2011 20:48:22, всего редактировалось 1 раз.
В поисках истины человек развивается.
Лютик
Нашел транзистор. Понюхал.
Сообщения: 161
Зарегистрирован: Вт мар 25, 2008 22:10:23
Откуда: Минск

Re: Вопросы по С/С++ (СИ)

Сообщение Лютик »

vitalik_1984 писал(а):
Лютик писал(а):судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца добиться желаемого значения

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

дело в том, что я конденсаторы не использую(в макетке), кварц и так возбуждается, поэтому считаю что можно подогнать частоту программно, тем более так проще имхо
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Лютик писал(а):
vitalik_1984 писал(а):
Лютик писал(а):судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца ???добиться желаемого значения

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

дело в том, что я конденсаторы не использую(в макетке), кварц и так возбуждается, поэтому считаю что можно подогнать частоту программно, тем более так проще имхо

Не частоту кварца тогда, а частоту секундных импульсов программно менять:)
В поисках истины человек развивается.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение urry »

как бы вопрос был по алгоритму Брезенхема, по мне - так очень непривычная реализация.
А попроще нельзя ? Так, например

Код: Выделить всё

#include <pic.h>
__CONFIG(HS & WDTDIS & LVPDIS & BORDIS & MCLREN);
#define FREQ 20000000 //  частота кварца
#define FREQ_IN FREQ/4  // частота на таймер =  частота кварца/4
// выбираем число сигнед инт в пределах 1 -32767 для нашей входной
// число должна делиться с 5 000 000 до кратного герцу значению
// останавливаемся на 25000, это будет квант
#define KVANT 25000
#define CMAX FREQ_IN/KVANT // получаем значения для дополнительного счетчика,
// по которому добиваем до секунды - число будет 200
volatile unsigned char cCounterSek; // сам дополнительный счетчик
volatile signed int iCounterKvant; //  счетчик кванта
#define OVERFL 256*8 // значение переполнения 0 таймера при делителе = 8
volatile unsigned char cFlagSek; // флаг срабатывания секунды
void init_port(void);
interrupt void intrTimer(void)
{
   if (T0IF&& T0IE)
   {         
      T0IF=0;
      iCounterKvant-= OVERFL;
      if(iCounterKvant <= 0)
      {
         iCounterKvant+= KVANT;
         cCounterSek++;
         if(cCounterSek == CMAX)
         {
         cFlagSek=1;
         cCounterSek=0;
         }
      }
   }
}
//----------
void main()
{
   init_port();
   for(;;)
   {
      if(cFlagSek)
      {
         cFlagSek=0;
         PORTB^=0xFF;
      }
   }

}
//----------



void init_port()
{
   CMCON=7;//выключаем компараторы
   TRISA=0xfF;
   TRISB=0x0;
   cCounterSek=0;
   cFlagSek=0;
   iCounterKvant= KVANT;
   T0CS=0;
   PSA=0;//делитель на таймер 0
   PS2=0; // делим до 8
   PS1=1;   
   PS0=0; //
   T0IE=1;
   PIR1 = 1;   
   PEIE = 1;
   GIE = 1;
}
//----------   
Лютик
Нашел транзистор. Понюхал.
Сообщения: 161
Зарегистрирован: Вт мар 25, 2008 22:10:23
Откуда: Минск

Re: Вопросы по С/С++ (СИ)

Сообщение Лютик »

urry писал(а):А попроще нельзя ? Так, например


не свосем понял, а если частота 500Гц, допустим, а не 1?
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Леонид Иванович »

Делал Брезенхема так:

Код: Выделить всё

u8 Power; //требуемое значение мощности
u8 Phase;
s8 Delta;

   Phase = MAXPOW;  //инициализация, делать 1 раз
        Power = MyPower; //задаем требуемое значение мощности

//делать по вылавливанию перехода через 0:

   Delta = Power + Delta;
   if (Delta < 0)
         {
           TriacOff();
         }
         else
          {
            TriacOn();
            Delta = Delta - MAXPOW;
          }
        Phase = Phase - 1;
        if (Phase == 0)
         {
           Phase = MAXPOW;
           Delta = - (Phase / 2);
         }
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение urry »

Лютик писал(а):
urry писал(а):А попроще нельзя ? Так, например


не свосем понял, а если частота 500Гц, допустим, а не 1?

Теперь я не понял, в чем разница ?
По алгоритму Брезенхема частота очень редко будет соответствовать именно значению 500 Герц, она будет бегать от 499 до 501, скажем, в зависимости от того, на каком участке сейчас находимся.
Но суммарная - за какое -то время - будет именно 500, и чем больше время измерения, тем ближе к требуемой.
Особое значение играет именно знаковая переменная - в моем примере signed int iCounterKvant;
в примере Леонида Ивановича s8 Delta;
в в зависимости от ее знака, принимается решение, в какую сторону регулировать.
Аватара пользователя
БАТАРЕЙКУС
Потрогал лапой паяльник
Сообщения: 346
Зарегистрирован: Сб фев 07, 2009 19:21:25

Re: Вопросы по С/С++ (СИ)

Сообщение БАТАРЕЙКУС »

вообщем заюзал MCC18 ПОД PIC18F242, просмотрел ассемблерный код замерил время выполнения программ. вообщем работает почти адекватно. умножение 266 м.ц. в товремя как на ассемблере за 200 м.ц. что почти хорошо. итд. но все-таки надыбал пару косяков например 2-е переменные char не может перемножить межсобой с сохранением результата в переменной int.

Код: Выделить всё

char a = 24 ;
char b = 55 ;
int c = 0 ;

c = a*b ; //  и тут косяк.


вообщем не очень страшно но всёж неприятно приходится хотяб одну переменную произведения использовать также как int.

да и математическая библиотека ложовая извлечение квадратного корня выполняется за более 6000 м.ц.
втовремя как на ассемблере корень из 24-х разрядного число высчитывается всего за 600 м.ц

оно вобщем и понятно в мат библиотеке переменные float и всё такое. но если меня устраивает точность до целых то зачем столько ждать.

и ещё непонятно 2-е вещи.
1) вопрос почему в пустом проекте где кроме функции main(){} нечего нету а память программ занята ажжж на 116 байт а озу вооще аж на 268 байт. эт куда такое излишество. чем они там занеты?
2) вопрос как мне зарезервировать некоторое количество байт в озу чтобы хранить там ассемблерные переменные и Си компилятор их не поубивал там.
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Лютик
Нашел транзистор. Понюхал.
Сообщения: 161
Зарегистрирован: Вт мар 25, 2008 22:10:23
Откуда: Минск

Re: Вопросы по С/С++ (СИ)

Сообщение Лютик »

urry писал(а):
Лютик писал(а):
urry писал(а):А попроще нельзя ? Так, например


не свосем понял, а если частота 500Гц, допустим, а не 1?

Теперь я не понял, в чем разница ?
По алгоритму Брезенхема частота очень редко будет соответствовать именно значению 500 Герц, она будет бегать от 499 до 501, скажем, в зависимости от того, на каком участке сейчас находимся.
Но суммарная - за какое -то время - будет именно 500, и чем больше время измерения, тем ближе к требуемой.
Особое значение играет именно знаковая переменная - в моем примере signed int iCounterKvant;
в примере Леонида Ивановича s8 Delta;
в в зависимости от ее знака, принимается решение, в какую сторону регулировать.


отличия Брезенхема состоит как раз в том, что оно дает точный результат, как написано на том сайте. выходит там написана не правда?
логически если подумать, то с какой стати показания буду прыгать, если действие(инкрементирование переменной или "пинание" ножки контроллера) происходит толкько в подрпрограмме обработки прерывания с занесением накопившейся ошибки, то есть однократно за весь период, а последующее это же действие произойдет через такой же промежток времени и почему же тогда значения будут прыгать? ведь все промежуточные значения, заносимые в TMR0 заранее преопределены и являются статичными
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение avreal »

Брезенхем даёт не "точный" результат, а хорошее приближение к нему.
Ну вот допустим для простоты, что за заданный временной интервал происходить 9.3 периода некоей частоты. Точно его отмерить просто невозможно.
Брезенхем на каждые 10 периодов выходной частоты даст
9 периодов входной частоты -- 7 раз
10 периодов входной частоты -- 3 раза.
среднее значение при этом будет (7*9+3*10)/10 точно 9.3
Но расстояие между импульсами на выходе будет прыгать
Брезенхем ещё постарается поравномернее размазать 9 и 10 входных периодов, так, чтобы на меньшем числе интервалов средняя ошибка тоже была минимально возможной.
Вот в данном случае если сделать
10 10 10 9 9 9 9 9 9 9
то за 10 периодов среднее будет 9.3, но за первые 3 периода среднее будет 10, отклонение +0.7.
Брезенхем даст что-то в духе
9 10 9 9 10 9 9 9 10 9
Только за одни смежные три периода (№6,7,8) будет среднее 9, отклонение -0.3.
За все остальные тройки среднее будет (9+10+9)/3 = 9.3(3), отклонение +0.03(3)
Если будем скользить окном 4 периода выхода, то среднее будет иногда 9.25, иногда 9.5. Отклонение будет от -0.05 до +0.2
А для собравшихся в начале 10-ток при окне 4 среднее буде меняться от 9 до 9.75, отклонение от -0.3 до 0.45
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Вопросы по С/С++ (СИ)

Сообщение Gudd-Head »

avreal писал(а):Вот в данном случае если сделать
10 10 10 9 9 9 9 9 9 9
то за 10 периодов среднее будет 9.3, но за первые 3 периода среднее будет 10, отклонение +0.7.
Брезенхем даст что-то в духе
9 10 9 9 10 9 9 9 10 9

Немного упустил нить вашего рассуждения, но это похоже на делитель частоты с дробным коэффициентом деления... тема моего диплома (правда, там всё было "в железе") :)
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
BerZerK-ku
Мучитель микросхем
Сообщения: 492
Зарегистрирован: Вт июл 22, 2008 08:10:54

Re: Вопросы по С/С++ (СИ)

Сообщение BerZerK-ku »

БАТАРЕЙКУС писал(а):и ещё непонятно 2-е вещи.
1) вопрос почему в пустом проекте где кроме функции main(){} нечего нету а память программ занята ажжж на 116 байт а озу вооще аж на 268 байт. эт куда такое излишество. чем они там занеты?
2) вопрос как мне зарезервировать некоторое количество байт в озу чтобы хранить там ассемблерные переменные и Си компилятор их не поубивал там.


1) HEAP, CSTACK, RSTACK - посмотрите настройки этих/подобных параметров в используемой среде. Могут быть заполнены вектора прерываний.
2) Как вариант, создаете переменную по определенному адресу и работаете с ней в ассемблере. В IAR это делается так:

Код: Выделить всё

 __no_init int a @ 0x80;
Аватара пользователя
БАТАРЕЙКУС
Потрогал лапой паяльник
Сообщения: 346
Зарегистрирован: Сб фев 07, 2009 19:21:25

Re: Вопросы по С/С++ (СИ)

Сообщение БАТАРЕЙКУС »

точно можно даж массив создать под это дело :))
а вот где настраивать HEAP, CSTACK, RSTACK я так и не нашол :cry:
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Ответить

Вернуться в «Разные вопросы по МК»