Перейти к содержанию

Pic18 Как Рассчитать Время Для Таймера На C18 Компиляторе Mplabx


vv7

Рекомендуемые сообщения

Всем Добрый день, Форумчане !!! :thank_you2:

Всё вот никак не могу понять, как рассчитать время для таймеров в C18 компиляторе. Вот под MicroC - в курсе, а под C18 - ну, вот - никак !

Есть ли где нормальное описание, что за что отвечает ? Всё перерыскал и собрал хоть какой, но рабочий код из кусочков, который нашёл в инете.

Камень: PIC18F452

Среда разработки: MPLAB X, Linux.

Компилятор C18.

Программатор: PICkit3

Кварц на 10 МГц, так как в наличии только 22пкф

:help:

Конфигурация в файле "config_bits.h":

// PIC18F452 Configuration Bit Settings
// 'C' source line config statements
#include <p18f452.h>
// CONFIG1H
#pragma config OSC = HS		 // Oscillator Selection bits (HS oscillator)
#pragma config OSCS = OFF	 // Oscillator System Clock Switch Enable bit (Oscillator system clock switch option is disabled (main oscillator is source))
// CONFIG2L
#pragma config PWRT = OFF	 // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON		 // Brown-out Reset Enable bit (Brown-out Reset enabled)
#pragma config BORV = 20	 // Brown-out Reset Voltage bits (VBOR set to 2.0V)
// CONFIG2H
#pragma config WDT = OFF	 // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 128	 // Watchdog Timer Postscale Select bits (1:128)
// CONFIG3H
#pragma config CCP2MUX = ON	 // CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)
// CONFIG4L
#pragma config STVR = ON	 // Stack Full/Underflow Reset Enable bit (Stack Full/Underflow will cause RESET)
#pragma config LVP = OFF	 // Low Voltage ICSP Enable bit (Low Voltage ICSP disabled)
// CONFIG5L
#pragma config CP0 = OFF	 // Code Protection bit (Block 0 (000200-001FFFh) not code protected)
#pragma config CP1 = OFF	 // Code Protection bit (Block 1 (002000-003FFFh) not code protected)
#pragma config CP2 = OFF	 // Code Protection bit (Block 2 (004000-005FFFh) not code protected)
#pragma config CP3 = OFF	 // Code Protection bit (Block 3 (006000-007FFFh) not code protected)
// CONFIG5H
#pragma config CPB = OFF	 // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code protected)
#pragma config CPD = OFF	 // Data EEPROM Code Protection bit (Data EEPROM not code protected)
// CONFIG6L
#pragma config WRT0 = OFF	 // Write Protection bit (Block 0 (000200-001FFFh) not write protected)
#pragma config WRT1 = OFF	 // Write Protection bit (Block 1 (002000-003FFFh) not write protected)
#pragma config WRT2 = OFF	 // Write Protection bit (Block 2 (004000-005FFFh) not write protected)
#pragma config WRT3 = OFF	 // Write Protection bit (Block 3 (006000-007FFFh) not write protected)
// CONFIG6H
#pragma config WRTC = OFF	 // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write protected)
#pragma config WRTB = OFF	 // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write protected)
#pragma config WRTD = OFF	 // Data EEPROM Write Protection bit (Data EEPROM not write protected)
// CONFIG7L
#pragma config EBTR0 = OFF	 // Table Read Protection bit (Block 0 (000200-001FFFh) not protected from Table Reads executed in other blocks)
#pragma config EBTR1 = OFF	 // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from Table Reads executed in other blocks)
#pragma config EBTR2 = OFF	 // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from Table Reads executed in other blocks)
#pragma config EBTR3 = OFF	 // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from Table Reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF	 // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from Table Reads executed in other blocks)
#pragma target clock 10_000_000

Сам код:

#include "config_bits.h"
#include <stdio.h>
#include <stdlib.h>
#include <timers.h>

