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

Здраствуйте!!!

помогите, пожалуйста...

 

Измерить временной интервал. Входные сигналы являются сигналами логического уровня ТТЛ. 2 входных сигнала (от двух фотодатчиков).

Использую микроконтроллер PIC24F16KA102 (28 ножек), семисегментную индикацию (5 индикаторов), интерфейс SPI.

 

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

Поделиться сообщением


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

0. К сожалению, ничего не прикрепилось.

1. С чем именно (PIC, PIC24, PIC24F16KA102, индикация, SPI интерфейс, используемый компилятор) Вы раньше не работали?

2. Чем конкретнее вопрос-тем конкретнее ответ. Где именно застряли? В описании Вашего алгоритма средствами языка программирования? Или в чем-то еще?

Поделиться сообщением


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

Индикацию так реализовала:

 

// Таблица изображения чисел и символов (0,1,2,3,4,5,6,7,8,9) для индикатора

const unsigned char digit[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

 

#define f 5 // Частота обновления результата измерения в предварительном программном буфере, гц.

#define nsum (200/f) // Количество слогаемых при усреднении результата измерения nsum=Fпрер/f.

int data, rez, n, temp, SYM[5];

 

void __attribute__ ((__interrupt__, no_auto_psv)) _T1Interrupt(void)

{

_T1IF = 0;

if (rez==T1)

{

 

// перевод 5-ти значного числа в десятично-символьное число

 

data=data+rez; //data - преобразуемое число,

n++;

if (n==nsum)

{

data=data/n;

if (data > 99999) data=99999;

data=data*10; // умножим число на 10, чтобы вывести один знак после запятой

temp=data/10000;

 

SYM[4]=digit[temp];

data=data-temp*10000;

temp=data/1000;

 

SYM[0]=digit[temp];

data=data-temp*1000;

temp=data/100;

 

SYM[1]=digit[temp];

data=data-temp*100;

temp=data/10;

 

SYM[2]=digit[temp];

data=data-temp*10;

temp=data;

 

SYM[3]=digit[temp];

data=0;

n=0;

}

}

}

 

Потом передаю через SPI

 

void SPI1MasterInit(void)

{

 

SPI1STATbits.SPIEN = 0;

SPI1CON1 = 0;

SPI1STATbits.SPIEN = 0; // отключить интерфейс SPI путем сброса бита SPIEN регистра состояния SPI1STAT

SPI1CON1 = 0; // очистить регистр управления интерфейса SPI1

 

// Используем две сигнальные линии (синхронизации передачи SCK1 и выходных данных SDO1), управляются микроконтроллером

SPI1CON1bits.DISSCK = 0; // бит DISSCK регистра управления SPI1CON сброшены

SPI1CON1bits.DISSDO = 0; // бит DISSDO регистра управления SPI1CON сброшены

SPI1CON1bits.MODE16 = 0; // для 8-битной посылки данных бит MODE16 регистра управления сброшен

SPI1CON1bits.MSTEN = 1; // микроконтроллер в режиме «ведущего», устанавливаем бит MSTEN

SPI1STATbits.SPIEN = 1; // включаем SPI - интерфейс

 

}

 

///// Передача данных на управляемый регистр

 

void peredacha (void)

{

 

// передается строка (массив) символов

 

char *pSYM = SYM[5];

_SPI1IF = 0;

SPI1MasterInit();

while (*pSYM!= 0)

{

// Для передачи одного байта записываем его в регистр SPI1BUF, микроконтроллер выполняет все циклы синхронизации передачи каждого бита

 

SPI1BUF = *pSYM++;

while (_SPI1IF == 0);

_SPI1IF = 0;

}

SPI1STATbits.SPIEN = 0; // выключаем SPI - интерфейс

while(1);

}

 

 

 

 

Как измерить интервал в секундах от начала первого сигнала до начала второго?

 

Сделаю два обработчика прерываний (сигнал 1 появляется на INT0, сигнал 2 появляется на INT1 ), появляются один за другим.Запуталась...как это реализовать.

 

 

Изменено пользователем yliya

Поделиться сообщением


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

Как измерить интервал в секундах от начала первого сигнала до начала второго?

 

Сделаю два обработчика прерываний (сигнал 1 появляется на INT0, сигнал 2 появляется на INT1 ), появляются один за другим.Запуталась...как это реализовать.

 

Как вариант:

1 - настроить прерывания "1" и "2" на срабатывание по фронту(или спаду , но одинаково).

2 - по получению прерывания "1" - обнулить таймер, запустить таймер.

3 - по получению сигнала "2" - остановить таймер, прочитать количество тактов из регистра таймера.

4 - пересчитать количество тактов во время на основании параметров тактирования таймера и частоты CPU.

 

#define _F_CLK 20000000 /*MHz*/
#define _F_TMR ((_F_CLK / _TMR_PR/*предделитель таймера*/) / 1000 /*для получения результата в милисекундах*/)

long tmrRes; /*результат из регистра таймера*/
long time; /*время*/

time = tmrRes  / _F_TMR;

 

Дополнительно, при длительных интервалах времени, может потребоваться фиксировать прерывания от таймера и учитывать переполнение счетчика при определении количества тактов таймера. Второй вариант - каскадирование таймеров в 32-битый (не помню которые позволяли пары создавать).

 

в порядке "покритиковать" - операции деления могут реализоваться программно (есть аппаратная реализация в PIC24 - но зависит от компилятора) и займут много машинного времени. Пересчет лучше перенести в фоновый цикл ПО. Хотя и не обязательно (все таки из вредности) .

Поделиться сообщением


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

Юля, дополню volodya:

 

int data, rez, n, temp, SYM[5];

...

if (data > 99999) data=99999;

data=data*10; // умножим число на 10, чтобы вывести один знак после запятой

 

Во первых, присваивать int значения больше 65535, нельзя. Оператор if здесь никогда не исполнится.

Во вторых, что это за переменная "data"? Вы добавляете туда значение таймера Т1? Так, это же двоичное значение.

Его нужно сначала перевести в десятичное, а только потом вытаскивать каждую цифру отдельно, что вы делаете дальше.

Хотя неизвестно зачем это вам, если будете передавать все цифры через серийный интерфейс SPI - можно "вычислять" каждую цифру

перед отправкой, а потом отправлять, в рамках одного цикла. В языке С принято одинаковые, многократно совершаемые действия,

загонять в цикл. Имейте ввиду, что если не переведете значение "data" в десятичное, при преобразовании "цифра" -> "символ",

зайдете за рамки массива digit, с весьма непредвидимыми(печальными) последствиями.

Но, конечно, вам сначала нужно решить основную задачу, именно как это вам расписал volodya.

Поделиться сообщением


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

int data, rez, n, temp, SYM[5];

...

if (data > 99999) data=99999;

data=data*10; // умножим число на 10, чтобы вывести один знак после запятой

 

А слона то я и не заметил! Переполнение гарантировано по закону Мерфи в момент демонстрации "лицам, облаченным властью" :santa2: .

 

Единственное оправдание - работал с PIC32 и С32 там int - 32 bit. Забыл про различия с PIC24(C16).

 

Поделиться сообщением


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

Спасибо большое!!!) Буду дальше продвигаться!

 

