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]", Как бы можно было-бы изменить данное положение, чтобы оно все работало ? Перекинуть одну программку на прерывание другого таймера или есть какой-то другой способ решения?