Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Вопросы начинающих

Вопросы начинающих Прежде чем задать вопрос, стоит воспользоваться поиском

Ответ
 
Опции темы Опции просмотра
Старый 21.11.2016, 16:49   #1
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Как посчитать длительность импульса

Всем доброго времени суток!
Столкнулся с проблемой:
Есть источник импульсов, который выдает импульсы с периодичностью 20 мс. Длительность импульса 7,86 мс. При моделировании в Proteus'e, все работает безукоризненно. Но вот после зашивки в контроллер, программа не считает эту длительность.
Импульсов на ножке RA0 вообще нет.

Код:
void Time_Impuls(void)
{
   
    if(Flag40us == 1)		//если установлен флаг 40 мкс
    {
		if(PORTAbits.RA4 == 0)
		{
			LATA0 = ~LATA0;
			Time++;				//увеличение счетчика длительности импульса
			if(Time == 192)		//если 0 на ножке длиться 40*192=7680 мкс
			{
				Time = 0;		//сброс счетчика
				LATA1 = 1;		//светодиод горит
			}
		}
		else
		{
			Time = 0;			//сброс счетчика
			LATA1 = 0;			//светодиод не горит
		}
		Flag40us = 0;
	}
}
HeKeD вне форума   Ответить с цитированием
Старый 21.11.2016, 17:19   #2
IceS
Super Moderator
 
Регистрация: 01.03.2007
Адрес: St. Petersburg
Возраст: 39
Сообщений: 3,251
Вес репутации: 3684/111
IceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond reputeIceS has a reputation beyond repute
Отправить сообщение для IceS с помощью ICQ
По умолчанию Re: Как посчитать длительность импульса

Цитата:
Сообщение от HeKeD Посмотреть сообщение
Всем доброго времени суток!
Столкнулся с проблемой:
Есть источник импульсов, который выдает импульсы с периодичностью 20 мс. Длительность импульса 7,86 мс. При моделировании в Proteus'e, все работает безукоризненно. Но вот после зашивки в контроллер, программа не считает эту длительность.
Импульсов на ножке RA0 вообще нет.

Код:
void Time_Impuls(void)
{
   
    if(Flag40us == 1)        //если установлен флаг 40 мкс
    {
        if(PORTAbits.RA4 == 0)
        {
            LATA0 = ~LATA0;
            Time++;                //увеличение счетчика длительности импульса
            if(Time == 192)        //если 0 на ножке длиться 40*192=7680 мкс
            {
                Time = 0;        //сброс счетчика
                LATA1 = 1;        //светодиод горит
            }
        }
        else
        {
            Time = 0;            //сброс счетчика
            LATA1 = 0;            //светодиод не горит
        }
        Flag40us = 0;
    }
}
1. В программе вижу только RA4, RA0 в ней нет
2. Аналоговые функции порта выключены?
3. Если ножка с открытым коллектором - нужно внешний подтягивающий резистор.
__________________
- Готово, мастер !!!
- Что готово ???
- Сломал ...
IceS вне форума   Ответить с цитированием
Старый 21.11.2016, 18:51   #3
tsb58
Senior Member
 
Аватар для tsb58
 
Регистрация: 04.11.2008
Адрес: Харьков
Сообщений: 362
Вес репутации: 992/49
tsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to behold
По умолчанию Re: Как посчитать длительность импульса

Цитата:
Сообщение от HeKeD Посмотреть сообщение
Есть источник импульсов, который выдает импульсы с периодичностью 20 мс. Длительность импульса 7,86 мс... Но вот после зашивки в контроллер, программа не считает эту длительность. Импульсов на ножке RA0 вообще нет.
Для начала было бы полезно указать тип микроконтроллера, для которого это писано.
Из приведенного фрагмента программы можно сделать выводы, что для того, чтобы на RA0 что-то изменилось, нужно выполнить ряд условий:
1) функция Time_Impuls() должна вызываться не однократно, а многократно, причем с довольно малым интервалом (предположительно из главного цикла);
2) где-то (предположительно в обработчике прерывания по одному из таймеров) должен периодически устанавливаться флаг Flag40us;
3) на ножке RA4 должен быть низкий уровень.
Выполняются ли все эти условия?
Даже если все эти условия выполняются, то на RA0 не будет "0 на ножке длиться 40*192=7680 мкс". Из программы следует, что состояние RA0 будет меняться на противоположное каждые 40 мкс. При этом ни начальное, ни конечное состояние RA0 в этом фрагменте программы не задано. Мало того, даже когда счетчик Time досчитает до положенных ему 192, процесс не окончится - счетчик сбросится и начнет считать по новой...
Так что в высказывание типа "При моделировании в Proteus'e, все работает безукоризненно" что-то не верится. Если Вы уж используете Proteus как аргумент, то приложите к сообщению архив с проектом, вот тогда и посмотрим, как оно "работает".
tsb58 на форуме   Ответить с цитированием
Старый 22.11.2016, 10:53   #4
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Как посчитать длительность импульса

