Ср ноя 08, 2017 06:24:36
uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag)
{
cli();
uint8_t OutFlag=0; //Переменная отвечает за RETURN f().
TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС
if (TIMER.Channel[Number].FlagTimersON==0) //Условия для захвата времени вызова функции и установки флага работы
{
TIMER.Channel[Number].TimeCountingON=TIMER.MS;
TIMER.Channel[Number].FlagTimersON=1;
}
uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON;
if ((TimerToStart >= TimeVar)&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar)) //Если время до старта == TimeVar, то OutFlag=1 и обнуляем Флаг работы.
{
OutFlag=1;
TIMER.Channel[Number].FlagTimersON=0;
TIMER.TimeCurrent=0;
TIMER.Channel[Number].TimeCountingON=0;
TimerToStart=0;
}
else
{
OutFlag=CurrentFlag;
if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar))
{
TIMER.MS=0;
TIMER.Channel[Number].TimeCountingON=0;
}
}
sei();
return OutFlag;
}
Ср ноя 08, 2017 06:52:50
Это происходит потому что условие проверок надо делать в прерывании ISR (TIMER0_OVF_vect). Тогда условие будет контролировать каждый тик таймера.7seg писал(а):Столкнулся только с одной проблемой при испытаниях кода переменная TIMER.MS была == uint16_t.
Если зафиксируем время допустим в 65530 TIMER.MS а TimeVar установим больше 5 то TIMER.MS обнулялся раньше чем выполниться условия (TimerToSTOP >= TimeVar) и соответственно происходил сбой в работе.
ISR (TIMER0_OVF_vect)
{
uint8_t Number=0;
TCNT0=0x83; //значение для T0_0VF переполнения 1 раз в MS
TIMER.MS++; //Подсчет MS
for (Number=0;Number<AMOUNT_TIMERS;Number++) {
if ((TIMER.Channel[Number].TimeCountingON == TIMER.MS) && (TIMER.Channel[Number].FlagTimersOFF==0)) {
TIMER.Channel[Number].FlagTimersON = 1;
}
if ((TIMER.Channel[Number].TimeCountingOFF == TIMER.MS) && (TIMER.Channel[Number].FlagTimersON==1)) {
TIMER.Channel[Number].FlagTimersOFF = 1;
TIMER.Channel[Number].FlagTimersON = 0;
}
}
}
if (TIMER.Channel[0].FlagTimersON == 1) {
PORTC |= (1<<1);
} else PORTC &= ~(1<<1);
if (TIMER.Channel[1].FlagTimersON == 1) {
PORTC |= (1<<2);
} else PORTC &= ~(1<<2);
if (TIMER.Channel[2].FlagTimersON == 1) {
PORTC |= (1<<3);
} else PORTC &= ~(1<<3);
Ср ноя 08, 2017 08:58:57
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
void Algoritm()
{
if (R01TOP==0)
{
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
}
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
}
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_MISO PB4
#define SPI_MOSI PB3
#define SPI_SCK PB5
#define SPI_SS PB2
struct UnionBits
{
unsigned DO0: 1;
unsigned DO1: 1;
unsigned DO2: 1;
unsigned DO3: 1;
unsigned DO4: 1;
unsigned DO5: 1;
unsigned DO6: 1;
unsigned DO7: 1;
};
union Byte {
uint8_t ByteRegister;
struct UnionBits Register;
};
union Byte OneOUT;
union Byte TwoOUT;
union Byte ThreeOUT;
union Byte OneIN;
union Byte TwoIN;
union Byte ThreeIN;
union Byte FourIN;
union Byte FifthIN;
#define AMOUNT_TIMERS 6 //Количество используемых таймеров
typedef struct
{
uint8_t FlagTimersON; //Флаг работы таймера
uint8_t FlagTimersOFF;
volatile uint32_t TimeCountingON; //Переменная фиксирующая время старта
volatile uint32_t TimeCountingOFF;
}TimerStruct;
typedef struct
{
TimerStruct Channel[AMOUNT_TIMERS];
volatile uint32_t MS;
volatile uint32_t TimeCurrent; //Текущие время
}SoftTimers;
SoftTimers TIMER;
/*Функция инициализации таймеров (установка всех значений в 0 )*/
void InitTimers()
{
TIMER.TimeCurrent=0;
TIMER.MS=0;
for(uint8_t i=0;i<AMOUNT_TIMERS;i++)
{
TIMER.Channel[i].FlagTimersON=0;
TIMER.Channel[i].FlagTimersOFF=0;
TIMER.Channel[i].TimeCountingON=0;
}
}
#define MAX_UINT32 4294967295UL
ISR (TIMER0_OVF_vect)
{
TCNT0=131; //значение для T0_0VF переполнения 1 раз в MS
TIMER.MS++; //Подсчет MS
if (TIMER.MS == MAX_UINT32)
{
TIMER.MS=0;
}
}
/*Функция вернет TRUE через время TimeVar,Иначе возвращает CurrentFlag */
uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag)
{
cli();
uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f().
TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС
if (TIMER.Channel[Number].FlagTimersON==0) //Условия для захвата времени вызова функции, и установки флага работы
{
TIMER.Channel[Number].TimeCountingON=TIMER.MS;
TIMER.Channel[Number].FlagTimersON=1;
}
volatile uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON;
//Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться),
//то OutFlag=1 и обнуляем Флаг работы
if ((TimerToStart >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar))
{
OutFlag=1;
TIMER.Channel[Number].FlagTimersON=0;
TIMER.Channel[Number].TimeCountingON=0;
TimerToStart=0;
}
else
{
OutFlag=CurrentFlag;
//Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер
if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar))
{
TIMER.MS=0;
TIMER.Channel[Number].TimeCountingON=0;
}
}
sei();
return OutFlag;
}
uint8_t OFFAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag)
{
cli();
uint8_t OutFlag=CurrentFlag; //Переменная отвечает за RETURN f().
TIMER.TimeCurrent=TIMER.MS; //Присваиваем текущие значение МС
if (TIMER.Channel[Number].FlagTimersOFF==0) //Условия для захвата времени вызова функции и установки флага работы
{
TIMER.Channel[Number].TimeCountingOFF=TIMER.MS;
TIMER.Channel[Number].FlagTimersOFF=1;
}
volatile uint32_t TimerToSTOP = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingOFF;
//Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться),
//то OutFlag=0 и обнуляем Флаг работы
if ((TimerToSTOP >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)>TimeVar))
{
OutFlag=0;
TIMER.Channel[Number].FlagTimersOFF=0;
TIMER.Channel[Number].TimeCountingOFF=0;
TimerToSTOP=0;
}
else
{
OutFlag=CurrentFlag;
//Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер
if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)<TimeVar))
{
TIMER.MS=0;
TIMER.Channel[Number].TimeCountingOFF=0;
}
}
sei();
return OutFlag;
}
void StartInitIO()
{
OneOUT.ByteRegister=0x00;
TwoOUT.ByteRegister=0x00;
ThreeOUT.ByteRegister=0x00;
OneIN.ByteRegister=0x00;
TwoIN.ByteRegister=0x00;
ThreeIN.ByteRegister=0x00;
FourIN.ByteRegister=0x00;
FifthIN.ByteRegister=0x00;
}
/*инициализация SPI модуля в режиме master*/
void SPI_Init(void)
{
/*настройка портов ввода-вывода
все выводы, кроме MISO выходы*/
SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(1<<SPR0);
SPSR = (0<<SPI2X);
}
uint8_t SPI_UpdataByte(uint8_t data)
{
uint8_t report;
SPDR = data;
while(!(SPSR & (1<<SPIF)));
report = SPDR;
return report;
}
void SpiOutRegister()
{
SPI_PORT &= ~(1<<SPI_SS);
OneIN.ByteRegister=SPI_UpdataByte(0);
TwoIN.ByteRegister=SPI_UpdataByte(0);
ThreeIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister);
FourIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister);
FifthIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister);
SPI_PORT |= (1<<SPI_SS);
}
/*Описание распределителей*/
#define R01TOP OneOUT.Register.DO0
#define R01DOWN OneOUT.Register.DO1
#define R02RO3 OneOUT.Register.DO2
#define R04 OneOUT.Register.DO3
#define R05 OneOUT.Register.DO4
#define R06RO7 OneOUT.Register.DO5
#define R08 OneOUT.Register.DO6
#define RO9 OneOUT.Register.DO7
#define R10 TwoOUT.Register.DO0
#define R11 TwoOUT.Register.DO1
#define R12 TwoOUT.Register.DO2
#define R13 TwoOUT.Register.DO3
#define R14 TwoOUT.Register.DO4
#define R15 TwoOUT.Register.DO5
#define R16 TwoOUT.Register.DO6
#define K1 TwoOUT.Register.DO7
#define K2 ThreeOUT.Register.DO1
/*Описание датчиков*/
#define D01 OneIN.Register.DO0
#define D02 OneIN.Register.DO1
#define D03 OneIN.Register.DO2
//#define D33 OneIN.Register.DO2
void Algoritm()
{
R01TOP=OnAfterTimeMS(1200,1,R01TOP);
R01TOP=OFFAfterTimeMS(1300,2,R01TOP);
}
int main(void)
{
SPI_Init();
StartInitIO();
InitTimers();
DDRD=0xff;// Настраиваем порт D на выход
TCCR0=(1<<CS01)|(1<<CS00); //Настраиваем пред делитель 64
TIMSK=(1<<TOIE0); // Запускаем таймер
TCNT0=131;
//TIMER.MS=MAX_UINT32-9000;
sei();
while(1)
{
SpiOutRegister();
Algoritm();
}
return 0;
}
Ср ноя 08, 2017 09:01:49
Ср ноя 08, 2017 09:12:51
Ср ноя 08, 2017 09:14:50
Ср ноя 08, 2017 11:16:24
typedef struct _soft_timer_t {
uint32_t start;
uint32_t timeout;
} soft_timer_t;
/*
* Включение таймера
* ~~~~~~~~~~~~~~~~~
* ВНИМАНИЕ! Если таймер включен, он перезапускается
*/
void soft_timer_arm (soft_timer_t *t, uint32_t timeout)
{
t->timeout = timeout;
if (timeout)
t->start = get_current_tick ();
}
bool_t soft_timer_armed (soft_timer_t *t)
{
return (t->timeout != 0);
}
bool_t soft_timer_expired (soft_timer_t *t)
{
uint32_t now;
if (! soft_timer_armed (t))
return 0; /* таймер не запущен, соответственно истекшим быть не может */
now = get_current_tick ();
return (now - t->start) >= t->timeout;
}
uint16_t TimeCountingON = 65530; // тик начала работы таймера
uint16_t MS = 0; // текущий тик (было переполнение)
// разница между текущим тиком и тиком начала работы таймера
uint16_t ticks_passed = MS - TimeCountingON; // ticks_passed будет 6!!!
Все работает как и задумывалось включение каждые 1300ms на 100ms.
/* включает/выключает что надо :-) */
void on_off (bool_t on)
{
.....
}
static soft_timer_t on_off_timer;
static bool_t on;
/*включение каждые 1300ms на 100ms*/
void Algoritm()
{
soft_timer_t *t = &on_off_timer;
if (soft_timer_expired (t)) { /* таймер истек */
/* переключаем */
on ^= 1; on_off (on);
/* и перезапускаем таймер */
soft_timer_arm (t, on ? 100 : 1200);
}
}
/* выключаем и стартуем таймер */
on_off (on = 0);
soft_timer_arm (&on_off_timer, 1200);
while(1)
{
SpiOutRegister();
Algoritm();
}
Ср ноя 08, 2017 14:18:16
Нет, не проще.viiv писал(а):Все работает как и задумывалось включение каждые 1300ms на 100ms.
Так не проще?
#define AMOUNT_TIMERS 6 //Количество используемых таймеров
Ср ноя 08, 2017 14:40:42
Ср ноя 08, 2017 15:11:18
// установка очередного таймера. если успешно, возвращает номер таймера, если не успешно, возвращает TIMER_ERROR
uint8_t set_timer(timer_t t);
// проверка указанного таймера. Если истек, возвращает 1, если не истек, возвращает 0, если номер не корректный - возвращает TIMER_ERROR
uint8_t timeout(uint8_t timer_id);
typedef uint16_t timer_t;
static timer_t timers[TIMER_CNT];
ISR(TIMER0_OVF_vect){
for(uint8_t i=0; i<TIMER_CNT; i++){
if(timers[i] != TIMER_FREE){
if(timers[i]) timers[i]--;
}
}
}
uint8_t set_timer(timer_t t){
if(t > TIMER_MAX) return TIMER_ERROR;
for(uint8_t i=0; i<TIMER_CNT; i++){
ATOMIC_BLOCK(ATOMICK_RESTORE_STATE){
if(timers[i] == TIMER_FREE){
timers[i] = t;
return i;
}
}
}
return TIMER_ERROR;
}
uint8_t timeout(uint8_t timer_id){
if(timer_id >= TIMER_CNT) return TIMER_ERROR;
ATOMIC_BLOCK(ATOMICK_RESTORE_STATE){
if(timers[timer_id] == TIMER_FREE) return TIMER_ERROR;
if(timers[timer_id] != 0) return 0;
else {
timers[timer_id] = TIMER_FREE;
return 1;
}
}
}
Чт ноя 09, 2017 03:00:05
Чт ноя 09, 2017 07:02:43
Чт ноя 09, 2017 07:35:15
Пт ноя 10, 2017 10:11:05
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Evaluation
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 10.11.2017
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
PORTC.0=1;
}
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTC=0x00;
DDRC=0xff;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x07;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;
// USART initialization
// USART disabled
UCSRB=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC disabled
ADCSRA=0x00;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// TWI disabled
TWCR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
// Place your code here
}
}
Пт ноя 10, 2017 10:26:06
TCCR0=0x07;
Пт ноя 10, 2017 10:41:21
TCCR0=0x07;
Пт ноя 10, 2017 10:54:15
Пт ноя 10, 2017 11:57:38
Вт дек 05, 2017 17:57:11
Вс янв 14, 2018 14:08:22