|
|
  |
1 секунда на С |
|
|
|
Apr 29 2008, 09:59
|

Частый гость
 
Группа: Свой
Сообщений: 91
Регистрация: 13-07-07
Из: Украина, Днепропетровск
Пользователь №: 29 095

|
Цитата(ZLOI @ Apr 29 2008, 10:45)  Здравствуйте, интересно бы увидеть фрагмент кода на С, который бы позволял на 16 пике с 4 МГц кварцем каждую секунду увеличивать значение какой-нибудь переменной на 1. Интересно, вдруг я делаю неправильно. Покажите что и как вы делаете, ну а мы уже скажем так или не так делает. Конфигурирование таймера и прерывания этож класскика жанра. Показуйте свой код ...
--------------------
2b || !2b = ? --------------------
|
|
|
|
|
Apr 29 2008, 12:00
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(ZLOI @ Apr 29 2008, 13:45)  который бы позволял на 16 пике с 4 МГц кварцем каждую секунду увеличивать значение какой-нибудь переменной на 1. Таймер разрядности менее, чем 32 можно программно расширить до 32-х разрядов. А с помощью 32-х разрядного уже можно отмерить интервал в 1с даже при тактовой 4 ГГц. И вообще, чем вас аппликухи у Microchip не устраивают?
|
|
|
|
|
Apr 30 2008, 09:49
|

Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-03-07
Из: Славный город Шелехов
Пользователь №: 25 967