void high_isr (void); // ?????!
#pragma code high_vector = 0x08
void interrupt_at_high_vector(void)
{
_asm GOTO high_isr _endasm
}

#pragma interrupt high_isr // Зачем эти приоритеты ?!
void high_isr (void) {

static int o = 0;

if (INTCONbits.TMR0IF){
 INTCONbits.TMR0IF = 0;				
 TMR0H = 0x85; // Здесь, я так понял, всё обнуляем ...
 TMR0L = 0xEE; // И тут

// Юзер [b]Alex[/b] попросил меня изменить данный цикл, я потом изменю, но как-то всё разберу окончательно !! Спасибо !!!
if ( o == 0 ) { PORTB = 0x0E; o = 1; } else
if ( o == 1 ) { PORTB = 0x0D; o = 2; } else
 if ( o == 2 ) { PORTB = 0x0B; o = 3; } else
 if ( o == 3 ) { PORTB = 0x07; o = 4; } else
 if ( o == 4 ) { PORTB = 0x0B; o = 5; } else
 if ( o == 5 ) { PORTB = 0x0D; o = 0; }

}
}
void main (void) {

// Тут просто распределяем выходы, входы и номиналы.
TRISA = 0x00;
PORTA = 0x00;
TRISB = 0xF0;
PORTB = 0x0F;
TRISC = 0x00;
PORTC = 0x00;
TRISD = 0x00;
PORTD = 0x00;
TRISE = 0x00;
PORTE = 0x00;

ADCON1 = 0x0F;

// Тут та самая **па 
T0CON = 0x85; // Регистр контроля ? Почему 0x85 ? 10000101 - я так понял включает определённые биты в этом регистре. В даташите были прописаны определённые биты, но почему именно эти !?
TMR0H = 0x85; // Вписываем что-то в таймер ? 10000101, опять ?
TMR0L = 0xEE; // Тут также ? Почему 11101110 ?
INTCON = 0x20; // Регистры прерывания ?!
INTCON2 = 0x04; // ?
RCONbits.IPEN = 1; // Включаем приоритеты ?
T0CON = 0x85; // Опять регистр контроля ?
TMR0H = 0x85; // Вписываем что-то опять в таймер ?
TMR0L = 0xEE; // Тут опять также ?
INTCONbits.GIEH = 1; // Активирует все высокие приоритеты ?

while (1) {
}
}

Сам код работает стабильно на живой схеме, но точно не в 1 секунду.

------------------------------------------

Собсно, сам вопрос ... ну вот как тут научиться рассчитать хоть 0.00001с или что, за что отвечает. Я рыскал в инете и под каждый компилятор всё по разному ... есть ли где литература или хоть что-то, где можно найти ответы на эти вопросы !!!?

Нашёл пару информаций по сайтам, например ... http://ee.cgu.edu.tw...uP102_Timer.pdf, но, блин, может кто нормально объяснить что и зачем ? Я буду очень благодарен ! Спасибо и дай Бог вам счастья и здоровья !!! :thank_you2: :thank_you2: :thank_you2:

Изменено пользователем vv7
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Вот прога для расчета: PIC Timer Calculator.zip

Спасибо, но он для другого компилятора, предположительно для HI-Tech ...

Вот как под C18 ? Они очень отличаются ...

Например OPTION_REG - в C18 и не пахнет. Или я ошибаюсь ?!

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)

Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.

На вебинаре мы представили информацию не только по линейкам аккумуляторной продукции EVE, но и по решениям для управления ею, что поможет рассмотреть эти ХИТ в качестве дополнительной альтернативы для уже выпускающихся изделий. Также рассмотрели нюансы работы с производителем и сервисы, предоставляемые Компэл по данной продукции. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

да на кой он нужен этот атч...

открываешь даташит на 103 стр читаешь за что отвечает каждый бит регистра T0CON