/***************************************** Обработчик прерывания 1 ******************************************/

 

Написала для себя алгоритмик, а как реализовать не знаю...Хоть в правильном направлении иду?

// сохранение контекста ( регистр STATUS и аккумулятор W)

// проверка источника запроса прерывания (опрашиваем флаг)

// сброс флага источника прерывания

// восстановление контекста

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT0Interrupt(void)

{

INTCON2=0;

_INT0EP=0;

// что-то....

 

}

 

/***************************************** Обработчик прерывания 2 ******************************************/

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT1Interrupt(void)

{

INTCON2=0;

_INT1EP=0;

// что-то

 

}

 

 

 

 

Как найти источник прерываний (опросить флаги)?

В программе необходимо определить источник прерывания (с какой стороны пришел сигнал), зажеч светодиод (INT0 - первый светодиод, на RB2, INT1 - второй светодиод, на RB3). Посчитать интервал в секундах.

 

+ есть кнопка которая разрешает выполнение программы и запрещает (кнопка нажата - пошла прога, еще раз нажали- остановилась (наверное запретили прерывания))

 

Обработку кнопки я поместила в main:

 

/* Для запрещения/разрешения прерываний используются две ассемблерные вставки. Группа команд

push SR

mov #0xE0, w0

ior SR

выполняет сохранение в стеке содержимого регистра состояния (push SR), устанавливает уровень приоритета 7 для процессора,

запрещая тем самым пользовательские прерывания (mov #0xE0, w0 и ior SR).

// Для разрешения прерываний нужно просто извлечь из стека старое содержимое регистра.Это произойдет при нажатии на кнопку */

 