Полный код программы:
Код:
#include <pic12f1840.h>

// CONFIG1
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF

// CONFIG2
#pragma config WRT = OFF
#pragma config PLLEN = ON 
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = ON

void Init(void);
void BD_Init(void);
void Processor(void);

    //  ==  переменные
unsigned char   Timer0_40us     =   80;
unsigned char   Flag40us        =   0;
unsigned char   Time            =   0;
unsigned char   StatusByte      =   0x00;

void interrupt inter()
{
    GIE = 0;                            //отмена всех прерываний
    if(T0IF == 1)                       //если переполнился таймер TMR0
    {
        TMR0 = 255 - Timer0_40us;       //записываем значение таймера
        T0IF = 0;                       //сбрасываем флаг переполнения
        Flag40us = 1;                   //установка флага 40мкс
    }//if(T0IF == 1)
    GIE = 1;                            //разрешение всех прерываний
}

int main() 
{
    Init();
    while(1)
    {
        Proccessor();
    }
}

void Init() 
{    
    OSCCON      = 0b11110000;           //PLL is enable, 32 MHz
    // == I/O Port
    ANSELA      = 0b00000000;           //все выходы/входы цифровые
    TRISA       = 0b11011100;           //RA5, RA1, RA0 - выход
    WPUA        = 0b00100011;
    LATA        = 0b00000011;
    // == Timer0 Config ==
    TMR0		= 255 - Timer0_40us;
    OPTION_REG	= 0b00000001;           //Prescaler T0 is 1:4
     // == Interrupt's Config ==
    INTCON      = 0b01100000;           //Timer0 IE is on (D5)
    GIE 		= 1;                    //Разрешение всех прерываний
}

void Proccessor(void)
{
    if(StatusByte == 0x00)
        BD_Init();
    else if(StatusByte == 0x01)
    {
        if(Flag40us == 1)
        {
            Time++;
            if(Time == 150)
            {
                Time = 0;
                LATA1 = ~LATA1;
            }
        }
    }
}

void BD_Init(void)
{
    if(Flag40us == 1)
    {
        if(PORTAbits.RA4 == 0)
        {
            Time++;
            if(Time >= 172)
            {
                if(PORTAbits.RA3 == 1)
                {
                    StatusByte = 0x01;
                    LATA0 = 1;
                }
                Time = 0;
            }
        }
        if(PORTAbits.RA4 == 1)
            Time = 0;
        Flag40us = 0;
    }
}
HeKeD вне форума   Ответить с цитированием
Старый 22.11.2016, 10:58   #5
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Как посчитать длительность импульса

проблема в том, что если без чтения (PORTAbits.RA3 == 1) все работает в железе... а с чтением - нет... хотя на RA3 приходит 5 вольт
HeKeD вне форума   Ответить с цитированием
Старый 22.11.2016, 13:50   #6
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Как посчитать длительность импульса

Прошу у всех прощения за потраченное время. Нашел свой косяк.
Контроллер уходил в режим программирования. После замены в Config LVP=ON на LVP=OFF все заработало.
тему можно закрыть
всем спасибо!
HeKeD вне форума   Ответить с цитированием
Старый 22.11.2016, 14:31   #7
tsb58
Senior Member
 
Аватар для tsb58
 
Регистрация: 04.11.2008
Адрес: Харьков
Сообщений: 362
Вес репутации: 992/49
tsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to behold
По умолчанию Re: Как посчитать длительность импульса

Цитата:
Сообщение от HeKeD Посмотреть сообщение
Нашел свой косяк.
Контроллер уходил в режим программирования. После замены в Config LVP=ON на LVP=OFF все заработало.
Ну, основной "косяк" был именно в этом, но понимаете Вы его не совсем правильно. На самом деле контроллер НЕ уходил в режим программирования, но даташит говорит, что при LVP=ON автоматически активируется функция MCLRE на ножке RA3, не смотря на то, что в программе написано MCLRE = OFF. А при этом ножка RA3 перестает быть просто "входом", поэтому программа и "не видела" 1 на этой ножке.
Но, кроме этого "косяка" в программе есть еще несколько "сопелек", которые, может быть, сейчас и не влияют на функционирование, но их желательно исправить.
Например, строка
Код:
    WPUA        = 0b00100011;
