требуется помощь знатоков Си

papakaplo
Offline
Зарегистрирован: 18.04.2016

Начал изучать структуры, решил сделать таймер который работает по заданным интервалам с заданой маской включения или выключения ножки МК. Пока сделал для 1 таймера все работает в протеусе как надо. Помогите правильно собрать всё функцию, то что сейчас находится в основном цикле программы так чтоб второй таймер крутился параллельно первому, но уже со своими интервалами и задержками. Переменная tic инерементируется по прерыванию раз в секунду. Я так понимаю тут без указателей не обойтись? 

#define F_CPU 8000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define TIMER_TICKS_IN_ONE_SECOND 8	//тики таймера в секунду при делителе 1024. OCRA=122. (1000000/1024/122 = 8)

unsigned char count_to_second; //число тиков TIMER1
unsigned long int tic; //отсчет времени в секундах
//------------------------------------------------------------------
void port_ini (void){
	DDRB =	(1 << PB0) //выход
			|(1 << PB1)//выход
			|(1 << PB2)//выход
			|(1 << PB3)//выход
			|(1 << PB4);//выход
	PORTB=0b00000000;
}
//------------------------------------------------------------------
//инициализация таймера1
void timer1_ini (void){
	TCCR1 |= (1 << CTC1) //режим CTC
	|(0<<COM1A1)|(0<<COM1A0) //отключаем OC1A
	|(1 << CS13)|(0 << CS12)|(1 << CS11)|(0 << CS10);  //Делитель 512
	TCNT1 = 0x00;                  //сброс счетчика
	OCR1A = 125;
	OCR1C = 125;                //регистр сравнения
	TIMSK |=(1<<OCIE1A);		//включаем прерывания по сравнению с OCR1A	
}

//------------------------------------------------------------------
//обработка прерывания таймера0
ISR (TIMER1_COMPA_vect){
	count_to_second++;
	if (count_to_second >= TIMER_TICKS_IN_ONE_SECOND) { // Отсчитываем прерывание 8 раз получаем 1 секунду
		tic++;
		count_to_second=0;
	}
}

typedef struct 		//создаем синоним структуры  
{
	unsigned char sequence;	//последовательность включения светодиода
	unsigned char intervals[8];    //время каждого интервала
} Timers;
int main(void)
{
	sei();
	port_ini(); //Инициализируем порты
	timer1_ini(); //Инициализируем таймер1
	Timers Timer_1 = {0b01010101, {1, 1, 1, 1, 2, 1, 2, 1}};
	//Timers Timer_2 = {0b01010101, {1, 1, 1, 1, 2, 1, 2, 1}};	
	 
    while(1)
    {

		for ( unsigned char i=0; i<8;){
		static unsigned char time; //сумма интервалов после 0 элемента массива
				if (tic<Timer_1.intervals[0]+time){

					if (((Timer_1.sequence>>i)&0x01)>0){
								PORTB |=(1<<PB0);}
					else {PORTB &=~(1<<PB0);}

				}
			else{ i++; time+=Timer_1.intervals[i];}
		 
				}
		 }
		 
	}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

посмотри как реализовано 

  https://github.com/DetSimen/Arduino-

1 аппаратный таймер для нескольких программных

 

papakaplo
Offline
Зарегистрирован: 18.04.2016

В классах пока не особо разбираюсь, я так понял вы реализуете все уменьшением заданного интервала. У вас на С++ все я на С# делаю :/

Меня интересует как собрать в функцию данный кусочек кода, именно программная реализация, не пойму как объявить элементы массива структуры как переменные в функции.  Моя структура Timer_1 со своими параметрами будет работать для PB0, Timer_1 для PB1 и т.д. Я понимаю что там много праллелных таймеров и они будут работать абсолютно асинхронно. 

for ( unsigned char i=0; i<8;){
		static unsigned char time; //сумма интервалов после 0 элемента массива
				if (tic<Timer_1.intervals[0]+time){

					if (((Timer_1.sequence>>i)&0x01)>0){
								PORTB |=(1<<PB0);}
					else {PORTB &=~(1<<PB0);}

				}
			else{ i++; time+=Timer_1.intervals[i];}
		 
				}
		 }

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

papakaplo пишет:

В классах пока не особо разбираюсь, я так понял вы реализуете все уменьшением заданного интервала. У вас на С++ все я на С# делаю :/

Тут я и ауелъ. Вопросов больше не имею. 

papakaplo
Offline
Зарегистрирован: 18.04.2016

не все вашего уровня, уж простите.

Logik
Offline
Зарегистрирован: 05.08.2014

DetSimen пишет:

посмотри как реализовано 

  https://github.com/DetSimen/Arduino-

1 аппаратный таймер для нескольких программных

 

Я посмотрел. Слабенько сделано. Чем дергать TTimerList::Step каждую мсек.  лучше расчитатьт по данным Items сколько времени нужно до ближайшего требуемого интервала и настроить таймер на требуемую длительность. Так процессор существенно менше нагружается. Определять сколько времени нужно - это поиск минимального значения в массиве.

По изложеному подходу я делал на одном таймере формирование интервалов для одновременного использования сервоприводов и ds18b20, интервалы от 10мксек получаются и погрешность 4мксек. Но то уже совсем жестко, приходится учитывать время отработки самого обработчика. В конце цикла по значению таймера смотрим как долго крутился обработчик и если до следующего интервала мало времени, то считаем что он уже наступил и вызываем его обработчик.

Гдето так вобщем.

void TIMER1::Interrupt(void)
{
   restart_proc: 
    cli(); 
     word dhh=Pause();
	 TCCR1A = 0; 
	 volatile word e;
	 volatile word f;
	 for(e=TCNT1;;){f=TCNT1;if(e!=f) break;} //ждем инкримента таймера для защиты от него следующих операций

	 f=TCNT1;
	 if(f>=dhh) //следующий интервал слишком короткий, он фактически прошел, сразу и стартуем
		 {TCNT1 =f-dhh;sei();goto restart_proc;} 
	 TCNT1 =f-dhh;
     sei();   
};                           


int TIMER1::Pause(void)
{ 
start:

    word t=0xffff; 
	TIMER1_INTERRUPT_LIST_RECORD* p;
	for(p=TIMER1_INTERRUPT_LIST;p->fn;p++)  
	{  
        /*  По логике CurrInterval всегда не более любого p->time */
		if(p->time) 
           p->time=p->time-CurrInterval;
	   
		if(p->time<4) //это допустимая погрешность, если осталось менше 4 тактов, то считаем пора
	       p->time=p->fn(p->ctx);
		   
		if(p->time)
		    if(p->time<t) 
			    t=p->time; 
//Serial.print(p->time);	Serial.print(";  ");	
	}	 
	   
       CurrInterval=t;
	return CurrInterval; 
}

 

Logik
Offline
Зарегистрирован: 05.08.2014

DetSimen пишет:

papakaplo пишет:

В классах пока не особо разбираюсь, я так понял вы реализуете все уменьшением заданного интервала. У вас на С++ все я на С# делаю :/

Тут я и ауелъ. Вопросов больше не имею. 

+1