Миландр

Ключевым подразделением нашей компании
является Центр Проектирования интегральных микросхем
Текущее время: 2021-окт-21 04:32

Часовой пояс: UTC+03:00




Начать новую тему  Ответить на тему  [ 2 сообщения ] 
Автор Сообщение
СообщениеДобавлено: 2021-июл-21 15:45 
Не в сети

Зарегистрирован: 2019-июн-20 16:29
Сообщения: 5
Организация: АО "Завод "Двигатель"
Здравствуйте!
Хочу поделится простеньким проектом на 1886ВЕ7. Возможно будет полезно тем кто осваивает контроллеры.
Устройство представляет собой программируемое реле времени на 16 интервалов. Код написан в IDE1886. Компилятор CC7A - demo.
Добавить: 
          1) Функцию защиты от сброса по WDT и питанию с использованием EEPROM для хранения состояния и прошедшего времени.
          2) Режим работы от RC цепи с функцией калибровки от генератора. Калибровочный коэфициент хранить в EEPROM
          3) Добавить авто расчет коэффициента деления предделителя таймера 0 для достижения наименьшей погрешности при максимально широком диапазоне интервалов
*/
#include <1886VE7.h> 

#pragma rambank 0
int32 sum;     // тут храним текущее кол-во переполнений таймера Т0

#include "int17xxx.h"
#pragma origin 0x8

interrupt iServer(void)
{
multi_interrupt_entry_and_save

 PERIPHERAL_service:
     nop();
 TMR0_service:
     T0IF = 0;
     sum++;
//     RA5=!RA5; //для теста

 T0CKI_service:
     nop();
 INT_service:
     nop();

    interrupt_exit_and_restore
}

#pragma codepage 1
#include "math32f.h" //Подключаем библиотеку для работы с плавающей запятой

#define CPUCLK 8000000.0 //Кварц или RC цепь
#define FC (CPUCLK/4.0)// Таймер получает CLK/4 это не указанно нигде кроме как на рисунке №20 стр. 54 даташита.
#define TIMER_SIZE 0xFFFF //16 разрядов
#define TIMER_CLK_PRESCALER 0 //степень двойки
#define T0_PRESCALER (1<<TIMER_CLK_PRESCALER)
#define NUMENATOR (FC/T0_PRESCALER/TIMER_SIZE) //количество прерываний от таймера 0 по переполнению в сек, нужно вещественное число для обеспечения точности в +/- 1 интервал переполнения таймера
#define ERROR 0.0 //Для компенсации времени запуска и ошибки от неточности RC цепи по данным с EEPROM (на будущее)

#define STEP 20.0 //шаг уставки сек
#define START 100.0 //Начало шакалы сек
#define INTERVAL_NUM 15 //Кол-во программируемых интервалов
#define TIME_DEFAULT INTERVAL_NUM //Интервал по умолчанию... нужно уточнить у специалистов какой взять!

#define TL_TH_MASK 0x03
#define A0_A3_MASK 0xE3

#define MUX_DELAY 5 //Задержка считывания сигнала с MUX после его переключения

#define PORTA_DEFAULT_STATE 0x43
#define PORTA_DEFAULT_DIRECTION 0x83

bit MUXEN		@ PORTA.6;

#define MUX_ENABLE MUXEN = 0
#define MUX_DISABLE MUXEN = 1

void init_port(void)
{//Инициализируем порт. Выход РА.7(реле) вз\т как вход во избежание.
     PORTA = PORTA_DEFAULT_STATE;     //Выставляем значения по умолчанию
     DDRA = PORTA_DEFAULT_DIRECTION;     //назначаем направления в порту А
     PORTA = PORTA_DEFAULT_STATE;     //Выставляем значения по умолчанию еще раз, ибо механизм работы подробно не описан.
}

void init_timer(void)
{//Инициализация таймера
     GLINTD = 1;             //Выключаем все прерывания
     sum=0;
     TMR0L=0;
     TMR0H=0;
     T0IF = 0;
     T0STA = TIMER_CLK_PRESCALER << 1;     // Устанавливаем предделитель клока таймера 0

}
 void init(void)
{
      init_port();
      init_timer();
}


void start(void)
{//Начинаем работу
     T0CS = 1;                   //Подаем клок на таймер 0
     T0IF = 0;              //сбрасываем флаг прерывания таймера 0
     T0IE = 1;              //разрешаем прерывание от таймера 0
     GLINTD = 0;          //Разрешаем прерывания
}

void stop(void)
{//Останавливаем таймер
    init(); 
}

void relay_on(void)
{//Включаем реле
     DDRA7 =0;
     PORTA7 =1;
}

