Вопросы по С/С++ (СИ)
- Antifritz
- Прорезались зубы
- Сообщения: 222
- Зарегистрирован: Чт июл 08, 2010 01:03:40
- Откуда: Украина, Киев
Re: Вопросы по С/С++ (СИ)
Поставьте в Протеусе частоту контролера 10000Hz и увидите то, что принципе, программа работает правильно, а вот задержку стоит сделать побольше и последний светодиод не загорается потому, что сразу после того как он был включен идет проверка и PORTB=0b10000000 заменяется на PORTB=0b00000001, проверку нужно делать еще до сдвига:
if(PORTB==0b10000000)
PORTB=0b00000001;
else
PORTB<<=1;
и так далее.
if(PORTB==0b10000000)
PORTB=0b00000001;
else
PORTB<<=1;
и так далее.
Re: Вопросы по С/С++ (СИ)
Antifritz Спасибо 
У радио нет будущего. Летательные аппараты тяжелее воздуха невозможны. Скоро выяснится, что рентгеновские лучи - мистификация.
[i]Лорд Кельвин, физик, 1899 г.[/i]
[i]Лорд Кельвин, физик, 1899 г.[/i]
-
Лютик
- Нашел транзистор. Понюхал.
- Сообщения: 161
- Зарегистрирован: Вт мар 25, 2008 22:10:23
- Откуда: Минск
Re: Вопросы по С/С++ (СИ)
наткнулся на неплохой мануал http://www.romanblack.com/one_sec.htm в котором используется Брезенгемский алгоритм, позволяющий получить период в 1 секунду(и др.) с любой частотой осцилятора.
для генерации 1ой секунды с моим 20МГц PIC16F628A кварцем(тело основного цикла, инициализацию и прочее я опустил(TMR0(прескалер 1:1) и TMR1(прескалер 1:1) включены, как и прерывания от них)):
Но вот беда- часы уходят за 6 часов на секунд 20(вперед), хотя должны идти точно =). Вопрос- чтото я делаю не так? А также, надо ли учитывать такты(машиные циклы) на выполнение сравнения "if(T0IF)", "if(!pcount)", инкрементирования переменной sec, в общем операции ДО сброса флага прерывания T0IF или я чтото неправильно понимаю
Код: Выделить всё
// 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 или я чтото неправильно понимаю
- Antifritz
- Прорезались зубы
- Сообщения: 222
- Зарегистрирован: Чт июл 08, 2010 01:03:40
- Откуда: Украина, Киев
Re: Вопросы по С/С++ (СИ)
Как по мне здесь бОльшую погрешность будет давать неидеальность кварца. По идее, при использовании других кварцев, даже на такую же частоту погрешность тоже должна изменится.
-
Лютик
- Нашел транзистор. Понюхал.
- Сообщения: 161
- Зарегистрирован: Вт мар 25, 2008 22:10:23
- Откуда: Минск
Re: Вопросы по С/С++ (СИ)
судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца добиться желаемого значения
- БАТАРЕЙКУС
- Потрогал лапой паяльник
- Сообщения: 346
- Зарегистрирован: Сб фев 07, 2009 19:21:25
Re: Вопросы по С/С++ (СИ)
доброе время суток мужыки.
пытаюсь изучать Си для pic. подскажите пожайлусто как создать поект для компилятора MCC18.
по описанию из книги ,, применение микроконтроллеров pic 18,, нечё неполучается, мож вы подскажите как быть.
пытаюсь изучать Си для pic. подскажите пожайлусто как создать поект для компилятора MCC18.
по описанию из книги ,, применение микроконтроллеров pic 18,, нечё неполучается, мож вы подскажите как быть.
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Лютик писал(а):Но вот беда- часы уходят за 6 часов на секунд 20(вперед), хотя должны идти точно =). Вопрос- чтото я делаю не так? А также, надо ли учитывать такты(машиные циклы) на выполнение сравнения "if(T0IF)", "if(!pcount)", инкрементирования переменной sec, в общем операции ДО сброса флага прерывания T0IF или я чтото неправильно понимаю
вот блин расстроился:)
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: Вопросы по С/С++ (СИ)
Лютик писал(а):судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #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 писал(а):Лютик писал(а):судя по всему выход один - частотомером измерить частоту генерируемой единицы при помощи данного метода и изменяя значение #define PERIOD , а следовательно и частоты кварца ???добиться желаемого значения
Вы, наверно, хотели сказать что подобрать значение,которое подходит для этой частоты кварца.интересное предложение это что означает программно менять частоту кварца??
дело в том, что я конденсаторы не использую(в макетке), кварц и так возбуждается, поэтому считаю что можно подогнать частоту программно, тем более так проще имхо
Не частоту кварца тогда, а частоту секундных импульсов программно менять:)
В поисках истины человек развивается.
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
как бы вопрос был по алгоритму Брезенхема, по мне - так очень непривычная реализация.
А попроще нельзя ? Так, например
А попроще нельзя ? Так, например
Код: Выделить всё
#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 писал(а):А попроще нельзя ? Так, например
не свосем понял, а если частота 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.
вообщем не очень страшно но всёж неприятно приходится хотяб одну переменную произведения использовать также как int.
да и математическая библиотека ложовая извлечение квадратного корня выполняется за более 6000 м.ц.
втовремя как на ассемблере корень из 24-х разрядного число высчитывается всего за 600 м.ц
оно вобщем и понятно в мат библиотеке переменные float и всё такое. но если меня устраивает точность до целых то зачем столько ждать.
и ещё непонятно 2-е вещи.
1) вопрос почему в пустом проекте где кроме функции main(){} нечего нету а память программ занята ажжж на 116 байт а озу вооще аж на 268 байт. эт куда такое излишество. чем они там занеты?
2) вопрос как мне зарезервировать некоторое количество байт в озу чтобы хранить там ассемблерные переменные и Си компилятор их не поубивал там.
Код: Выделить всё
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: Вопросы по С/С++ (СИ)
Брезенхем даёт не "точный" результат, а хорошее приближение к нему.
Ну вот допустим для простоты, что за заданный временной интервал происходить 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
Ну вот допустим для простоты, что за заданный временной интервал происходить 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: Вопросы по С/С++ (СИ)
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: Вопросы по С/С++ (СИ)
БАТАРЕЙКУС писал(а):и ещё непонятно 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 я так и не нашол
а вот где настраивать HEAP, CSTACK, RSTACK я так и не нашол
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.