и согласно рисункам на стр 104 выставляешь нужные биты

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Спасибо ! Открыл. А какие регистры нужно вообще использовать и настраивать для настройки таймера ?

Только T0CON, T1CON, T2CON ? А приоритеты зачем ?

Ссылка на комментарий
Поделиться на другие сайты

каждый регистр отвечает за отдельный таймер.

перечень регистров относившихся к модулю находится в конце раздела на данный модуль

приоритет относится к прерываниям , указание микроконтроллеру где находится обработчик прерывания

Ссылка на комментарий
Поделиться на другие сайты

Как бы вы настраивали первый ( TMR0 ) таймер ?

Хоть маленький пример кода. Я про то, в какой последовательности конфигурировать регистры и какие именно.

В даташите нашёл:

TMR0L

TMR0H

INTCON

T0CON

TRISA

В таблице 10-1 на 105 странице. ( REGISTERS ASSOCIATED WITH TIMER0 )

Получается, что только их надо конфигурировать ?

GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF

T0CON TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0

В таблице были эти значения битов. Где можно найти хоть что-то описывающее эти биты ?

Спасибо, IMXO !

post-195350-0-60972000-1467916076.png

Ссылка на комментарий
Поделиться на другие сайты

INTCON - регистр отвечающий за прерывания вот и ищем его в 8ом разделе даташита

В таблице 10-1 на 105 странице. ( REGISTERS ASSOCIATED WITH TIMER0 )

Получается, что только их надо конфигурировать ?

непосредственно для таймера да, если еще и прерывания от него + в INTCON1 дополнительно указывается уровень приоритета

ЗЫ я кажется уже давал номер страницы, где описаны биты регистра T0CON или нет? >:)

Ссылка на комментарий
Поделиться на другие сайты

Всем огромное спасибо. Уже начал кое как разбираться в конфигурации таймеров и вообще в конфигурации регистров с помощью даташитов.

Но вот как подсчитать 1 секунду или даж лучше миллисекунду - пока никак.

Вот что получилось:

В программе, которую мне прислал Vovka я подобрал 1мс и попробовал интегрировать пару значений из неё в программу - в результате - не получилось. Намного быстрее чем 1 секунда, может ~800мс по ощущениям. Но может и 600.

Файл программы:

#include "config_bits.h"
#include <stdio.h>
#include <stdlib.h>
#include <timers.h>

void high_isr (void);
#pragma code high_vector = 0x08
void interrupt_at_high_vector(void)
{
_asm GOTO high_isr _endasm
}
#pragma interrupt high_isr
void high_isr (void) {

static int o = 0;
static int ms = 0;

if (INTCONbits.TMR0IF){
 INTCONbits.TMR0IF = 0;				
 TMR0H = 0xFC;
 TMR0L = 0x18;
 ms++;

 if ( ms == 2000 ) {
 if ( o == 0 ) { PORTB = 0x0E; o = 1; } else
 if ( o == 1 ) { PORTB = 0x0D; o = 2; } else
 if ( o == 2 ) { PORTB = 0x0B; o = 3; } else
 if ( o == 3 ) { PORTB = 0x07; o = 4; } else
 if ( o == 4 ) { PORTB = 0x0B; o = 5; } else
 if ( o == 5 ) { PORTB = 0x0D; o = 0; }
 ms = 0;
 }
}
}
void main (void) {

TRISA = 0x00;
PORTA = 0x00;
TRISB = 0xF0;
PORTB = 0x00;
TRISC = 0x00;
PORTC = 0x00;
TRISD = 0x00;
PORTD = 0x00;
TRISE = 0x00;
PORTE = 0x00;

ADCON1 = 0x0F;
T0CON = 0b10001000; // 10000101 TMR0ON T0PS2 T0PS0
TMR0H = 0xFC;
TMR0L = 0x18;
INTCON = 0x20;			
INTCON2 = 0x04;
RCONbits.IPEN = 1;				
INTCONbits.GIEH = 1;

while (1) {
}
}