asm ("push SR"

"\n mov #0xE0, w0"

"\n ior SR");

while (_RA6 != 1);

asm("pop SR");

while(1);

 

}

 

 

 

 

 

Как найти источник прерываний (опросить флаги)?

В программе необходимо определить источник прерывания (с какой стороны пришел сигнал), зажеч светодиод (INT0 - первый светодиод, на RB2, INT1 - второй светодиод, на RB3). Посчитать интервал в секундах.

 

+ есть кнопка которая разрешает выполнение программы и запрещает (кнопка нажата - пошла прога, еще раз нажали- остановилась (наверное запретили прерывания))

 

Обработку кнопки я поместила в main:

 

/* Для запрещения/разрешения прерываний используются две ассемблерные вставки. Группа команд

push SR

mov #0xE0, w0

ior SR

выполняет сохранение в стеке содержимого регистра состояния (push SR), устанавливает уровень приоритета 7 для процессора,

запрещая тем самым пользовательские прерывания (mov #0xE0, w0 и ior SR).

// Для разрешения прерываний нужно просто извлечь из стека старое содержимое регистра.Это произойдет при нажатии на кнопку */

 

asm ("push SR"

"\n mov #0xE0, w0"

"\n ior SR");

while (_RA6 != 1);

asm("pop SR");

while(1);

 

}

 

Поделиться сообщением


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

Написала для себя алгоритмик, а как реализовать не знаю...Хоть в правильном направлении иду?

Юля! Прочтите внимательно! На этом форуме считается "моветон" просить что бы кто-то за вас написал программу. Это не в обиду, просто имейте

ввиду!

Проехали.

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

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

в попутной прилавке, хотя это можно по запаху установить, но допустим у вас нос заложен).

Сначала вам нужно определится с задачей. Если вы хотите засечь время - это и есть ваша главная задача. Придумать список покупок и

подсчитать необходимую сумму(опрашивать кнопки и передавать результат по SPI), это второстепенные задачи. И так, начнем:

Вам нужно засечь время между выходом молодого человека из дома (сигнал на входе INT0) и возвращением его домой (сигнал на входе INT1).

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

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

в регистре IEC0 прерывание INT0 - выставить бит 0, а также в регистре IEC1 прерывание INT1 - выставить бит 4. Естественно, не надо забывать

настроить соответствующие выводы процессора на "вход" - в соответствующих регистрах TRIS).

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