неправильная. Если Вы планировали использовать внутренние "подтяжки", то 1 нужно прописывать в разрядах входов, а не выходов. Если же внутренние подтяжки не нужны, то просто в регистре OPTION_REG старший бит (WPUEN) сделать 1 и, тогда, регистр WPUA можно вообще "не трогать" (ну, или "для уверенности" прописать туда все 0).

В строке
Код:
    INTCON      = 0b01100000;
лишняя 1 в разряде PEIE, для прерываний по TMR0 она не нужна.

В обработчике прерываний лишние строки
Код:
    GIE = 0;                            //отмена всех прерываний
    
    GIE = 1;                            //разрешение всех прерываний
Эти действия выполняются автоматически логикой обработки прерываний.

Ну и напоследок, судя по приведенному Вами тексту программы, сигнал на выходе RA0 (LATA0) и не должен меняться. Сначала в Init() он устанавливается в 1, а потом, в BD_Init() - опять в 1...
tsb58 на форуме   Ответить с цитированием
Старый 22.11.2016, 14:43   #8
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Как посчитать длительность импульса

Просто приведенная программа - вырезка из основного проекта. Некоторые регистры менял, когда запаниковал, почему не видит '1' на RA3 =)
Просто пробовал.

Не соглашусь, что LVP = ON - включение MCLR. Как тогда объяснить то, что программа, после подключения контроллера к схеме, была переписана и не проходила верификацию. но если контроллер не подключался к схеме, то все было нормально?
HeKeD вне форума   Ответить с цитированием
Старый 22.11.2016, 15:00   #9
tsb58
Senior Member
 
Аватар для tsb58
 
Регистрация: 04.11.2008
Адрес: Харьков
Сообщений: 362
Вес репутации: 992/49
tsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to beholdtsb58 is a splendid one to behold
По умолчанию Re: Как посчитать длительность импульса

Цитата:
Сообщение от HeKeD Посмотреть сообщение
Не соглашусь, что LVP = ON - включение MCLR.
Вот выдержки из документации:
Миниатюры
LVP.png   MCLR.png  
tsb58 на форуме   Ответить с цитированием
Старый 22.11.2016, 19:32   #10
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 778
Вес репутации: 1355/52
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Как посчитать длительность импульса

плохой подход:
Цитата:
unsigned char Timer0_40us = 80;
unsigned char Flag40us = 0;
unsigned char Time = 0;
unsigned char StatusByte = 0x00;
флаги правильней описывать через структуру
Код:
volatile struct flag_type {
  unsigned STATUS        : 1;
  unsigned     : 1;
  unsigned          : 1;
  unsigned FL40uS           : 1;
  unsigned                  : 1;
  unsigned                  : 1;
  unsigned                  : 1;
  unsigned                  : 1;
} flag;
это улучшит читаемость кода, сэкономит память, и уменьшит размер кода
Код:
void Proccessor(void)
{ 
     if(!flag.STATUS) 
      { 
        BD_Init();
      }     
     else      
      {         if(flag.FL40uS)         
           {             Time++;             
              if(Time == 150)             
                 {                 
                   Time = 0;
                  LATA1 = ~LATA1; 
                  }
             }     
         }
}
DmitrijVDN вне форума   Ответить с цитированием
Старый 23.11.2016, 09:45   #11
HeKeD
Member
 
Регистрация: 13.10.2016
Адрес: Minsk
Возраст: 28
Сообщений: 39
Вес репутации: 100/9
HeKeD will become famous soon enoughHeKeD will become famous soon enough
По умолчанию Re: Как посчитать длительность импульса

Цитата:
Сообщение от DmitrijVDN Посмотреть сообщение
флаги правильней описывать через структуру
это улучшит читаемость кода, сэкономит память, и уменьшит размер кода
согласен.
После запуска готового решения в железе, программа будет дорабатываться. Некоторые флаги и переменные будут уходить, некоторые будут добавляться. Когда буду точно знать количество всех флагов, буду переделывать в структуры, в зависимости от использования =)

но пока мне удобней так
HeKeD вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Что случилось в работе схемы, и как можно избавиться от этого? vladh Источники питания и силовая электроника 8 16.11.2016 10:37
Измерение длительности импульса с помощью TMR0 TNT116 Вопросы начинающих 44 01.11.2015 01:09
DS2781 1-wire freiheit303 Вопросы начинающих 4 24.02.2011 20:16
Как в объявленной переменной обозначить биты? VAV Продукция MICROCHIP 4 28.02.2008 15:55
PIC16f84a как посчитать сигналы с двух портов surgeon_q Продукция MICROCHIP 14 12.01.2008 10:21


Часовой пояс GMT +3, время: 16:06.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot