ЗЫ: Использую настройки тактирования камня по дефалту. т.е 9,6МГц/CKDIV = 1,2МГц... Таймер тикает на 1,200000/8 = 150 000.
Схема:
- Вложения
-
- Project.rar
- (57.94 КБ) 149 скачиваний
Вроде все настроил, в протеусе пашет... Только проверил. Настроил таймер по переполнению CTC Mode, в OCRA записал 95 - это дало мне 1 мс. По поводу пари часов, разве не получится инкрементируя переменную накопить нужное число и выполнить действие?СКАЗОЧНИК писал(а):А как 8 битным таймером считать несколько часов???![]()
Еще, лень распаковывать проект, тем более, у меня нет КодеВижена, зато есть АВРСтудия, в которую по любому ваш код не смогу портировать... Поэтому, если не сложно, то выложите свой код в теги под спойлер.
Код: Выделить всё
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=Out Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB5) | (0<<DDB4) | (1<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=T Bit4=P Bit3=1 Bit2=T Bit1=P Bit0=T
PORTB=(0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);
// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 150,000 kHz
// Mode: CTC top=OCR0A
// Timer Period: 1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x95;
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
#asm("sei")
Код: Выделить всё
//RC intrrnal Clock 9,6Mhz
#include <tiny13.h>
#include <delay.h>
#define out PORTB.3 // Лампа;
#define pir PINB.0 // PIR-датчик;
#define key PINB.1 // Выключатель;
#define debounce 10000
#define pir_delay 30
#define lamp_off_time 60000
#define off_time 50
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
}
volatile unsigned int on=0, tic_tac=0, tic_down=0; // Счетчик;
volatile unsigned int outdoor_sensor; // Датчик света;
volatile unsigned int sensivity; // Регулировка чувствительности;
volatile unsigned char key_on_flag = 0; // состояние выключателя 0 - выключен;
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
static unsigned char counter = 15; // Счетчик для сетевого віключателя;
TCNT0=0x00;
if(key)
{
// считали 1 - похоже, выключен;
// проверяем сколько времени прошло;
if(counter)
{
// время не вышло;
counter --;
}
else
{
// прошло 15 миллисекунд выключатель выключен
key_on_flag = 0;
counter = 15; // устанавливаем счётчик заново
}
}
else
{
// считали 0 - включён
key_on_flag = 1;
counter = 20; // устанавливаем счётчик заново
}
if (key_on_flag) // Запуск таймера включения кнопки (антидребезг);
tic_tac++;
else tic_tac=0;
if (!pir && key_on_flag==0){ // Задержка на включение, антидребезг ПИР дачика;
on++;
}
else
{
on=0;
//TCNT0=0;
}
}
void adc_read (void) // Функция считывания значения из АЦП. АЦП 8бит;
{
outdoor_sensor=adc_data[1]; // Значение 1 канала, PORTB2 ;
sensivity=adc_data[0]; // Значение 2 канала читаем из массива сканированных каналов АЦП, PORTB4;
}
void main(void)
{
unsigned char key_on = 0; // состояние выключателя
#include <init_PIR.c>
// Обнуляю порты;
out=0;
// Global enable interrupts
for(;;)
{
// считываем состояние выключателя;
#asm("cli") // Запрещаем глобальные прерывания;
key_on = key_on_flag;
#asm("sei") // Разрешаем глобальніе прерівания;
if (key_on==1 && tic_tac>=debounce) // Приоритет включения по клавише;
{
out=1;
while (key_on==1 && tic_tac>=lamp_off_time)
{
out=0;
}
}
else
{
adc_read (); //Функция чтения значения из АЦП (0-255);
if (!pir&&on>=pir_delay&&outdoor_sensor>=sensivity) // Пир сработал, выключатель отключен, фотодатчик сработал;
out = 1; // Порт включен;
// else if (pir||((outdoor_sensor<=sensivity)||outdoor_sensor==0)&& tic_down>=off_time)
// out = 0;
else
out = 0; // Порт выключен;
}
}
}Код: Выделить всё
clr temp
out TCCR0A, temp ; Нормальный режим счета (выводы отключены)
out TCNT0, temp ; Очищаем счетный регистр
ldi temp, (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(1<<CS00) ; Делитель 1024
out TCCR0B, temp
ldi temp, (0<<OCIE0B)|(0<<OCIE0A)|(1<<TOIE0) ; Разрешаем прерывание по переполнению
out TIMSK0, tempКод: Выделить всё
ldi temp, (0<<REFS0)|(1<<ADLAR)|(1<<MUX1)|(0<<MUX0) ; АЦП: опорное 5 В питания; сдвиг влево результата; вывод для считывания РВ4
out ADMUX, temp
ldi temp, (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA, temp ; АЦП: запуск; постоянные преобразования; прерывания; прескалер/128
ldi temp, (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0) ; АЦП: свободный запуск/ непрерывный режим
out ADCSRB, tempКод: Выделить всё
// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (1<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
Опять взялись за старое? Сделайте как файле проектаJman писал(а):Код: Выделить всё
// ADC Auto Trigger Source: Free Running
Код: Выделить всё
// ADC Auto Trigger Source: Timer0 Compare Match AПочему? Очень даже нормальный режим, когда надо делать очень много отсчётов за короткое время. АЦП перезапускает сам себя. Остаётся только считывать результат по прерыванию. Короче цикла не придумаешь.Jman писал(а):free running не очень хорошая идея
Код: Выделить всё
volatile unsigned long int overflow_time = 3600000; // 1 час...
if (key_on_flag==1) // Запуск таймера включения кнопки (антидребезг);
{
tic_tac++;
if (i==0 || i<overflow_time) {i++;}
}
else { tic_tac=0; i=0; }
Код: Выделить всё
if (key_on==1 && tic_tac>=debounce) // Приоритет включения по клавише;
{
out=1;
while (key_on==1 && i>=overflow_time)//lamp_off_time)
{
out=0;
}
if (key_on==0)
{
out=0;
}
}
Код: Выделить всё
volatile unsigned long int overflow_time = 60000; ой нет... Видимо до 65535 считает...Барсик писал(а):А переменная i у Вас тоже типа unsigned long int ?
Код: Выделить всё
volatile unsigned int i=0Код: Выделить всё
if (key_on_flag==1) // Запуск таймера включения кнопки (антидребезг);
{
tic_tac++;
m_sec++;
if (m_sec==999)
{
m_sec=0;
sec++;
if (sec==59)
{
sec=0;
minutes++;
if (minutes==59)
{
minutes=0;
hours++;
if (hours == 5)
{
hours=0;
}
}
}
}
}
else { tic_tac=0; m_sec=0; }Код: Выделить всё
/*
* pir_control.c
* PORTB3 // Bulb out, log 1;
* PINB0 // PIR-sensor, zero active level;
* PINB1 // Light switch, zero active level;
*/
//PINB &_BV(PINB0)
//(PINB &_BV(PINB1)
//PORTB &= ~_BV(1<<3)
#ifndef F_CPU
#define F_CPU 9600000L
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#define OUT PORTB
//#define PIR (PINB &_BV(PINB0))
//#define KEY (PINB &_BV(PINB1))
#define DEBOUNCE 2000
#define PIRDELAY 3000
#define PHOTOOFFSET 5000
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
//Global varibles;
volatile unsigned int adcScanningData[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
// Counters;
volatile unsigned int on=0, timeCounter=0, timeCounterDown=0;
volatile unsigned char photoSeensor;
volatile unsigned char sensivity;
// switch flag;
volatile unsigned char keyFlag = 0;
volatile unsigned int milliSeconds = 0, seconds = 0, minutes=0, hours=0;
// Prototype of functions;
//peripherial initialisation;
void init (void);
// ADC data read function;
void adcInputsread (void);
//main logic function;
void mainLogic (void);
// Free running ADC interrupt;
ISR(ADC_vect)
{
static unsigned char input_index=0;
// Read the AD conversion result
adcScanningData[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
}
// Timer0 compare interrupt;
ISR (TIM0_COMPA_vect)
{
// Counter for light switch;
static unsigned char acNetCounter = 15;
// TCNT0=0x00;
if((PINB &_BV(PINB1))==1)
{
// Read 1 state - switch is active;
// Time checking;
if(acNetCounter)
{
// time is not run;
acNetCounter --;
}
else
{
// 15 mseconds switch is on;
keyFlag = 0;
// set the counter again;
acNetCounter = 15;
}
}
else
{
// Read 0 - Switch is on;
keyFlag = 1;
// set the counter again;
acNetCounter = 15;
}
// Start with switch / debounnce;
if (keyFlag==1)
{
timeCounter++;
if (timeCounter>=DEBOUNCE)
{
timeCounter = DEBOUNCE;
timeCounter++;
if (milliSeconds==999)
{
milliSeconds=0;
seconds++;
if (seconds==59)
{
seconds=0;
minutes++;
if (minutes==59)
{
minutes=0;
hours++;
if (hours > 5)
{
hours=7;
}
}
}
}
}
}
else
{
timeCounter=0; milliSeconds=0; seconds = 0, minutes=0, hours=0;
}
// Switch on delay and Pir sensor debounce
if ((PINB &_BV(PINB0)==0) && (keyFlag==0)&&(photoSeensor>=sensivity))
{
on++;
}
else
{
on=0;
//TCNT0=0;
}
if ((PINB &_BV(PINB0)==0) && (photoSeensor<sensivity) && (PORTB|=(1<<3)))
timeCounterDown++;
else timeCounterDown = 0;
TCNT0=0x00;
}
int main(void)
{
init();
PORTB &= ~(1<<3);
// Main programm
while (1)
{
// ADC read function(10bit);
adcInputsread();
// Main logic function;
mainLogic();
}
}
// Initialisation microcontroller and peripherals;
void init (void)
{
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=Out Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB5) | (0<<DDB4) | (1<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=T Bit4=P Bit3=1 Bit2=T Bit1=P Bit0=T
PORTB=(0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);
// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 150,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x95;
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
sei ();
}
}
void adcInputsread (void)
{
// first channel value, PORTB2 ;
photoSeensor=adcScanningData[0];
// second channel value, PORTB4;
sensivity=adcScanningData[1];
}
void mainLogic (void)
{
// switch state
unsigned char switchOn;
// Forbid global interrupts;
cli ();
switchOn = keyFlag;
// Allow global interrupts;
sei ();
// AC switch priority;
if ((switchOn==1) && (timeCounter>=DEBOUNCE) && (hours<5))
{
PORTB |=(1<<3);
}
// PIR=0,Switch=1
if ((PINB &_BV(PINB0)==0)&&(photoSeensor>=sensivity)&&(on>=PIRDELAY))
{
// Out is log 1;
PORTB |=(1<<3);
}
else if ((PINB &_BV(PINB0)==0)&&(!switchOn||switchOn)&&(photoSeensor>=sensivity)&&(PORTB |=(1<<3)))
{
PORTB |=(1<<3);
}
if ((PINB &_BV(PINB0)==0) && (photoSeensor<sensivity) && (PORTB |=(1<<3))&& timeCounter>PHOTOOFFSET)
{
PORTB &=~(1<<3);
}
else if (PINB &_BV(PINB0)==1)
{
PORTB &=~(1<<3);
}
}
Код: Выделить всё
DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
Код: Выделить всё
#define BULB 3
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
volatile unsigned int adcScanningData[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
volatile char photoSeensor;
volatile char sensivity;
ISR(ADC_vect)
{
static unsigned char input_index=0;
// Read the AD conversion result
adcScanningData[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
}
Код: Выделить всё
void adcInputsread (void)
{
// first channel value, PORTB2 ;
photoSeensor=adcScanningData[1];
// second channel value, PORTB4;
sensivity=adcScanningData[0];
}
Код: Выделить всё
if (photoSeensor>=sensivity)
{
// Out is log 1;
PORTB |=(1<<BULB);
}
else if(photoSeensor<sensivity) PORTB &=~(1<<BULB);