Регулированный ШИМ от ДУ

Все о микроконтроллерах: AVR, PIC, STM8, STM32, Arduino, Altera, Xilinx, все что угодно. Этот раздел для всего что клацает байтиками.
Аватара пользователя
eleutherius
Сообщения: 11

Сообщение eleutherius » 14 июн 2015, 11:13

Год назад разрабатывал устройство... Хочется довести это дело до конца. ТЗ:
1) Устройство должно управляться от ИК пульта ДУ, протокол RC5.
2) Устройство должно создавать несколько ШИМ каналов (от 4 - 12). Пользователь должен быть способен изменять ШИМ или переключать подпрограммы. Как контроллер выбрал ATmega 8, компилятор Codevision AVR.
Есть две программы которые как-то нужно объединить.
1) Программа ИК ДУ :

Код: Выделить всё

//Chip type : ATmega8
//AVR Core Clock frequency: 4.000000 MHz

#include <mega8.h>
#include <stdio.h>
#include <delay.h>

typedef unsigned char byte;
typedef unsigned int word;

byte evnt; //Счетчик событий
word pkv; //Тут хранятся принятые биты
bit start; //Первый бит

void keypress(byte toggle,byte address,byte command) {

 if (command == 1) {
 PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
};

//Здесь пишем код, для события

printf("KEY: %u,%u,%u\r",toggle,address,command);
}

void tmr_reset() {
TCCR0=0; //Выключаем счетчик
TCNT0=0; //Сбрасываем счетчик
evnt=0;
pkv=0;
}



interrupt [EXT_INT0] void ext_int0_isr(void) { //Внешнее прерывание
if (evnt==0) { //Первое событие
TCCR0=(1<<CS02) | (0<<CS01) | (0<<CS00); //Включаем счетчик 15,625КГц
start=PIND.2; //Записываем первый бит
}
if ((evnt&1)!=0&&TCNT0>18) evnt++; 
if (evnt>0&&(evnt&1)==0) {
if (evnt==2) {
if (start!=PIND.2) tmr_reset(); //Если первый бит не равен второму, заканчиваем обработку
start=!start; //Инвертируем бит
}else{
pkv<<=1; //Сдвигаем на бит вправо
pkv|=PIND.2^start; //Сохраняем принятый бит
}
}
if (TCCR0!=0) { //Если счетчик не выключен
if (evnt==26) keypress((pkv>>11)&1,(pkv>>6)&31,pkv&63);
evnt++; //Инкриминируем событие
TCNT0 = 0b00000000; //Сбрысываем счетчик
}
}

interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
tmr_reset(); //Если счетчик переполнен, выключаем и обнуляем его
}

void main(void) {
DDRC=(0<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (0<<DDC0);
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

DDRD=0;
PORTD= 0b00000010;
TIMSK =(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<TOIE0); //Прерывание для Счетчика 1
//Разрешаем внешнее прерывание, на любое изменение
GICR=0x40;
MCUCR=0x01;
GIFR=0x40;
tmr_reset();
//Настраиваем UART 19200 бод 8 бит
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0C;

//Пишем в терминал
putsf("TEST PHILIPS RC5:\r");
//Разрешаем прерывания
#asm("sei")
}


И еще программа программного ШИМ-а:

Код: Выделить всё

#include <mega8.h>
#include <delay.h>

/*блок дефайнов*****************************************************************************************/
#define RED PORTB.0
#define GREEN PORTB.1
#define BLUE PORTB.2
/***************************************************************************************************************/



/*объявляем прерменные*******************************************************************************/
unsigned char red=255,   green,     blue;       //переменные, для изменения скважности ШИМ в программе
unsigned char red_b,     green_b,   blue_b;     //переменные, для буферизации значений скважности ШИМ
unsigned char count;                            //переменная- счетчик вызовов обработчика прерываний
unsigned char temp=1;                           //переменная для работы алгоритма смены цветов
/****************************************************************************************************************/



/*обработчик прерывания********************************************************************************/
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
count++;
if (count == 0){                                //если счетчик переполнился и принял значение 0

        red_b   = red;                          //сохранием значения в буфер
        green_b = green;
        blue_b  = blue;

        RED   = 1;                               //выставляем ноги, отвечающие за ШИМ в логическую 1
        GREEN = 1;
        BLUE  = 1;

        }

if (red_b   == count) { RED   = 0;}             //по достижении заданной скважности выводим логический 0 в ножку МК
if (green_b == count) { GREEN = 0;}
if (blue_b  == count) { BLUE  = 0;}
}
/************************************************************************************************************************/



/*главная функция************************************************************************************************/
void main(void)
{

PORTB=0x08;                                     //конфигурируем порт
DDRB=0x07;

TCCR0=0x01;                                     //настраиваем таймер
TCNT0=0x00;

TIMSK=0x01;                                     //разрешаем генерацию прерывания по переполнению таймера T0

#asm("sei")                                     //глобально разрешаем прерывания


/*бесконечный цикл*******************************************************************************************/
while (1)
      {
        if (temp==1) {if (green < 255)   green += 1; else temp = 2;}
        if (temp==2) {if (red   >   0)   red   -= 1; else temp = 3;}
        if (temp==3) {if (blue  < 255)   blue  += 1; else temp = 4;}
        if (temp==4) {if (green >   0)   green -= 1; else temp = 5;}
        if (temp==5) {if (red   < 255)   red   += 1; else temp = 6;}
        if (temp==6) {if (blue  >   0)   blue  -= 1; else temp = 1;}

        delay_ms(2);

      };
}
/****************************************************************************************************************/



Проблема в том что программы используют одно прерывание "interrupt [TIM0_OVF]", Как бы можно было-бы изменить данное положение, чтобы оно все работало ? Перекинуть одну программку на прерывание другого таймера или есть какой-то другой способ решения?

Qic
Сообщения: 1007

Сообщение Qic » 14 июн 2015, 12:02

Даже не глядя в код - RC5 по таймеру принимается, и ШИМ по таймеру работает. Очевидно - два разных таймера нужно.
А глядя в ШИМ, я например 3 честных канала делал на меге8 вот как-то так:

Код: Выделить всё

   DDRB=0x0e;                            //OC1A,OC1B,OC2 - выходы
   TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);    //Конфигурация счетчика OC1A
   TCCR1B=(1<<CS10);                      //Конфигурация счетчика OC1B
   TCCR2=(1<<CS20)|(1<<COM21)|(1<<WGM20);       //Конфигурация счетчика OC2
   
   //Установка начальных значений счетчиков
   OCR1AL=0x00; //Выключен 0
   OCR1BL=0x00; //Выключен 0
   OCR2=0x00;   //Выключен 0

И всёже ШИМ каналов или ШИМ программ? Разница кардинальная. Если всётаки каналов то вот пожалуйста http://easyelectronics.ru/upravlenie-mn ... hinok.html Тоже делал, работает отлично.

demiurg1978
Сообщения: 1

Сообщение demiurg1978 » 07 янв 2016, 11:02

BAM. http://www.youtube.com/watch?v=AU1PVRk_G70 Могу помочь с вашим проектом.

Вернуться в «Микроконтроллеры и ПЛИС»



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

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