|
Цитата(GVC @ Apr 29 2008, 18:59)  Покажите что и как вы делаете, ну а мы уже скажем так или не так делает. Конфигурирование таймера и прерывания этож класскика жанра. Показуйте свой код ... Забыл подписаться, поэтому не отвечал. Код #include <pic12F6x.h>
int time;
void interrupt Times(void) { if (++time==3906) { unsigned char to_delay=0; while (++to_delay<6) {} time=0; _asm NOP _endasm time=0;// time=0;//Вообщем надо как-то паузу сделать, TMR0=0;//по грамотному, а то вдруг компилер сменил и всё, не пашет. GPIO=!GPIO; } T0IF = 0; } main() { int x; GPIO=0; CMCON=7; TRISIO=254; GPIO=0; GIE=1; T0IE=1; T0CS=0; PSA=1; TMR0=1; for(;;) {} } Собственно сейчас у меня компилера нет поэтому протестить особо не могу, но по памяти, что-то типа такого делал. И работало оно как надо, по крайней мере за неделю ни на секунду не сдвинулось. Алгоритм простой, таймер инкрементиться каждые 256 машинных циклов таймер вызывает прерывание и увеличивает переменную time на 1. Секунда проходит через 1000 000 машинных циклов или через 3906 прерываний и ещё 64 такта. Вот у меня и вопрос, как сделать чисто на С, чтобы любой другой компилятор поставил и всё работает. Хочется знаете, увидеть как делают мастера. Цитата(rezident @ Apr 29 2008, 21:00)  Таймер разрядности менее, чем 32 можно программно расширить до 32-х разрядов. А с помощью 32-х разрядного уже можно отмерить интервал в 1с даже при тактовой 4ГГц. Знаю. Проблем со "сделать" нет. Не хочется быть умным программистом, который тупым кодом делает гениальные вещи. Хочется делать красиво. Вот Вы мне скажете. Я посмотрю и подумаю: "Ёлки палки, да ведь здесь же надо в таком направлении двигаться, такие книжки читать и т.д.". P.S. Сомневаюсь, что буду когда-нибудь использовать такие бешеные частоты
|
|
|
|
|
Apr 30 2008, 14:05
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(ZLOI @ Apr 30 2008, 15:49)  Знаю. Проблем со "сделать" нет. Не хочется быть умным программистом, который тупым кодом делает гениальные вещи. Хочется делать красиво. Вот Вы мне скажете. Я посмотрю и подумаю: "Ёлки палки, да ведь здесь же надо в таком направлении двигаться, такие книжки читать и т.д.". Если у вас уже есть таймерное прерывание, то в нем просто инкрементируйте какую-либо беззнаковую переменную на величину тика таймера, выраженную, например, в миллисекундах. Код #define TICK_TIMER 10UL // тик таймера 10 мс
volatile unsigned long time;
void interrupt Times(void) { time+=TICK_TIMER; ... } Переменная time "тикает" себе в фоне потихоньку. Когда вам нужно сделать задержку в main-е, то делаете такую конструкцию Код void main (void) { unsigned long tmpTime1, tmpTime2; ... _disable_interrupt(); tmpTime1=time; _enable_interrupt(); do { _disable_interrupt(); tmpTime2=time; _enable_interrupt(); } while ((tmpTime2-tmpTime1)<1000UL); //задержка на 1000мс=1с ... } Запрет прерываний перед считыванием переменной time требуется только, если другим образом нельзя обеспечить атомарность операции ее чтения. Например, когда вы пытаетесь на 8-ми битном MCU оперировать 32-х битными переменными. Все используемые в примере переменные должны быть беззнаковыми. Переменная time обязательно должна иметь квалификатор volatile. При исчислении в миллисекундах 32-х разрядной переменной хватает для измерения интервалов времени длительностью свыше 1,5 месяца. P.S. Для выполнения каких-либо действий по отметкам времени можно поступать аналогично. Код void main (void) { unsigned long tmpTime1, tmpTime2; ... _disable_interrupt(); tmpTime2=time; _enable_interrupt(); if ((tmpTime2-tmpTime1)>=1000UL) // прошло больше 1000мс? { funcDo1sPeriod(); // да, вызываем функцию _disable_interrupt(); tmpTime1=time; // обновляем значение переменной заданного интервала _enable_interrupt(); } ... } Еще раз обращаю внимание, что переменные должны быть беззнаковыми. В этом случае корректно обрабатывается ситуация переполнения их максимального значения при сравнении этих чисел.
|
|
|
|
|
Apr 30 2008, 14:37
|

Частый гость
 
Группа: Свой
Сообщений: 91
Регистрация: 13-07-07
Из: Украина, Днепропетровск
Пользователь №: 29 095

|
Цитата(ZLOI @ Apr 30 2008, 12:49)  Вот у меня и вопрос, как сделать чисто на С, чтобы любой другой компилятор поставил и всё работает. Хочется знаете, увидеть как делают мастера. Принцип правильный, програмируете таймер на определённый интервал времени (не обязательно 256 машинных циклов, есть же делители у таймера  ), в зависимости от требуемой дискреты (это добивается делителем для таймера а также значением загружаемым в счётчик таймера), например можно получить почти 1, 10, 100 мСек. Ну а далее в прерывании от этого таймера программно "считает" эти интервалы времени до требуемой вам величины. Это чисто на си реализуемо просто. А вот вся "обвязка" прерываний на си не имеет стандарта и в зависимости от компилятора вам всётаки прийдётся вносить изменения в обьявления векторов прерывания и обработчиков ... Такчто полной универсальности трудно добится, есть особенности у каждого компилятора.
--------------------
2b || !2b = ? --------------------
|
|
|
|
|
Apr 30 2008, 15:49
|

Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-03-07
Из: Славный город Шелехов
Пользователь №: 25 967

|
Цитата(GVC @ Apr 30 2008, 23:37)  Ну а далее в прерывании от этого таймера программно "считает" эти интервалы времени до требуемой вам величины. Вот я про это и говорю, компиляторы могут по разному "считать" и поэтому лучше АСМ вставить. Просто цикл забабахать и всё. Цитата(rezident @ Apr 30 2008, 23:05)  Если у вас уже есть таймерное прерывание, то в нем просто инкрементируйте какую-либо беззнаковую переменную на величину тика таймера, выраженную, например, в миллисекундах. Я говорил конкретно под 4 МГц. Просто нацело миллион на 256 не делится и мне кажется, что придётся отсчитывать конкретное количество циклов. Т.е. когда у нас предделитель перед WDT, то как я уже говорил 3906 прерываний и 64 такта длятся одну секунду. Если поставить предделитель перед таймером скажем 256, то секнда будет длится 15 прерываний и 16960 машинных циклов. Или нет? © Bill. Впрочем спасибо за ответ, когда достану хайтек Иваныча, то попробую.
Сообщение отредактировал ZLOI - Apr 30 2008, 15:50
|
|
|
|
|
Apr 30 2008, 16:17
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(ZLOI @ Apr 30 2008, 21:49)  Я говорил конкретно под 4 МГц. Просто нацело миллион на 256 не делится и мне кажется, что придётся отсчитывать конкретное количество циклов. Т.е. когда у нас предделитель перед WDT, то как я уже говорил 3906 прерываний и 64 такта длятся одну секунду. Если поставить предделитель перед таймером скажем 256, то секнда будет длится 15 прерываний и 16960 машинных циклов. Или нет? © Bill. Во-первых, я давал вам советы с точки зрения алгоритма без привязки к конкретному МК или компилятору. Во-вторых, я не знаком с периферией PIC16, чтобы что-либо конкретно советовать по таймеру. У тех таймеров с которыми я работал кроме предделителя имеется режим счета с перезагрузкой. Т.е. таймер считает не до макс. значения, а до какого-то конкретного значения, задаваемого в регистре сравнения, после чего перескакивает в состояние 0. Поэтому установить более точную частоту прерываний не составляет особой сложности. В-третьих, вы же не указали с какой точностью вам нужно отсчитывать секундные интервалы. Если вам небольшие интервалы для регистрации каких-то событий нужно отсчитывать это одно, а же если вы решили организовать RTC с точностью хода ±20 секунд/год это совершенно другой коленкор! В-четвертых, если вы хотите быть программистом, то должны стремиться к самостоятельной разработке алгоритмов. Программисту достаточно понимания самой идеи и/или принципов, а разработка и программная реализация алгоритма это и есть собственно работа программиста. Ну уж а писать программу по готовому алгоритму это вовсе работа кодера, а не программиста.
|
|
|
|
|
May 1 2008, 07:36
|

Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-03-07
Из: Славный город Шелехов
Пользователь №: 25 967

|
Цитата(rezident @ May 1 2008, 01:17)  Во-первых, я давал вам советы с точки зрения алгоритма без привязки к конкретному МК или компилятору. Я заметил. Цитата(rezident @ May 1 2008, 01:17)  Во-вторых, я не знаком с периферией PIC16, чтобы что-либо конкретно советовать по таймеру. Думаю, не слишком много потеряли  Цитата(rezident @ May 1 2008, 01:17)  В-третьих, вы же не указали с какой точностью вам нужно отсчитывать секундные интервалы. Цитата каждую секунду увеличивать значение какой-нибудь переменной на 1 Цитата(rezident @ May 1 2008, 01:17)  В-четвертых, если вы хотите быть программистом, то должны стремиться к самостоятельной разработке алгоритмов. Программисту достаточно понимания самой идеи и/или принципов, а разработка и программная реализация алгоритма это и есть собственно работа программиста. Ну уж а писать программу по готовому алгоритму это вовсе работа кодера, а не программиста.  Ну вот алгоритм я сам и придумал, это не сложно. Апликухами я вообще почти не пользуюсь, от этого есть и минусы, но безусловно есть и плюсы, не похвалишься сотней устройств сделанных по чужим схемам, но начинаешь понимать многое сам.
|
|
|
|
|
May 1 2008, 15:22
|

Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-03-07
Из: Славный город Шелехов
Пользователь №: 25 967

|
Цитата(_Ivan_33 @ May 1 2008, 17:36)  эээ... while(1) { delay_ms(1000); a++;} Вообще оригинальный ответ Я даже не думал, что Вы так словчите. Но мне он не кажется корректным. Если delay_ms это задержка на одну милисекунду, то это тоже неправильный код, поскольку ещё будет добавляться время от a++. А оно должны быть пару мкс. А пара микросекунд за год это уже полминуты набежало. Хотелось бы узнать как delay_ms определяет какой у Вас кварц стоит. Конечно я говорил о другом. Вся эта тема с таймером не должна занимать основное время МК, там ещё надо будет на ЖК выводить и другие операции. И правильное решение через прерывание. P.S. Ну и мотивация для создания темы была желание проверить, нужно ли знать ассемблер, чтобы решить такую задачу.
|
|
|
|
|
May 2 2008, 23:18
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Цитата(ZLOI @ May 2 2008, 00:22)  Вообще оригинальный ответ Я даже не думал, что Вы так словчите. Но мне он не кажется корректным. Если delay_ms это задержка на одну милисекунду, то это тоже неправильный код, поскольку ещё будет добавляться время от a++. И не только от a++, надо полагать, что у Вас, кроме инкремента переменной и другая полезная работа выполняется, на которую тоже время нужно... Цитата(ZLOI @ May 2 2008, 00:22)  Хотелось бы узнать как delay_ms определяет какой у Вас кварц стоит. Возможно это пример под GCC компилятор. Величина системной частоты передается через параметр в makefile. Цитата(ZLOI @ May 2 2008, 00:22)  Конечно я говорил о другом. Вся эта тема с таймером не должна занимать основное время МК, там ещё надо будет на ЖК выводить и другие операции. И правильное решение через прерывание. Чтоже мешает реализовать все это через прерывания? Если с учетом делителей таймера не подходит кварц, то можно выбрать другой. Либо настроить режим работы таймера по совпадению, если такой имеется в PIC'e. И инкрементировать переменную уже в прерывании. Цитата(ZLOI @ May 2 2008, 00:22)  Ну и мотивация для создания темы была желание проверить, нужно ли знать ассемблер, чтобы решить такую задачу. Не нужно.
--------------------
Выбор.
|
|
|
|
|
May 3 2008, 05:12
|

Частый гость
 
Группа: Участник
Сообщений: 147
Регистрация: 7-03-07
Из: Славный город Шелехов
Пользователь №: 25 967

|
Цитата(haker_fox @ May 3 2008, 08:18)  Чтоже мешает реализовать все это через прерывания? Ничего я же давно это реализовал.
|
|
|
|
|
May 4 2008, 23:33
|
Местный
  
Группа: Свой
Сообщений: 237
Регистрация: 14-08-07
Из: Москва
Пользователь №: 29 791

|
Цитата(ZLOI @ May 3 2008, 09:12)  Ничего я же давно это реализовал. Программист микроконтроллеров несколько отличается от просто программиста.  Поставь кварц на 40 96 кГц и работай просто по прерыванию.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|