unsigned char read_switch(void)
{

     unsigned char i=0,temp=0,temp2=0; 
     MUX_ENABLE;//Включаем мультиплексоры
     temp = PORTA;             
     for (i=0;i<8;i++)
     { 
         clrwdt();
          temp &= A0_A3_MASK;
          temp += (i << 2);//инкрементируем адрес на мультиплексорах
          PORTA = temp;
          for (temp2 = 0; temp2 < MUX_DELAY; temp2++) nop();//Дадим время на переключение мультиплексора и входного каскада
          temp2 = PORTA;
          temp2 = ~temp2; //Забавно 533КП15 имеют такой ток утечки по входам что подтяжка к земле в 47кОм дает почти вольт на входе. Пришлось поменять логику на инверсную. 
                          //Надо попробовать взять другой мультиплексор посовременней с меньшим потреблением. Но пока что есть(
          temp2 &= TL_TH_MASK;
          if (temp2)
          {//Есть что-то на входе. Преобразуем данные с мультиплексоров в положение выключателя
               temp2 >>= 1;
               temp2 *= 8;
               temp2 += i;
               MUX_DISABLE;//Выключаем мультиплексоры
               return temp2; //возвращаем положение переключателя  
          }
     }
     MUX_DISABLE;//Выключаем мультиплексоры
     return TIME_DEFAULT;  //время срабатывания по умолчанию, если положение переключателя не определенно       
}

double calc_timer_events_num (unsigned char task)
{ 
/*
Вычисляем кол-во переполнений таймера Т0 для заданного промежутка времени
по формуле FC * (x * STEP + START)/ N, где x-заданное кол-во интервалов, STEP - продолжительность интервала,
START - минимальный интервал, FC - тактовая частота на входе таймера, N - размерность счетчика таймера
*/
      double temp3;
      temp3 = task;
      temp3 *= STEP;
      temp3 += START;
      temp3 *= NUMENATOR;
      temp3 -= ERROR;
      //Компилятор не дает делать выражения сложнее!
    return temp3; 
}
/******************/
void main(void)
{
double comp; 
int32 temp4;
init();
start();
clrwdt();
comp = calc_timer_events_num(read_switch());
clrwdt();
    while(1)
    {
            T0IE = 0; 
            temp4 = sum;
            T0IE = 1; 
            
        if(temp4>=comp)
        {
         relay_on();
         init_timer();
        } 
        clrwdt();    
    }
}


Вложения:
Комментарий к файлу: Схема
Реле времени программируемое.pdf [1.16 МБ]
23 скачивания
Вернуться к началу
 Заголовок сообщения: Re: Простой проект на 1886ВЕ7У1
СообщениеДобавлено: 2021-июл-21 16:53 
Не в сети
Support
Аватара пользователя

Зарегистрирован: 2018-авг-10 23:14
Сообщения: 441
Организация: АО «ПКК Миландр»
Откуда: Зеленоград
Hodunov84 писал(а): *
Здравствуйте!
Хочу поделится простеньким проектом на 1886ВЕ7. Возможно будет полезно тем кто осваивает контроллеры.
Устройство представляет собой программируемое реле времени на 16 интервалов. Код написан в IDE1886. Компилятор CC7A - demo.
Добавить: 
          1) Функцию защиты от сброса по WDT и питанию с использованием EEPROM для хранения состояния и прошедшего времени.
          2) Режим работы от RC цепи с функцией калибровки от генератора. Калибровочный коэфициент хранить в EEPROM
          3) Добавить авто расчет коэффициента деления предделителя таймера 0 для достижения наименьшей погрешности при максимально широком диапазоне интервалов
*/
#include <1886VE7.h> 

#pragma rambank 0
int32 sum;     // тут храним текущее кол-во переполнений таймера Т0

#include "int17xxx.h"
#pragma origin 0x8

interrupt iServer(void)
{
multi_interrupt_entry_and_save

 PERIPHERAL_service:
     nop();
 TMR0_service:
     T0IF = 0;
     sum++;
//     RA5=!RA5; //для теста

 T0CKI_service:
     nop();
 INT_service:
     nop();

    interrupt_exit_and_restore
}

#pragma codepage 1
#include "math32f.h" //Подключаем библиотеку для работы с плавающей запятой

#define CPUCLK 8000000.0 //Кварц или RC цепь
#define FC (CPUCLK/4.0)// Таймер получает CLK/4 это не указанно нигде кроме как на рисунке №20 стр. 54 даташита.
#define TIMER_SIZE 0xFFFF //16 разрядов
#define TIMER_CLK_PRESCALER 0 //степень двойки
#define T0_PRESCALER (1<<TIMER_CLK_PRESCALER)
#define NUMENATOR (FC/T0_PRESCALER/TIMER_SIZE) //количество прерываний от таймера 0 по переполнению в сек, нужно вещественное число для обеспечения точности в +/- 1 интервал переполнения таймера
#define ERROR 0.0 //Для компенсации времени запуска и ошибки от неточности RC цепи по данным с EEPROM (на будущее)