Скрин с программы в атаче.

post-195350-0-67086700-1467925298_thumb.png

Изменено пользователем vv7
Ссылка на комментарий
Поделиться на другие сайты

Как бы вы настраивали первый ( TMR0 ) таймер ?

Хоть маленький пример кода. Я про то, в какой последовательности конфигурировать регистры и какие именно.

кварц =Fosc = 10MHz, нужно скажем получить период срабатывания таймера 1мс

тактовая частота Fм.ц.=Fosc/4=2.5MHz ,

период маш.циклов Тм.ц=1/Fм.ц.=1/2,5=0,4мкс

1мс/0,4мкс=2500 - кол-во приращений таймера

прерывание по таймеру происходит при его переполнении

настраиваем таймер

T0CONbits.T08BIT=0; // 16-ти разрядный таймер
T0CONbits.T0CS=0;// тактирование от осцилятора Fosc/4
T0CONbits.T0SE=0;//
T0CONbits.PSA=1; // предделитель не используется
T0CONbits.T0PS=0;// коэф. предделителя не используется

те для 16-ти разрядного таймера нужно из 65536 вычесть нужное кол-во приращений

65536-2500=63036(10) = 0xF63C(16)

записываем в регистры

TMR0H = 0xF6;
TMR0L = 0x3C;

указываем приоритет прерывания от TMR0

RCONbits.IPEN = 1;  //включаем приоритет
INTCON2bits.TMR0IF=1; // высокое прерывание

разрешаем прерывания

INTCONbits.TMR0IF=1; // от таймера
INTCONbits.GIE=1;// глобально

включаем таймер

 T0CONbits.TMR0ON=1;

в прерывании

#pragma interrupt high_isr // Зачем эти приоритеты ?!
void high_isr (void) {

if (INTCONbits.TMR0IF&&INTCONbits.TMR0IF){
	 INTCONbits.TMR0IF = 0;	
T0CONbits.TMR0ON=0; 			
	 TMR0H = 0xF6;
	 TMR0L = 0x3C;
T0CONbits.TMR0ON=1;}
}

Ссылка на комментарий
Поделиться на другие сайты

чтобы не писать магические числа

                TMR0H = 0xF6;
                TMR0L = 0x3C;

тк регистры расположены последовательно можно назначить 16ти битную переменную непосредственно указав компилятору ее адрес

в хайтеке это

unsigned short          TMR0               @ 0x0FD6;

у вас типа

#define TMR0_const    65536-2500 
#pragma udata my_TMR0 =0x0FD6 // адрес регистра TMR0L
unsigned short          TMR0 = TMR0_const;
#pragma udata

Ссылка на комментарий
Поделиться на другие сайты

Огромное Спасибо !!! Знал бы лично - выслал бы по 2 ящика пива. :thank_you2:

Всё заработало и осознал, как высчитать, как связаны между собой TMR0H и TMR0L, как пользоваться DataSheet и м.д. !!!!

Наиограмное пасиба !!! :thank_you2:

Секунда получилась ! Но - сбивается. Это наверно из-за цикла, да ? Ведь таймер на 1 мс.

Ну я про саму процедуру прерывания таймера, где внутри цикл до 1000 ( 1 секунда ) и после ( внутри ветвления ) - выполнение кода. ( Я правильно понимаю, ведь каждая команда - 1мс ( Грубо говоря ) ) Или, всё-таки что-то сбивает другое. Я просто поставил на часы и после подошёл ( через 3-4 минуты ) и на 0.5 секунд светодиоды сбились.

П.С. А вообще можно так считать точную секунду ? Таким циклом, если таймер на 1 мс ?

