Поклонники продукции Microchip Technology Inc тусуются тут.
Ответить

Плафон освещения кабины на pic12f615

Сб июл 20, 2019 11:03:53

Задача состоит в том, чтобы при нажатии кнопки переключались режимы:
1) последовательность импульсов, где 1- 667 мкс, 0-1333 мкс
2) последовательность импульсов, где 1- 1333 мкс, 0-667 мкс
3) уровень 1
4) уровень 0
Но у меня получается, что горит либо пока зажата кнопка, и то по одному режиму, либо после отпускания кнопки горит еще секунды 3 и все, а нужно после нажатия чтоб горело до следующего нажатия с переключением. Свой код прилагаю. Помогите подправить, пожалуйста.
Код:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 8MHZ    // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000      // Declare crystal frequency to be 8MHZ (for delay functions)

void rezhim1() {
   GPIO2 = 1;
 __delay_us(667);
        GPIO2 = 0;
        __delay_us(1333);
}
void rezhim2() {
   GPIO2 = 1;
 __delay_us(1333);
        GPIO2 = 0;
        __delay_us(667);
}
void rezhim3() {
   GPIO2 = 1;
}
void rezhim4() {
        GPIO2 = 0;
}

int main(int argc, char** argv) {

{   
   ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
   ADCON0 = 0x00;       // Shut off the A/D Converter
   TRISIO0 = 1;       // GP3 input, rest all output
    TRISIO2 = 0;
   GPIO   = 0x00;       // Make all pins 0
   while(1)
   {
       if (GPIO0 == 1)
        {
        GPIO2 = 0;
        }  else
        {
        rezhim1();   
        }
        if (GPIO0 == 1)
        {
           GPIO2 = 0;
        } else
        {
        rezhim2();
        }
        if (GPIO0 == 1)
        {
           GPIO2 = 0;
        } else
        {
        rezhim3();
        }
        if (GPIO0 == 1)
        {
           GPIO2 = 0;
        } else
        {
        rezhim4();
        }
    }       
    }   
}

Re: Плафон освещения кабины на pic12f615

Сб июл 20, 2019 12:42:49

У Вас в корне всё неправильно. Под Вашу задачу "подправить" не получится, нужно полностью переписывать весь код.
Формирование импульсов сделайте на прерывании таймера. Периоды у Вас кратны одному значению.
Обработку кнопок можно тоже туда же запихнуть, времени между вызовами должно хватить на всё. В крайнем случае, сделаете обработку и переключение режимов в основном цикле.

Re: Плафон освещения кабины на pic12f615

Сб июл 20, 2019 12:46:50

Аlex, а мини пример можно такого? а то я пока не особо понимаю как это реализовать

Re: Плафон освещения кабины на pic12f615

Сб июл 20, 2019 12:54:17

Посмотрел даташит на ваш камушек, там даже есть модуль PWM. Проблем решить Вашу задачу нет вообще никаких...
Курим раздел этого модуля в даташите...
Если PWM будет сложно, то изучаем таймеры (в частности TMR2). Его описание есть также в ДШ.

Re: Плафон освещения кабины на pic12f615

Вс июл 21, 2019 06:42:11

я пока не особо понимаю как это реализовать

Для начала смените сам подход к решению.
Если Вы хотите перебирать неких 4 режима (не важно чего), то создайте автомат реализующий эти 4 режима. По сути - программный счетчик по нажатию кнопки. И учтите, что у кнопки есть дребезг.
Дребезг удаляется с помощью чтения кнопки с интервалом бОльшим, чем время дребезга. Даже если кнопка посредственного качества, то 20...30 мс перекроют ее дребезг. На выходе такой защиты будет состояние кнопки без дребезга, но еще не сам счетчик режимов. Далее нужно ловить СОБЫТИЕ (а не состояние) нажатия. То есть анализировать ПРЕДЫДУЩЕЕ и ТЕКУЩЕЕ состояние кнопки. И при их сочетании соответствующем событию нажатия (01 или 10 - зависит от схемотехники кнопки) можно инкрементировать счетчик режимов. Далее нужно этот счетчик ограничить в счете или анализе (у Вас 4 режима, значит можно просто наложить маску &0b00000011 при анализе режима, но не ограничивать счет).
Ну и анализируя номер режима, переключать этот самый режим по if, а лучше по case, загружая в PWM необходимые параметры.
ЗЫ. По поводу реализации. И таки да, прерывания по таймеру для анализа кнопки, а не дурацкий блокирующий delay(), Вам помогут...

