Skip to content

Commit 0544ff8

Browse files
committed
✔️[Fix] Add Timers library
1 parent 50f00c1 commit 0544ff8

File tree

2 files changed

+329
-0
lines changed

2 files changed

+329
-0
lines changed

Robot/Timers.c

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#include "main.h"
2+
#include "Timers.h"
3+
4+
//Incializa estructura Tcfg de forma que T0_Init configure
5+
//al TIMER0 con los valores de Reset (no modifica registros):
6+
void T0_deInit(tT0config * Tcfg) {
7+
Tcfg->modo=Normal;
8+
Tcfg->pre=des;
9+
Tcfg->OCA=sNo;
10+
Tcfg->OCB=sNo;
11+
}
12+
//Incializa estructura Tcfg de forma que T1_Init configure
13+
//al TIMER1 con los valores de Reset (no modifica registros):
14+
void T1_deInit(tT1config * Tcfg) {
15+
Tcfg->modo=Normal1;
16+
Tcfg->pre=des;
17+
Tcfg->OCA=sNo;
18+
Tcfg->OCB=sNo;
19+
}
20+
//Incializa estructura Tcfg de forma que T2_Init configure
21+
//al TIMER2 con los valores de Reset (no modifica registros):
22+
void T2_deInit(tT2config * Tcfg) {
23+
Tcfg->modo=Normal;
24+
Tcfg->pre=des2;
25+
Tcfg->OCA=sNo;
26+
Tcfg->OCB=sNo;
27+
}
28+
29+
//Configura pines como salidas, y sus Modos de Salida: toggle, clear o set (1, 2 o 3):
30+
void T0_Init(tT0config * Tcfg) {
31+
if (Tcfg->OCA) DDRD|=(1<<DDB6); //OC0A es PD6 en Atmega328
32+
if (Tcfg->OCB) DDRD|=(1<<DDB5); //OC2B es PD5
33+
//Los tipos enumerados son tipo int.
34+
TCCR0A = (Tcfg->OCA <<COM0A0)|(Tcfg->OCB<<COM0B0)|(Tcfg->modo&0x03); //Configura Modo Operacional,..
35+
TCCR0B = (((Tcfg->modo)<<1)&8)|Tcfg->pre; //..Prescaler y Modo de Salida en los dos registros TCCR.
36+
}
37+
void T1_Init(tT1config * Tcfg) {
38+
if (Tcfg->OCA) DDRB|=(1<<DDB1); //OC1A es PB1
39+
if (Tcfg->OCB) DDRB|=(1<<DDB2); //OC1B es PB2
40+
TCCR1A = (Tcfg->OCA <<COM1A0)|(Tcfg->OCB<<COM1B0)|(Tcfg->modo&0x03);
41+
TCCR1B = (((Tcfg->modo)<<1)&0x18)|(Tcfg->pre);
42+
}
43+
void T2_Init(tT2config * Tcfg) {
44+
if (Tcfg->OCA) DDRB|=(1<<DDB3); //OC2A es PB3
45+
if (Tcfg->OCB) DDRD|=(1<<DDB3); //OC2B es PD3
46+
TCCR2A = (Tcfg->OCA <<COM2A0)|(Tcfg->OCB<<COM2B0)|(Tcfg->modo&0x03);
47+
TCCR2B = (((Tcfg->modo)<<1)&8)|Tcfg->pre;
48+
}
49+
50+
//Habilitacion de interrupciones de software de los timers:
51+
void T0_Interrupts(tT0INTconfig *T0i) {
52+
TIMSK0=(T0i->IT_compb)<<OCIE0B|(T0i->IT_compa)<<OCIE0A|(T0i->IT_ovf)<<TOIE0;
53+
TIFR0=(T0i->IT_compb)<<OCF0B|(T0i->IT_compa)<<OCF0A|(T0i->IT_ovf)<<TOV0; //apagado de flag
54+
}
55+
void T1_Interrupts(tT1INTconfig *T1i) {
56+
TIMSK1=(T1i->IT_ic)<<ICIE1|(T1i->IT_compb)<<OCIE1B|(T1i->IT_compa)<<OCIE1A|(T1i->IT_ovf)<<TOIE1;
57+
TIFR1=(T1i->IT_ic)<<ICF1|(T1i->IT_compb)<<OCF1B|(T1i->IT_compa)<<OCF1A|(T1i->IT_ovf)<<TOV1;
58+
}
59+
void T2_Interrupts(tT2INTconfig *T2i) {
60+
TIMSK2=(T2i->IT_compb)<<OCIE2B|(T2i->IT_compa)<<OCIE2A|(T2i->IT_ovf)<<TOIE2;
61+
TIFR2=(T2i->IT_compb)<<OCF2B|(T2i->IT_compa)<<OCF2A|(T2i->IT_ovf)<<TOV2; //borra solo..
62+
} //..los flags de int habilitadas
63+
64+
void configurarTimer0(tT0y2modo modoOperacionT0, tT0y1pre prescalerT0, tTsalida modoSalidaA, tTsalida modoSalidaB) {
65+
T0_deInit(&T0cfg);
66+
T0cfg.modo = modoOperacionT0;
67+
#ifdef EstadoInicialActivado
68+
T0cfg.pre = prescalerT0;
69+
#endif
70+
#ifdef EstadoInicialDesactivado
71+
T0cfg.pre = des; //TIMER0 comienza en Estado Desactivado
72+
#endif
73+
T0cfg.OCA = modoSalidaA;
74+
T0cfg.OCB = modoSalidaB;
75+
T0_Init(&T0cfg);
76+
valorPrescaler__T0=valorPrescalerT0y1(prescalerT0);
77+
OCR0A = (uint16_t)( (ANCHO_PULSO_INICIAL_A/1000)*(F_CPU/valorPrescaler__T0) +1 ); //Servo A
78+
OCR0B = (uint16_t)( (ANCHO_PULSO_INICIAL_G/1000)*(F_CPU/valorPrescaler__T0) +1 ); //Servo G
79+
}
80+
void configurarTimer1(tT1modo modoOperacionT1, tT0y1pre prescalerT1, tTsalida modoSalidaA,
81+
tTsalida modoSalidaB) {
82+
/* Config Timer1:
83+
T1cfg esta declarada en Timers.h como variable tipo tT1config
84+
tT1config esta definida en Timers.h como una estructura con campos
85+
de diversos tipos enumerados, lo que facilita su llenado.*/
86+
T1_deInit(&T1cfg); //Incializa estructura de forma que T1_Init configure al TIMER1 con los valores
87+
//de Reset (buena practica), aunque no es necesario si llenamos todos los parametros.
88+
T1cfg.modo = modoOperacionT1;
89+
#ifdef EstadoInicialActivado
90+
T1cfg.pre = prescalerT1;
91+
#endif
92+
#ifdef EstadoInicialDesactivado
93+
T1cfg.pre = des; //TIMER1 comienza en Estado Desactivado
94+
#endif
95+
T1cfg.OCA = modoSalidaA;
96+
T1cfg.OCB = modoSalidaB;
97+
// Hasta aqui solamente se ha cargado la variable T1cfg con datos, no se ha
98+
// modificado ningun registro del Timer1 del micro.
99+
T1_Init(&T1cfg); // Llama a la funcion que va a configurar al Timer1 con los
100+
// parametros cargados en T1cfg.
101+
valorPrescaler__T1=valorPrescalerT0y1(prescalerT1);
102+
ICR1 = (uint16_t)( (T_ms/1000)*(F_CPU/valorPrescaler__T1) +1 ); //Controla Periodo de los PWM en Timer1
103+
OCR1A = (uint16_t)( (ANCHO_PULSO_INICIAL/1000)*(F_CPU/valorPrescaler__T1) +1 ); //Servo B
104+
OCR1B = (uint16_t)( (ANCHO_PULSO_INICIAL/1000)*(F_CPU/valorPrescaler__T1) +1 ); //Servo M
105+
}
106+
void configurarTimer2(tT0y2modo modoOperacionT0y2,tT2pre prescalerT2, tTsalida modoSalidaA,
107+
tTsalida modoSalidaB) {
108+
T2_deInit(&T2cfg);
109+
T2cfg.modo = modoOperacionT0y2;
110+
#ifdef EstadoInicialActivado
111+
T2cfg.pre = prescalerT2;
112+
#endif
113+
#ifdef EstadoInicialDesactivado
114+
T2cfg.pre = des2; //TIMER2 comienza en Estado Desactivado
115+
#endif
116+
T2cfg.OCA = modoSalidaA;
117+
T2cfg.OCB = modoSalidaB;
118+
T2_Init(&T2cfg);
119+
valorPrescaler__T2=valorPrescalerT2(prescalerT2);
120+
OCR2A = (uint16_t)( (ANCHO_PULSO_INICIAL_C/1000)*(F_CPU/valorPrescaler__T2) +1 ); //Servo C
121+
//OCR2B = (uint16_t)( (ANCHO_PULSO_INICIAL/1000)*(F_CPU/valorPrescaler__T2) +1 );
122+
}
123+
uint16_t valorPrescalerT0y1(tT0y1pre prescalerT0y1) { //Valor numerico del prescaler para TIMER0 y TIMER1
124+
switch(prescalerT0y1) {
125+
case des:
126+
return 0;
127+
break;
128+
case prex1:
129+
return 1;
130+
break;
131+
case prex8:
132+
return 8;
133+
break;
134+
case prex64:
135+
return 64;
136+
break;
137+
case prex256:
138+
return 256;
139+
break;
140+
case prex1024:
141+
return 1024;
142+
break;
143+
case Ext_Fneg:
144+
return 0;
145+
break;
146+
case Ext_Fpos:
147+
return 0;
148+
break;
149+
default:
150+
return 0;
151+
break;
152+
}
153+
}
154+
uint16_t valorPrescalerT2(tT2pre prescalerT2) { //Valor numerico del prescaler para TIMER2
155+
switch(prescalerT2) {
156+
case des2:
157+
return 0;
158+
break;
159+
case pre2x1:
160+
return 1;
161+
break;
162+
case pre2x8:
163+
return 8;
164+
break;
165+
case pre2x32:
166+
return 32;
167+
break;
168+
case pre2x64:
169+
return 64;
170+
break;
171+
case pre2x128:
172+
return 128;
173+
break;
174+
case pre2x256:
175+
return 256;
176+
break;
177+
case pre2x1024:
178+
return 1024;
179+
break;
180+
default:
181+
return 0;
182+
break;
183+
}
184+
}