if (INTCONbits.TMR0IF){
 INTCONbits.TMR0IF = 0;				
 TMR0H = 0xF6;
 TMR0L = 0x3C;
 ms++;

 if ( ms == 1000 ) {
	 // ***
 }

Ну, да ладно. С меня ( ещё раз ) огромная благодарность данному форуму и Вам !!! Дай Бог Вам Счастья, Удачи и Здоровья !!! IMXO, Yurkin2015, Vovka

Изменено пользователем vv7
Ссылка на комментарий
Поделиться на другие сайты

Просто ... даже и сказать то нечего ... в инете искал, но как-то нигде не нашёл достойной информации ... попались только туториалы и описания других пиков, в которых есть конфигурация FOSC. ( Например PIC18F4550 )

Из-за безысходности пришлось создать эту тему.

Спасибо Yurkin2015, поставил, из-за чего может быть ? :unknw:

Кажется всё рассчитали ))

Было:

TMR0H = 0xF6
TMR0L = 0x3C

0xF63C = 63036

65536-63036 = 2500

Сейчас получается:

TMR0H = 0xF6
TMR0L = 0x41

0xF641 = 63041

65536-63041 = 2495

Разница 5 приращений ? Я правильно понимаю ?

post-195350-0-30972000-1467932271_thumb.png

Изменено пользователем vv7
Ссылка на комментарий
Поделиться на другие сайты

Расчётные значения для TMR0H и TMR0L хороши, если бы они записывались в таймер в то самое мгновение, когда произошло прерывание.

Но в реале это не так. После появления прерывания процессор тратит пару тактов на переход в саму программу обработки прерывания, потом выполняется проверка и обнуление флага INTCONbits.TMR0IF = 0, потом записывается значение TMR0H. И только после всего этого записывается значение в TMR0L и таймер начинает считать с нового числа. То есть от нужных 2500 тиков уже пяток тиков по времени израсходовано. Вот и уменьшаем до 2495.

Если переставить запись в таймер в другое место в обработчике прерывания, типа, добавить пару строк перед, то и константу 2495 снова нужно будет корректировать.

Ссылка на комментарий
Поделиться на другие сайты

Эх ... понял, благодарю ! И как такое можно корректировать ? Только так или есть другой выход ( Небось секретный ;) ) ? Или в помощь придёт осциллограф ? ))

Ссылка на комментарий
Поделиться на другие сайты

В Вашем случае используется старый казацкий способ:

Поставили TMR0L=0х41, запустили систему и с часами в руках ждёте в какую сторону будет расхождение моргания светодиодов и часов.

Если светодиоды отстают от часов увеличиваете TMR0L=0х42 для ускорения.

Если светодиоды побежали вперёд часов - то уменьшайте TMR0L=0х40 ...

Ссылка на комментарий
Поделиться на другие сайты

Всё очень просто.

Вместо

TMR0H = 0xF6
TMR0L = 0x3C

Пишем

TMR0=TMR0-2500;

Тогда все пройденные такты до этой записи будут автоматом корректироваться.

На сколько мне известно, В С18 0-вой таймер уже объявлен как двухбайтный.

Но, дам небольшой совет. 0-вой таймер для таких дел не очень подходит. Заюзайте TMR2, он сам, аппаратно, сбрасывается в 0 при достижении определённого значения. На нём Вы уже сможете сделать точные периодические интервалы.

Ссылка на комментарий
Поделиться на другие сайты

Оно, конечно, заманчиво сделать так

TMR0=TMR0-2500;

Только процессор 8-битный, и сколько тактов он будет вычитать двухбайтные числа? А каждый такт - это тик таймера, видимо константу 2500 надо будет всё же уменьшать.

И потом, надо записать сначала результат вычитания в TMR0H, а потом уже в TMR0L: в другом порядке старший байт не запишется в таймер.

А компилятор может сделать наоборот: сначала вычесть младший байт, записать в TMR0L, потом вычесть старшие байты с учётом заёма и записать в TMR0H.

Интересно было бы взглянуть в ассемблере на результат С18-компиляции такого вычитания.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...