#define STEP 20.0 //шаг уставки сек
#define START 100.0 //Начало шакалы сек
#define INTERVAL_NUM 15 //Кол-во программируемых интервалов
#define TIME_DEFAULT INTERVAL_NUM //Интервал по умолчанию... нужно уточнить у специалистов какой взять!

#define TL_TH_MASK 0x03
#define A0_A3_MASK 0xE3

#define MUX_DELAY 5 //Задержка считывания сигнала с MUX после его переключения

#define PORTA_DEFAULT_STATE 0x43
#define PORTA_DEFAULT_DIRECTION 0x83

bit MUXEN		@ PORTA.6;

#define MUX_ENABLE MUXEN = 0
#define MUX_DISABLE MUXEN = 1

void init_port(void)
{//Инициализируем порт. Выход РА.7(реле) вз\т как вход во избежание.
     PORTA = PORTA_DEFAULT_STATE;     //Выставляем значения по умолчанию
     DDRA = PORTA_DEFAULT_DIRECTION;     //назначаем направления в порту А
     PORTA = PORTA_DEFAULT_STATE;     //Выставляем значения по умолчанию еще раз, ибо механизм работы подробно не описан.
}

void init_timer(void)
{//Инициализация таймера
     GLINTD = 1;             //Выключаем все прерывания
     sum=0;
     TMR0L=0;
     TMR0H=0;
     T0IF = 0;
     T0STA = TIMER_CLK_PRESCALER << 1;     // Устанавливаем предделитель клока таймера 0

}
 void init(void)
{
      init_port();
      init_timer();
}


void start(void)
{//Начинаем работу
     T0CS = 1;                   //Подаем клок на таймер 0
     T0IF = 0;              //сбрасываем флаг прерывания таймера 0
     T0IE = 1;              //разрешаем прерывание от таймера 0
     GLINTD = 0;          //Разрешаем прерывания
}

void stop(void)
{//Останавливаем таймер
    init(); 
}

void relay_on(void)
{//Включаем реле
     DDRA7 =0;
     PORTA7 =1;
}

unsigned char read_switch(void)
{

     unsigned char i=0,temp=0,temp2=0; 
     MUX_ENABLE;//Включаем мультиплексоры
     temp = PORTA;             
     for (i=0;i<8;i++)
     { 
         clrwdt();
          temp &= A0_A3_MASK;
          temp += (i << 2);//инкрементируем адрес на мультиплексорах
          PORTA = temp;
          for (temp2 = 0; temp2 < MUX_DELAY; temp2++) nop();//Дадим время на переключение мультиплексора и входного каскада
          temp2 = PORTA;
          temp2 = ~temp2; //Забавно 533КП15 имеют такой ток утечки по входам что подтяжка к земле в 47кОм дает почти вольт на входе. Пришлось поменять логику на инверсную. 
                          //Надо попробовать взять другой мультиплексор посовременней с меньшим потреблением. Но пока что есть(
          temp2 &= TL_TH_MASK;
          if (temp2)
          {//Есть что-то на входе. Преобразуем данные с мультиплексоров в положение выключателя
               temp2 >>= 1;
               temp2 *= 8;
               temp2 += i;
               MUX_DISABLE;//Выключаем мультиплексоры
               return temp2; //возвращаем положение переключателя  
          }
     }
     MUX_DISABLE;//Выключаем мультиплексоры
     return TIME_DEFAULT;  //время срабатывания по умолчанию, если положение переключателя не определенно       
}

double calc_timer_events_num (unsigned char task)
{ 
/*
Вычисляем кол-во переполнений таймера Т0 для заданного промежутка времени
по формуле FC * (x * STEP + START)/ N, где x-заданное кол-во интервалов, STEP - продолжительность интервала,
START - минимальный интервал, FC - тактовая частота на входе таймера, N - размерность счетчика таймера
*/
      double temp3;
      temp3 = task;
      temp3 *= STEP;
      temp3 += START;
      temp3 *= NUMENATOR;
      temp3 -= ERROR;
      //Компилятор не дает делать выражения сложнее!
    return temp3; 
}
/******************/
void main(void)
{
double comp; 
int32 temp4;
init();
start();
clrwdt();
comp = calc_timer_events_num(read_switch());
clrwdt();
    while(1)
    {
            T0IE = 0; 
            temp4 = sum;
            T0IE = 1; 
            
        if(temp4>=comp)
        {
         relay_on();
         init_timer();
        } 
        clrwdt();    
    }
}
Здравствуйте!

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

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

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
Показать сообщения за:  Поле сортировки  
Начать новую тему  Ответить на тему  [ 2 сообщения ] 

Часовой пояс: UTC+03:00


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость


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

Перейти: 

cron
Создано на основе phpBB® Forum Software © phpBB Limited
Русская поддержка phpBB