реального времени), тогда можно использовать обычный кухонный таймер на 30 минут (лучше использовать Таймер1 процессора, так как он

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

(настраиваем требуемые функции Таймера1, в регистре T1CON, оставив пока бит 15 - 0, так как запустим таймер по первому событию - INT0).

Молодому человеку объясняем, что собираемся варить яйцо, поэтому достали таймер. Поскольку ожидаемое время прибытия подопытного

может оказаться за пределами этого полчаса (измеряемый интервал времени может оказаться больше времени переполнения Таймера1)

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

(в регистре IEC0 выставляем бит 3, что бы разрешить прерывание от Таймера1).

Все это была подготовка. (Всю эту подготовку, нужно сделать в основной программе. Можно, для наглядности ее вынести в отдельную процедуру,

назвав ее InitTimerAndInterrupts и вызвать ее в начале основной программы)

Теперь ждем первого звонка дверного колокольчика(передаем управление основной программе, в которой опрашиваем кнопки и т.д.).

Как только раздается звонок, запускаем кухонный таймер (при возникновении события на входе INT0 исполнение основной программы прерывается

и контроллер прерываний отправляет процессор на вектор соответствующего прерывания. Не надо опрашивать флаги прерываний, в 24-ой серии

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

заботится компилятор. И так первое что нужно сделать в обработчике прерываний по-вектору INT0 - это запустить Таймер1, выставив

бит 15 в регистре T1CON. После этого, что бы не терять время, нужно обнулить флаг INT0IF в регистре IFS0. Если предполагается что измерение

интервалов времени будет делаться многократно, сначала при входе в прерывание нужно обнулить Таймер1 а также и переменную vremya, в

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

сделать в обработчике прерывании INT0. Можно на всякий пожарный запретить прерывания INT0, что бы если произойдет второе событие

на входе INT0, до завершении цикла INT1, оно не сбило счет времени).

Дальше возвращаемся в одноклассники (управление автоматически передается основной программе. Продолжаем опрашивать кнопки и т.д.).

Как только раздается звонок кухонного таймера (если Таймер1 один переполнится - возникает прерывание), заряжаем его на 30 минут опять,

достаем ручку и ставим одну отметку на лист бумаги(в обработчике прерывании по вектору Т1 добавляем к переменной vremya 65536,

сбрасываем флаг T1IF в регистре IFS0 и выходим).

Дальше эта нехитрая процедура повторяется до возвращения любимого.

Как только услышим второй звонок дверного колокольчика, останавливаем кухонный таймер и записываем его показание(в обработчике

прерывании по вектору INT1 добавляем содержимое Таймера1 во vremya и останавливаем Таймер1 сбросив бит 15 в регистре T1CON. Если

запретили прерывание от INT0, здесь его нужно разрешить снова, что бы подготовить систему для следующего измерения).

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

для точности и звоним маме/продвинутой подруге (делим значение переменной vremya на количество тактов Таймера1 в секунду, что бы

получить время в секундах, а если хотим получить время в десятых секунды, делим на количество тактов Таймера1 в десятую секунды.

Дальше если надо, преобразуем значение времени в десятичное и выставляем флаг, что бы дать основной программе знать, что процедура

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

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

в нетерпение вернутся домой.

И все. Тут и сказочке конец. Увидели как просто! :biggrin:

Поделиться сообщением


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

Я хочу научиться, а не просто "передрать и сдать"...)

 

Ничего себе, интересно и понятно! спасибо большое!))))))

Поделиться сообщением


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

Я хочу научиться, а не просто "передрать и сдать"...)

 

Юля, это золотые слова! Я надеюсь, что ваша пыль не остынет! Не страшно ошибиться, страшно сдаться. (знаю, что банально)

Раньше советские женщины летали в космос. Я, по своей работе, встречал девушки, которые могут дать фору любому из здешних

обитателей.

Буду рад помочь!

Поделиться сообщением


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

))))

Сделала так, чуть по другому. Мне надо знать в ту ли он сторону пошел вообще)

 

/*********************************** Обработчик прерывания 1 (INT0)(идет налево) ****************************/

 

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT0Interrupt(void)

{

_RB2=0; // засветили зеленый светодиод

_RB3=1; // погасили красный светодиод

 

IFS0bits.INT0IF =0; // обнуляем флаг INT0IF в регистре IFS0

IEC0bits.INT0IE=0; // запрещаем прерывания INT0, чтобы если произойдет второе событие на входе INT0,

// до завершении цикла INT1, оно не сбило счет времени

if (i==0)

{

T1CONbits.TON=1; // старт таймера 1

i=1;

}

else

T1CONbits.TON=0; // cтоп таймера 1

tmr1Res = TMR1;

 

TMR1=0; // обнуляем таймер 2

i=0;

 

}

 

/***************************************** Обработчик прерывания 2 (INT1) (идет вправо) **************************/

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT1Interrupt(void)

{

 

_RB2=1; // погасили зеленый светодиод

_RB3=0; // засветили красный светодиод

 

IFS1bits.INT1IF =0; // обнуляем флаг INT1IF в регистре IFS1

IEC1bits.INT1IE=0; // запрещаем прерывания INT1

 

if (j==0)

{

T2CONbits.TON=1; // старт таймера 2

j=1;

}

else

T2CONbits.TON=0; // cтоп таймера 2

tmr2Res = TMR2;

 

TMR2=0; // обнуляем таймер 2

j=0;

}

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

/************************************** Основная программа ***************************************************/