Re: Плафон освещения кабины на pic12f615

Вс июл 21, 2019 10:34:44

КРАМ, если с дребезжанием мне еще понятно, то вот на ловку события хотелось бы увидеть хотя бы несколько строк кода примера, ибо мои поиски не увенчались успехом, это вам легко на словах, а мне как не профи в этом не очень, поэтому и прошу хоть какой-то мини пример

Re: Плафон освещения кабины на pic12f615

Вс июл 21, 2019 11:21:36

вот на ловку события хотелось бы увидеть

Заводим некую переменную - состояние кнопки (назовем ее statButton, например):
В нее вдвигаем (левый сдвиг) текущее бездребезговое значение кнопки и маскируем два младших разряда этой переменной:
Код:

uint8_t countMode=0;
uint8_t reqChangeMode=0;

// в обработчике прерываний по таймеру - чтение кнопки GP0
static uint8_t statButton;

if (GP0) {
     statButton=((statButton<<1)|1)&0x3;
            } else  {
     statButton=((statButton<<1)|0)&0x3;
}
if (statButton == 0b10) {
reqChangeMode=1;
}



// в main-e
if  (reqChangeMode) {
reqChangeMode=0;
countMode=(countMode+1)&0x3;
switch (countMode)
       case  0: настраиваем режим 0
       case  1: настраиваем режим 1
       case  2: настраиваем режим 2
       case  3: настраиваем режим 3
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 07:40:35

КРАМ, в итоге теперь мигает всегда при не включенной кнопке, можете глянуть, что не так?
Код:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 4MHZ    // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000      // Declare crystal frequency to be 8MHZ (for delay functions)

int statButton = 0b11;
int countMode = 0;
int reqChangeMode = 0;
unsigned char ncnt = 0;

void InitTimer2(void)
{   
  TOUTPS3 = 1; //Prescaler Out 10
  TOUTPS2 = 0;
  TOUTPS1 = 0;
  TOUTPS0 = 1;
  T2CKPS0 = 1;//Postcaler In 16
  T2CKPS1 = 1;
  PR2 = 0xFF; //TIMER2 Period 255
  TMR2IE = 1;
  TMR2ON = 1;
}

void interrupt isr(void)
{
  if(TMR2IE&&TMR2IF)
  {
    TMR2IF = 0;
    ncnt++;
    if(ncnt > 25)
    {
      ncnt = 0;
    }
  }
  if (GP0)
  {
    statButton = ((statButton<<1)|1)&0x3;
    } else
    {
    statButton = ((statButton<<1)|0)&0x3;
    }
    if (statButton == 0b10)
    {
    countMode = (countMode+1)&0x3;
    reqChangeMode = 1;
    }
}

unsigned char CheckButton(void)

{
  unsigned char result = 0;
  unsigned int butcount = 0;
  while(GP0)
  {
    if(butcount < 10000)
    {
      butcount++;
    }
    else
    {
      result = 1;
      break;
    }
  }
  return result;
}

int main(int argc, char** argv) {

{   
   ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
   ADCON0 = 0x00;       // Shut off the A/D Converter
   TRISIO0 = 1;       // GP3 input, rest all output
    TRISIO2 = 0;
   GPIO   = 0x00;       // Make all pins 0
    CCP1IE = 1;
    CCP1CON = 0x0F; //PWM mode CCP
    InitTimer2();
   while(1)
   {
        if (CheckButton())
        {
        }
    if (reqChangeMode) {
    reqChangeMode = 0;
    switch (countMode) {
    case 0:
    {
        T2CON = 0b00000111;
        CCPR1L = 0b00101001;
        CCP1CON = 0b00101100;
    }
    case 1:
    {
       T2CON = 0b00000111;
       CCPR1L = 0b01010011;
       CCP1CON = 0b00011100;
    }
    case 2:
    {
        T2CON = 0b00000111;
        CCPR1L = 0b01111100;
        CCP1CON = 0b00111100;
    }
    case 3:
    {
        T2CON = 0b00000111;
        CCPR1L = 0b00000000;
        CCP1CON = 0b00001100;
    }       
    }   
    }
}
}
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:07:33

Какая то каша из того, что предложил я и странного кода...
Объясните к чему в обработчике какой то счетчик и что за CheckButton?
И почему в комментариях упоминается GP3 как пин с кнопкой, а Вы оставили GP0?
Или давайте схему.
Совершенно непонятно какая частота у МК.

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:21:41

КРАМ, на схеме там GP0 выход, просто не стирала комменты, схему прикрепила, частота мк 4 МГц, внутренний генератор

Добавлено after 1 minute 57 seconds:
https://pp.userapi.com/c855232/v8552327 ... K7bOnw.jpg

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:28:13

В прерывании проверка пина должна находится ВНУТРИ обработчика таймера (T2IE&&T2IF), а не снаружи.
Не надо выносить переменные используемые в прерывании наружу. Достаточно сделать их static.
И уберите из кода все, что не относится к алгоритму.

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:38:21

КРАМ, так? все равно не идет, от кнопки 0 должен поступать, вроде и поменяла и все равно
Код:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 4MHZ    // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000      // Declare crystal frequency to be 8MHZ (for delay functions)


//unsigned char ncnt = 0;

void InitTimer2(void)
{   
  TOUTPS3 = 1; //Prescaler Out 10
  TOUTPS2 = 0;
  TOUTPS1 = 0;
  TOUTPS0 = 1;
  T2CKPS0 = 1;//Postcaler In 16
  T2CKPS1 = 1;
  PR2 = 0b01111100;
  TMR2IE = 1;
  TMR2ON = 1;
}

void interrupt isr(void)
{
    static int statButton = 0b11;
static int countMode = 0;
static int reqChangeMode = 0;
  if(TMR2IE&&TMR2IF)
  {
    TMR2IF = 0;
    if (GP0)
  {
    statButton = ((statButton << 1)|0)&0x3;
    } else
    {
    statButton = ((statButton << 1)|1)&0x3;
    }
    if (statButton == 0b01)
    {
    countMode = (countMode + 1)&0x3;
    reqChangeMode = 1;
    }
  }
 
}

void setDuty(unsigned int duty) {
    CCPR1L = duty >> 2;
    CCP1CON &= 0xCF;
    CCP1CON |= (0x30 & (duty << 4));
}

int main(int argc, char** argv) {

{   
    static int statButton = 0b11;
static int countMode = 0;
static int reqChangeMode = 0;
   ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
   ADCON0 = 0x00;       // Shut off the A/D Converter
   TRISIO0 = 1;       // GP3 input, rest all output
    TRISIO2 = 0;
   GPIO   = 0x00;       // Make all pins 0
   CCP1IE = 1;
    InitTimer2();
   while(1)
   {
    if (reqChangeMode) {
    reqChangeMode = 0;
    switch (statButton) {
    case 0:
    {
       //setDuty(33.35);
       T2CON = 0b00000111;
       CCPR1L = 0b00101001;
       CCP1CON = 0b00101100;
    }
    case 1:
    {
        //setDuty(66.65);
       T2CON = 0b00000111;
       CCPR1L = 0b01010011;
       CCP1CON = 0b00011100;
    }
    case 2:
    {
        //setDuty(100);
        T2CON = 0b00000111;
        CCPR1L = 0b01111100;
        CCP1CON = 0b00111100;
    }
    case 3:
    {
        //setDuty(0);
        T2CON = 0b00000111;
        CCPR1L = 0b00000000;
        CCP1CON = 0b00001100;
    }       
    }   
    }
}
}
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:56:08

Внимательно посмотрите что было в моем коде static. И static не инициализируют, иначе в нем нет никакого смысла.
static - это локальная переменная не изменяющая своего значения между выходом и следующим входом в функцию.
Только statButton локальная статик переменная. Остальные - глобальные.
И не нужно их делать 16 разрядными. Все переменные алгоритма unsigned char или uint8_t

Добавлено after 6 minutes 3 seconds:
ЗЫ. Кстати, а Вы работаете в железе или в симуляторе?

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 09:56:57

КРАМ, а можно уже сразу на коде показать? ибо и так не идет
Код:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdint.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 4MHZ    // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000      // Declare crystal frequency to be 8MHZ (for delay functions)

uint8_t countMode=0;
uint8_t reqChangeMode=0;

void InitTimer2(void)
{   
  TOUTPS3 = 1; //Prescaler Out 10
  TOUTPS2 = 0;
  TOUTPS1 = 0;
  TOUTPS0 = 1;
  T2CKPS0 = 1;//Postcaler In 16
  T2CKPS1 = 1;
  PR2 = 0b01111100;
  TMR2IE = 1;
  TMR2ON = 1;
}

void interrupt isr(void)
{
uint8_t statButton=0b11; 
  if(TMR2IE&&TMR2IF)
  {
    if (GP0)
  {
    statButton = ((statButton << 1)|0)&0x3;
    } else
    {
    statButton = ((statButton << 1)|1)&0x3;
    }
    if (statButton == 0b01)
    {
    countMode = (countMode + 1)&0x3;
    reqChangeMode = 1;
    }
    TMR2IF = 0;
  }
}

int main(int argc, char** argv) {

{   
uint8_t statButton=0b11;
   ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
   ADCON0 = 0x00;       // Shut off the A/D Converter
   TRISIO0 = 1;       // GP3 input, rest all output
    TRISIO2 = 0;
   GPIO = 0x00;       // Make all pins 0
    CCP1IE = 1;
    InitTimer2();
   while(1)
   {
    if (reqChangeMode) {
    reqChangeMode = 0;
    switch (statButton) {
    case 0:
    {
       T2CON = 0b00000111;
       CCPR1L = 0b00101001;
       CCP1CON = 0b00101100;
    }
    case 1:
    {
       T2CON = 0b00000111;
       CCPR1L = 0b01010011;
       CCP1CON = 0b00011100;
    }
    case 2:
    {
        T2CON = 0b00000111;
        CCPR1L = 0b01111100;
        CCP1CON = 0b00111100;
    }
    case 3:
    {
        T2CON = 0b00000111;
        CCPR1L = 0b00000000;
        CCP1CON = 0b00001100;
    }       
    }   
    }
}
}
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 10:10:26

Bondosha, в MPLAB имеется стимулятор. вы бы там попробовали свой код.

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 10:25:00

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdint.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 4MHZ // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000 // Declare crystal frequency to be 8MHZ (for delay functions)

uint8_t countMode=0;
uint8_t reqChangeMode=0;

void InitTimer2(void)
{
TOUTPS3 = 1; //Prescaler Out 10
TOUTPS2 = 0;
TOUTPS1 = 0;
TOUTPS0 = 1;
T2CKPS0 = 1;//Postcaler In 16
T2CKPS1 = 1;
PR2 = 0b01111100;
TMR2IE = 1;
TMR2ON = 1;
}

void interrupt isr(void)
{
static uint8_t statButton=0b11;
if(TMR2IE&&TMR2IF)
{
if (GP0)
{
statButton = ((statButton << 1)|0)&0x3;
} else
{
statButton = ((statButton << 1)|1)&0x3;
}
if (statButton == 0b01)
{
countMode = (countMode + 1)&0x3;
reqChangeMode = 1;
}
TMR2IF = 0;
}
}

int main(int argc, char** argv) {

{
uint8_t statButton=0b11;
ANSEL = 0x00; // Set ports as digital I/O, not analog input
ADCON0 = 0x00; // Shut off the A/D Converter
TRISIO0 = 1; // GP3 input, rest all output
TRISIO2 = 0;
GPIO = 0x00; // Make all pins 0
CCP1IE = 1;
InitTimer2();
while(1)
{
if (reqChangeMode) {
reqChangeMode = 0;
switch (statMode) {
case 0:
{
T2CON = 0b00000111; // общая часть - вынести в инициализацию
CCPR1L = 0b00101001;
CCP1CON = 0b00101100;
}
case 1:
{
T2CON = 0b00000111;
CCPR1L = 0b01010011;
CCP1CON = 0b00011100;
}
case 2:
{
T2CON = 0b00000111;
CCPR1L = 0b01111100;
CCP1CON = 0b00111100;
}
case 3:
{
T2CON = 0b00000111;
CCPR1L = 0b00000000;
CCP1CON = 0b00001100;
}
}
}
}
}
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 10:44:20

КРАМ, даже так не хочет, никак не реагирует на кнопку

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 11:08:33

У Вас глобальные и периферийные прерывания были запрещены, а прерывания от ЩИМа зачем то разрешены. Добавил исправления

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdint.h>

#pragma config FOSC = INTOSCCLK
#pragma config IOSCFS = 4MHZ // Internal Oscillator Frequency Select bit (8 MHz)
#define _XTAL_FREQ 16000000 // Declare crystal frequency to be 8MHZ (for delay functions)

uint8_t countMode=0;
uint8_t reqChangeMode=0;

void InitTimer2(void)
{
TOUTPS3 = 1; //Prescaler Out 10
TOUTPS2 = 0;
TOUTPS1 = 0;
TOUTPS0 = 1;
T2CKPS0 = 1;//Postcaler In 16
T2CKPS1 = 1;
PR2 = 0b01111100;
TMR2IE = 1;
TMR2ON = 1;
}

void interrupt isr(void)
{
static uint8_t statButton=0b11;
if(TMR2IE&&TMR2IF)
{
if (GP0)
{
statButton = ((statButton << 1)|0)&0x3;
} else
{
statButton = ((statButton << 1)|1)&0x3;
}
if (statButton == 0b01)
{
countMode = (countMode + 1)&0x3;
reqChangeMode = 1;
}
TMR2IF = 0;
}
}

int main(int argc, char** argv) {

{
uint8_t statButton=0b11;
ANSEL = 0x00; // Set ports as digital I/O, not analog input
ADCON0 = 0x00; // Shut off the A/D Converter
TRISIO0 = 1; // GP3 input, rest all output
TRISIO2 = 0;
GPIO = 0x00; // Make all pins 0
CCP1IE = 1;
InitTimer2();
PEIE=1;
GIE=1;

while(1)
{
if (reqChangeMode) {
reqChangeMode = 0;
switch (statMode) {
case 0:
{
T2CON = 0b00000111; // общая часть - вынести в инициализацию
CCPR1L = 0b00101001;
CCP1CON = 0b00101100;
}
case 1:
{
T2CON = 0b00000111;
CCPR1L = 0b01010011;
CCP1CON = 0b00011100;
}
case 2:
{
T2CON = 0b00000111;
CCPR1L = 0b01111100;
CCP1CON = 0b00111100;
}
case 3:
{
T2CON = 0b00000111;
CCPR1L = 0b00000000;
CCP1CON = 0b00001100;
}
}
}
}
}
}

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 11:13:00

КРАМ, все то же самое

Re: Плафон освещения кабины на pic12f615

Пн июл 22, 2019 11:22:22

давайте Ваш текущий код
Ответить