Robot/Timers.h

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
Define tipos y declara funciones para configurar los modulos de timer del Atmega328
3+
y sus interrupciones:
4+
El Atmega328 tiene dos timers de 8 bits (TIMER0 y TIMER2) y un timer de 16 (TIMER1)
5+
Los modos de trabajo de TIMER0 y TIMER2 son iguales entre si, pero difieren respecto
6+
a los del TIMER1 (este tiene mas modos).
7+
Las opciones de prescaler de TIMER0 y TIMER1 son iguales entre si, pero difieren de
8+
las del prescaler del TIMER2 (este no tiene los modos externos, y agrega dos modos
9+
internos x32 y x128).
10+
*/
11+
12+
#ifndef TIMERS_H_
13+
#define TIMERS_H_
14+
15+
typedef enum {
16+
Normal = 0,
17+
PWM_PC_8b = 1,
18+
CTC_OCRA = 2,
19+
FAST_PWM_8b = 3,
20+
PWM_PC_OCR = 5,
21+
FAST_PWM_OCR = 7
22+
}tT0y2modo; //Tipo modos de trabajo para TIMER0 y TIMER2
23+
typedef enum {
24+
Normal1 = 0,
25+
PWM_PC1_8b = 1,
26+
PWM_PC1_9b = 2,
27+
PWM_PC1_10b = 3,
28+
CTC_OCR1A = 4,
29+
FAST_PWM1_8b = 5,
30+
FAST_PWM1_9b = 6,
31+
FAST_PWM1_10b = 7,
32+
PWM_PyFC_ICR1 = 8,
33+
PWM_PyFC_OCR1A = 9,
34+
PWM_PC_ICR1 = 10,
35+
PWM_PC_OCR1A = 11,
36+
CTC_ICR1 = 12,
37+
FAST_PWM_ICR1 = 14,
38+
FAST_PWM_OCR1A = 15
39+
}tT1modo; //Tipo modos de trabajo para TIMER1
40+
41+
typedef enum {
42+
des = 0,
43+
prex1 = 1,
44+
prex8 = 2,
45+
prex64 = 3,
46+
prex256 = 4,
47+
prex1024 = 5,
48+
Ext_Fneg = 6,
49+
Ext_Fpos = 7
50+
}tT0y1pre; //Tipo prescaler para TIMER0 y TIMER1
51+
typedef enum {
52+
des2 = 0,
53+
pre2x1 = 1,
54+
pre2x8 = 2,
55+
pre2x32 = 3,
56+
pre2x64 = 4,
57+
pre2x128 = 5,
58+
pre2x256 = 6,
59+
pre2x1024 = 7
60+
}tT2pre; //Tipo prescaler para TIMER2
61+
62+
typedef enum {
63+
sNo = 0,
64+
sToggle = 1,
65+
sClear = 2,
66+
sSet = 3
67+
}tTsalida; //Tipo salida para todos los timers
68+
69+
//Aqui se definen las estructuras con todos los Parametros de Configuracion
70+
//de TIMER0, TIMER1 y TIMER2. Son estructura con campos de diversos tipos enumerados.
71+
typedef struct {
72+
tT0y2modo modo; //estos campos son los anteriormente definidos
73+
tT0y1pre pre;
74+
tTsalida OCA;
75+
tTsalida OCB;
76+
}tT0config;
77+
typedef struct {
78+
tT1modo modo;
79+
tT0y1pre pre;
80+
tTsalida OCA;
81+
tTsalida OCB;
82+
}tT1config;
83+
typedef struct {
84+
tT0y2modo modo;
85+
tT2pre pre;
86+
tTsalida OCA;
87+
tTsalida OCB;
88+
}tT2config;
89+
90+
// Aqui se definen las estructuras para activar interrupciones de
91+
// TIMER0, TIMER1 y TIMER2.
92+
typedef struct {
93+
bool IT_ovf:1; //Estos campos son simplemente booleanos.
94+
bool IT_compa:1;
95+
bool IT_compb:1;
96+
}tT0INTconfig;
97+
typedef struct {
98+
bool IT_ovf:1; //Al usar booleanos lo ideal es especificar su longitud para que
99+
bool IT_compa:1; //sea de 1 Byte (con :1), sino genera una longitud de 3 Bytes;
100+
bool IT_compb:1; //aunque no es necesariamente fundamental, si es que se cuenta con
101+
bool IT_ic:1; //un Uc que dispone de mucha mas memoria de la que se necesita.
102+
}tT1INTconfig;
103+
typedef struct { //Esta estructura es igual a la de TIMER0
104+
bool IT_ovf:1;
105+
bool IT_compa:1;
106+
bool IT_compb:1;
107+
}tT2INTconfig;
108+
109+
// Declaracion de variables:
110+
#define T_ms 16.32 //Periodo fijo [en ms]
111+
#define ANCHO_PULSO_INICIAL 1.500 //Pulso Inicial [en ms]
112+
#define ANCHO_PULSO_INICIAL_G 2.100 //Pulso Inicial servo Giro gripper [en ms]
113+
#define ANCHO_PULSO_INICIAL_A 2.500 //Pulso Inicial servo Altura gripper [en ms]
114+
#define ANCHO_PULSO_INICIAL_C 0.250 //Pulso Inicial servo Cierre-apertura gripper [en ms]
115+
116+
uint16_t valorPrescaler__T0;
117+
uint16_t valorPrescaler__T1;
118+
uint16_t valorPrescaler__T2;
119+
tT0config T0cfg;
120+
tT1config T1cfg;
121+
tT2config T2cfg;
122+
123+
// Declaracion de las funciones:
124+
void T0_Init(tT0config *Tcfg);
125+
void T0_deInit(tT0config *Tcfg); //Funcion que pone parametros de estructura Tcfg
126+
//en valores por defecto.
127+
void T1_Init(tT1config *Tcfg);
128+
void T1_deInit(tT1config *Tcfg); //Funcion que pone parametros de estructura Tcfg
129+
//en valores por defecto.
130+
void T2_Init(tT2config *Tcfg);
131+
void T2_deInit(tT2config *Tcfg); //Funcion que pone parametros de estructura Tcfg
132+
//en valores por defecto.
133+
void T0_Interrupts(tT0INTconfig *Tintcfg);
134+
void T1_Interrupts(tT1INTconfig *Tintcfg);
135+
void T2_Interrupts(tT2INTconfig *Tintcfg);
136+
void configurarTimer0(tT0y2modo modoOperacionT0, tT0y1pre prescalerT0, tTsalida modoSalidaA,
137+
tTsalida modoSalidaB);
138+
void configurarTimer1(tT1modo modoOperacionT1, tT0y1pre prescalerT1, tTsalida modoSalidaA,
139+
tTsalida modoSalidaB);
140+
void configurarTimer2(tT0y2modo modoOperacionT2, tT2pre prescalerT2, tTsalida modoSalidaA,
141+
tTsalida modoSalidaB);
142+
uint16_t valorPrescalerT0y1(tT0y1pre prescalerT0y1);
143+
uint16_t valorPrescalerT2(tT2pre prescalerT2);
144+
145+
#endif /* TIMERS_H_ */

0 commit comments

Comments
 (0)