void main (void)

{

InitTimerAndInterrupts ();

_RB2=1; // погасили светодиод 1

_RB3=1; // погасили светодиод 2

 

 

// Счет времени

 

if (IFS0bits.INT0IF =1)

{

time = tmr1Res/256 /*предделитель таймера*/ / 1000/*для результата в милисекундах*/; // Результат, "молодец"

}

else

time = tmr2Res/256 /*предделитель таймера*/ / 1000/*для результата в милисекундах*/; // Результат, "сходил налево"

 

 

// *************************************** Инициализация ******************************************************//

// инициализация

void InitTimerAndInterrupts (void)

{

// Настройка прерываний

IEC0bits.INT0IE=1; // в регистре IEC0 прерывание INT0 - выставить бит 0, а также в регистре IEC1 прерывание INT1 - выставить бит 4

IEC1bits.INT1IE=1; // разрешаем прерывания на INT0 и INT1

// Настройка таймеров

IFS0bits.T1IF = 0; // Clear Output Compare interrupt flag

IEC0bits.T1IE = 1; // разрешаем прерывания таймеров

IFS0bits.T2IF = 0;

IEC0bits.T2IE = 1;

 

// работа от внешнего источника тактового сигнала

_TCS=1;

_TSYNC = 1; // выполняется синхронизация внешнего сигнала

_TCKPS=0011;

// Настройки выводов

TRISBbits.TRISB7 = 1; // выводы прерываний сконфигурированы на вход (RB7 и RB14)

TRISBbits.TRISB14 = 1;

TRISBbits.TRISB2 = 0; // выводы светодиодов сконфигурированы на выход (RB7 и RB14)

TRISBbits.TRISB3 = 0;

 

}

 

 

 

 

// Счет времени там... если... тыры пыры не обращайте внимания) там неправильно...посчитаю правильно в самих обработчиках и там же пошлю на индикацию

Поделиться сообщением


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

Сделала так, чуть по другому. Мне надо знать в ту ли он сторону пошел вообще)

самих обработчиках и там же пошлю на индикацию

 

Не совсем понятно - зачем в прерывании INT1 запускать второй таймер. Вроде требовалось измерять время между двумя прерываниями. То есть - по второму прерыванию - остановить первый таймер и зафиксировать его счетчик.

В вашем куске кода (по первым прикидкам) запустится два таймера и , по скольку, дальнейшие прерывания запрещены (INTxIE = 0) то результат не будет получен никогда. Или (если прерывания не запрещать) то будут получены времена между событиями на каждом из прерываний но между собой не- или слабо- связанные. То есть от время период следования каждого из сигналов.

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

То есть запустить таймер по первому прерыванию и остановить по второму. Таймеров в PIC хватает - можно и третий использовать - тогда будут получены и периоды и фаза между сигналами.

В main части ожидание отсутствует (нет ни while ни др. операторов) сразу после инициализации пройдет проверка (if (IFS0bits.INT0IF = 1) - не проверка , а присваивание всегда TRUE кроме прочего может генерировать прерывание) с выполнением кода до else

и далее по программе (кода не приведено)

 

Рекомендую для наглядности просимулировать в microcip-овккой IDE (не очень наглядно) или попробовать в PROTEUS со схемкой в реальном времени (очень наглядно , правда там не все модели PIC , но подходящий можно подобрать и пробламы с лицензиями - или платить или ломать - в и-нете масса ссылок ).

Поделиться сообщением


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

В правильном направлении двигаетесь, Юля.

Если я хорошо понимаю, вы решили измерять временные интервалы между импульсами на одном и том же входе - INT0 и INT1.

Время между импульсами на входе INT0 измеряете Таймером1 и записываете в переменную tmr1res, а соответственно время между импульсами на входе INT1 - Таймером2 и записываете в переменную tmr2res.

Все правильно сделано, понравилось использование флагов i и J. Правда, принято в С обозначать флаги немножко по-другому,

использовать другие имена, начинающие, например на "fl" - fl_tmr1 или fl_tmr2. Но это вопрос синтаксиса.

Также не надо запрещать прерывание:

             IFS0bits.INT0IF =0; // обнуляем флаг INT0IF в регистре IFS0
             IEC0bits.INT0IE=0;     // запрещаем прерывания INT0, чтобы если произойдет второе событие на входе INT0, 
                                // до завершении цикла INT1, оно не сбило счет времени

так как в таком случае, после первого прерывания, второго не будет. Просто удалите строчку IEC0bits.INT0IE=0;. Я это предложил вам сделать,

что бы цикл измерения начинался только с сигнала на входе INT0 и заканчивался только по сигналу на входе INT1. Но тогда я вам

предложил разрешить его в конце цикла измерения, а именно в обработчике прерывания INT1.

Зато здесь, если запретите после первого сигнала, второй сигнал не вызовет прерывание и программа "зависнет".

То же самое нужно сделать и во втором обработчике - убрать похожую строчку.

Прокралась синтаксическая ошибка:

if (i==0)

{

T1CONbits.TON=1; // старт таймера 1

i=1;

}

else

{

T1CONbits.TON=0; // cтоп таймера 1

tmr1Res = TMR1;

 

TMR1=0; // обнуляем таймер 2

i=0;

}

 

В основном - очень хорошо! Давайте дальше - вам нужно написать два (практически одинаковых) обработчика прерываний таймеров (1 и 2).

 

 

ПП А вот это:

...посчитаю правильно в самих обработчиках и там же пошлю на индикацию

в обработчиках не делается. Принцип С - это писать обработчики прерываний как можно короче и не прерывать исполнение кода обработчика

обращениями ко внешним функциям. Когда процессор исполняет код обработчика, он находится в особом состоянии - "исключение". Если в

основной программе его можно прерывать, здесь (в зависимости от приоритета прерывания, конечно) - нельзя. Поэтому можно пропустить

важные события или опоздать с обработкой других данных, если задержатся слишком долго в обработчике. Считается правильнее делать обработку данных в основной программе, а в обработчике прерываний выполнять только служебную работу - сбрасывать/поднимать флаги, запускать/заряжать таймеры, запускать/останавливать/опрашивать периферийные модули и т.д.

 

EDIT: volodya меня опередил. Все что он написал верно, просто вы до этого пока не дошли.

Поделиться сообщением


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

Спасибо огромное за ценные замечания) Обязательно учту.

 

volodya, вы поняли меня правильно и я хотела так и делать, но сложность моей задачи состоит в том, что где появится первый сигнал неизвестно (либо на INT0, либо на INT1)...

 

сделала бы так (если бы точно знала что сигнал появится на первом входе INT0) и пользовалась бы одним таймером:

 

/* Обработчик прерывания 1 (INT0) (пошел в магаз) */

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT0Interrupt(void)

{

_RB8=1; // засветили светодиод 1 (ушел)

_RB9=0; // погасили светодиод 2

 

IFS0bits.INT0IF =0; // обнуляем флаг INT0IF в регистре IFS0

IEC0bits.INT0IE=0; // запрещаем прерывания INT0

TMR1=0; // обнуляем таймер 1

tmr1Res = 0; // обнуляем переменную, в кот. накапливается кол-во времени от таймера

T1CONbits.TON=1; // старт таймера 1

 

}

 

 

/* Обработчик прерывания 2 (INT1) (вернулся домой) */

 

void __attribute__ ((__interrupt__, no_auto_psv)) _INT1Interrupt(void)

{

 

_RB8=0; // погасили светодиод 1

_RB9=1; // засветили светодиод 2 (вернулся домой)

 

IEC0bits.INT0IE=1; // разрешаем прерывания INT0

IFS1bits.INT1IF =0; // обнуляем флаг INT1IF в регистре IFS1

T1CONbits.TON=0; // cтоп таймера 1

tmrRes=TMR1;

}

 

но ... если сигнал появится на INT1? что делать в этом случае? поэтому чуть изменила мысль...

 

я получаю из таймера двоичное значение, мне нужно перевести в десятичное... Примерно так :

 

tmrRes=tmr1h

T=T+tmr1l

tmrRes=((tmr1H<<8)+tmr1L) ???

 

tmr1h, tmr1l - можно unsigned char?

 

Мало пока понимаю, но все же...

 

Спасибо огромное за помощь!

Изменено пользователем yliya

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

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