Upload
radio-bronka-1045-fm
View
438
Download
0
Embed Size (px)
Citation preview
Excitador
La vaca
Manual de usuario
Índice
1. Sin computadora 2
1.1. Cómo seleccionar la frecuencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Con computadora 2
2.1. Cómo conectar a una computadora y probar la comunicación . . . . . . . . . . . . . 22.2. Cómo seleccionar la frecuencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.3. Cómo controlar la potencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.4. Referencia de comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3. Diagramas 4
3.1. Esquemático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43.2. PCB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2.1. Tarjeta madre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.2.2. Tarjeta de comunicación serial . . . . . . . . . . . . . . . . . . . . . . . . . . 83.2.3. Tarjeta del amplificador operacional . . . . . . . . . . . . . . . . . . . . . . . 83.2.4. Tarjeta de contadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4. Código Fuente 9
4.1. modos.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94.2. modos.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124.3. serial.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134.4. serial.rl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144.5. vaca.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224.6. vaca.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.7. Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1
2011, La kehuelga radio.
El excitador puede ser configurado de dos maneras; con 8 interruptores que están soldados a latarjeta y mediante un puerto de comunicación serial RS232.
Con los interruptores solo es posible seleccionar la frecuencia de operación, mientras que conel puerto serial el excitador puede comunicar información referente a su funcionamiento, como elestado de algunos contadores, además de poder seleccionar la frecuencia y la potencia de salida.
1. Sin computadora
Si no tienes disponible una computadora con puerto serial o simplemente no quieres usarlapara configurar los parámetros del excitador, debes prender el interruptor número 8 del dipswitch;entonces, el aparato leerá la frecuencia de los 7 interruptores restantes del mismo dipswitch y no desu memoria.
1.1. Cómo seleccionar la frecuencia
Podemos considerar que los 7 interruptores definen un número binario, el cual corresponde se-cuencialmente a las frecuencias de operación que van de 87.9 MHz hasta 107.9 MHz. Es decir alnúmero binario 0000000 corresponde la frecuencia 87.9 MHz, al número 0000001 la frecuencia 88.0MHz y así sucesivamente hasta llegar a 107.9 MHz, o sea 1100100.
En lugar de contar desde 0 hasta el número que corresponde a la frecuencia que queremosconfigurar, podemos usar la siguiente relación:
n =f × 10− 879
2(1)
Donde, f es la frecuencia en MHz, y n es el número que hay que configurar en el dipswitch; nestá en base decimal, hace falta convertirlo a base binaria.
Digamos por ejemplo, que queremos operar en la frecuencia de los 93.5 MHz.Si aplicamos la relación (1), tenemos:
n =93,5× 10− 879
2
= 28
28 en base binaria es 0011100.
2. Con computadora
2.1. Cómo conectar a una computadora y probar la comunicación
El excitador cuenta con un puerto de comunicación serial que sigue el estándar RS232; puedesconectarlo a un puerto serial de una computadora, necesitarás un programa emulador de terminal quese pueda conectar a un puerto serie, en GNU/Linux puedes usar gtkterm; además debes configurarlocon los siguientes parámetros:
2
2011, La kehuelga radio.
Velocidad 9600Bits de datos 8Bits de paro 1Paridad Ninguna
Prueba la comunicación, por ejemplo, pregúntale al excitador en qué frecuencia está trabajando;debes escribir en la terminal el comando:
f?
Para que el comando sea enviado al excitador, debes oprimir la tecla enter después de escribir elcomando. Si la comunicación funciona correctamente, el excitador responderá con la frecuencia deoperación, así:
F1021
Eso significa que la frecuencia de operación del excitador es 102.1 MHz.
2.2. Cómo seleccionar la frecuencia
El comando para seleccionar la frecuencia tiene la forma
Fiiii
La f puede ser minúscula o mayúscula, iiii debe sustituirse por la frecuencia de operación enmegahertz multiplicada por 10.
El excitador responde con el mensaje:
Fiiii
Por ejemplo, si queremos operar el excitador a 105.3 MHz el comando sería:
F1053
2.3. Cómo controlar la potencia
Es posible controlar la potencia del excitador; el comando tiene la forma:
Ahh
hh es un número expresado en base hexadecimal, que va desde 00 hasta FF; 00 es la potenciamínima y FF la máxima.
El excitador debe responder con:
Ahh
3
2011, La kehuelga radio.
2.4. Referencia de comandos
Hay bastantes comandos para cambiar y conocer el estado del excitador, están resumidos en elsiguiente cuadro, en el que i se refiere a un dígito decimal y h a un dígito hexadecimal.
Comando Descripción Respuesta Error
Ahh Cambia la potencia Ahh
A? Reporta la potencia Ahh
GA Guarda la potencia en la EEPROM GAhh
RA Restaura la potencia desde la EE-PROM
RAhh
IAM La potencia de inicio se lee de la EE-PROM
IAM
IA0 Hace que la potencia de inicio sea 0 IA0IA? Reporta la fuente de la potencia de
inicioIAM, IA0
Fiiii Cambia la frecuencia Fiiii ERROR: Frec. INVALIDA!F? Reporta la frecuencia Fiiii
GF Guarda la frecuencia seleccionada enla EEPROM
GFiiii
IFS La frecuencia de inicio se lee deldipswitch
IFS
RF Restaura la frecuencia desde la EE-PROM
RFiiii ERROR: Frec. INVALIDA!
IFM La frecuencia de inicio se lee de laEEPROM
IFM
IF? Reporta la fuente de la frecuencia deinicio
IFM, IFS
S? Reporta el dipswitch Shh
P[0-3][01] Cambia el valor de un pin de control P[0-3][01]P[0-3] Reporta el valor del pin de un con-
trolP[0-3][01]
V[0-7] Reporta un canal del ADC (conver-tidor analógico digital)
V[0-7]hhh
3. Diagramas
3.1. Esquemático
4
3 2
1
3 2
1
1 2
3 2
1
12
D9
Q
13
CL
R8
Q
10
PR
E
11
CL
K
2D
5Q
1C
LR
6Q
4P
RE
3C
LK
+5
V
AT
mega32 D
IP40
1P
B0 (
XC
K/T
0)
2P
B1 (
T1)
3P
B2 (
INT
2/A
IN0)
4P
B3 (
OC
0/A
IN1)
5P
B4 (
SS
_L)
6P
B5 (
MO
SI)
7P
B6 (
MIS
O)
8P
B7 (
SC
K)
22
PC
0 (
SC
L)
23
PC
1 (
SD
A)
24
PC
2 (
TC
K)
25
PC
3 (
TM
S)
26
PC
4 (
TD
O)
27
PC
5 (
TD
I)
28
PC
6 (
TO
SC
1)
29
PC
7 (
TO
SC
2)
14
PD
0 (
RX
D)
15
PD
1 (
TX
D)
16
PD
2 (
INT
0)
17
PD
3 (
INT
1)
18
PD
4 (
OC
1B
)
19
PD
5 (
OC
1A
)
20
PD
6 (
ICP
)
21
PD
7 (
OC
2)
9R
ES
ET
_L
10 VCC
13
XT
AL1
12
XT
AL2
PA
7 (
AD
C7)
33
PA
6 (
AD
C6)
34
PA
5 (
AD
C5)
35
PA
4 (
AD
C4)
36
PA
3 (
AD
C3)
37
PA
2 (
AD
C2)
38
PA
1 (
AD
C1)
39
PA
0 (
AD
C0)
40
31GND
11GND
32
AR
EF
30
AV
CC
+5
V
+5
V
+5
V
32
1
8 4
+5
V
1 2
3 2
1
3 2
1
12345678
16
15
14
13
12
11
10
9
SW
DIP
−8
56
7
8 4
2V
+
3C
1−
4C
2+
5C
2−
6V
−
7T
x2
Ou
t
8R
x2
In
9R
x2
Ou
t
10
Tx2
In
11
Tx1
In
12
Rx1
Ou
t1
3R
x1
In
14
Tx1
Ou
t
1C
1+
MA
X232
12
12
12
+5
V
12
+1
2V
+1
2V
10
CL
K
11
Re
se
t
9Q
1
7Q
2
5Q
4
4Q
7
6Q
3
13
Q8
12
Q9
14
Q1
0
15
Q1
1
1Q
12
2Q
6
3Q
5
1 2
2 1
1 2
+5
V
INO
UT
GN
D
1
2
3
1 2
1 2
INO
UT
GN
D
1
2
3
1 2
1 2
INO
UT
GN
D
1
2
3
1 2
1 2
1 2
Q3
MP
SH
10
R8
12k
R14
4k7
R22
220
C19
33pF
C16
4p7
C22
.1uF
D1
MV
209
Q1
MP
SH
10
R5
4K
7
R11
4k7R
6220
C11
1000pF
C17
47pF
L2
6v. #18 1
/4in
d.i.
C21
220pF
C6
1000pF
R2
47
C5
1000pF
C3
.01uF
C2
4u7
+12V
Q2
MP
SH
10
R19
22
C18
1000pF
R9
4K
7
R16
470
C14
100pF
L1
8v. #18 1
/4in
d.i.
U5
74A
C74
U5
74A
C74
R25
220
R24
4K
7
U7
X1
16M
Hz
C46
15pFC
36
.01uF
R34
22k
U4
Vcc
C26 .1uF
R23
3k3
R26
4k7
R20
4k7
C25
.1uF
R29
22k
R28
39k
R30
4k7
C24
150pF
R31
3k3
R18
33k
C27
1uF
MP
SH
10
Q4
C20
100pF
R17
4K
7
R21
470
2sc1970
Q6
L3
6v. #16 1
/4in
d.i.
C23
1000pF
R27
18
C31
.1uF
C33
1000pF
Salid
a R
F
U9
U4
R37
100k
C35
.1uF
R35
1k
U8
RS
232 R
xD
(D
B9 H
em
bra
pin
2)
RS
232 T
xD
(D
B9 H
em
bra
pin
3)
C50
1uF
C47
1uF
C51
1uF
C48
1uF
C44
5−
30pf
U6
74H
C4040
RS
232 G
ND
(D
B9 H
em
bra
pin
5)
LE
D1
Fre
c. F
ija
R44
2k2
C49
4u7
R33
220
C32
.01uF
RS
232 D
TR
(D
B9 H
em
bra
pin
4)
RS
232 R
TS
(D
B9 H
em
bra
pin
7)
RS
232 C
TS
(D
B9 H
em
bra
pin
8)
Z1
1n4733 5
.1V
R48
4k7
R49
4k7
R50
4k7
R47
4k7
J1
jum
per,
para
pro
gra
mar
C28
330pF
T1
L4
70nH
C37
12pF
C38
27pF
C43
56pF
L5 1
14nH
C45
33pF
C40
0.2
2uF
C39
.022uF
R40
6k8
R38
68k
R42
680
C41
2.2
uF
D2 1n4148
C42
.01uFR41
1k
R39
20k
P1 D
B15H
D−
1
P2 D
B15H
D−
2
P3 D
B15H
D−
3
P4 D
B15H
D−
4
AN
7 D
B15H
D−
15
AN
6 D
B15H
D−
14
AN
5 D
B15H
D−
13
AN
4 D
B15H
D−
12
AN
3 D
B15H
D−
11
AN
2 D
B15H
D−
8
AN
1 D
B15H
D−
7
AN
0 D
B15H
D−
6
+5V
DB
15H
D−
9
AG
ND
DB
15H
D−
10
DG
ND
DB
15H
D−
5
R46
4k7
R45
33k
C52
100p
R43
4k7
R32
4k7
R36
12k
C29
4u7 tant.
C30
.01uF
Q5
MT
P2955
Apagar
RF
Apagar
RF
C34
470pF
+5V
Conta
dore
s78L05
U3
C9
4u7
C12
4u7
R4
100
VS
S
Vee
+5V
RS
232
78L05
U2
C7
4u7
C10
4u7
R3
100
VS
S
Vee
+5V
AtM
ega
78L05
U1
C4
4u7
C8
4u7
R1
100
VS
S
Vee
Audio
R
R7
12k
C13
.0068uF
R12
12k
C15
.0068uF
Audio
L
R15
1k
R10
470
R13
470
C1
47uF
C42
.001uF
3v. #16,
1/4
in. d.i.
4v. #16,
1/4
in. d.i.
par
trensado d
e c
at5
,
2v, 3/8
in. d.i.
2011, La kehuelga radio.
2011, La kehuelga radio.
3.2. PCB
6
2011, La kehuelga radio.
3.2.1. Tarjeta madre
7
2011, La kehuelga radio.
3.2.2. Tarjeta de comunicación serial
3.2.3. Tarjeta del amplificador operacional
3.2.4. Tarjeta de contadores
8
2011, La kehuelga radio.
4. Código Fuente
4.1. modos.c
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "vaca.h"
#include "serial.h"
/* las funciones que corren en main y en la interrupción, respectivamente */
void (*funmain)(), (*funinter)();
/* semáforo de la interrupción pwm, definido en vaca.c */
uint8_t pwmsema;
uint8_t estado = 0, amp;
uint16_t dif, contvco, ucontvco, veces;
int16_t frec;
uint32_t ds, lvco=7, vco = 0x80707007;
int32_t error;
static uint32_t acc = 7;
9
2011, La kehuelga radio.
uint16_t nvfrec __attribute__((section (".eeprom"))) = (NV_FREC);
uint8_t nvamp __attribute__((section (".eeprom"))) = (NV_AMP);
uint8_t nvfi __attribute__((section (".eeprom"))) = (NV_IF);
uint8_t nvai __attribute__((section (".eeprom"))) = (NV_IA);
void pll_main()
{
static uint8_t upwmsema=0;
if ( estado == 1 ) {
PORTB |= _BV(PB0);
} else {
PORTB &= ~_BV(PB0);
}
if (pwmsema ^ upwmsema) {
if(veces < 65500) veces += (uint8_t)(pwmsema - upwmsema);
upwmsema = pwmsema;
if(veces > 62000) {
estado = 1;
}
if(veces > 50000) {
OCR0 = amp;
}
}
}
void pll_inter()
{
OCR2 = (uint8_t)(acc >> 24);
if(TIFR & _BV(ICF1)) {
TIFR |= _BV(ICF1);
contvco = ICR1;
dif = contvco - ucontvco;
ucontvco = contvco;
error = ((int32_t)dif * (int32_t)(BITS_FREC) * (int32_t)((ESCALA) / (DIV_HW))) - ds;
lvco &= (0xffffffff >> (KS));
lvco += error;
vco += (((int32_t)lvco) >> (KS));
if( estado == 0) {
vco += (error >> (KRAPIDO));
}
}
10
2011, La kehuelga radio.
acc &= 0x00ffffff;
acc += vco;
}
void modo_pll()
{
estado = 0;
veces = 0;
/* si el pin #7 del dipswitch. no está en modo manual, y la fuente de la
amplitud de inicio es cero, entonces la amplitud de inicio es 0. En todos
los demás casos, la amplitud de inicio es la que está guardada en la
EEPROM. */
if((PINC & 0x80) && (eeprom_read_byte(&nvai) == ’0’)) {
amp = 0;
} else {
amp = eeprom_read_byte(&nvamp);
}
if((PINC & 0x80) && (eeprom_read_byte(&nvfi))) {
frec = eeprom_read_word(&nvfrec);
} else {
frec = 879 + 2 * (uint16_t)(PINC & 0x7f);
}
ds = calcds(frec);
funmain = pll_main;
funinter = pll_inter;
}
void debug_main() {}
void debug_inter()
{
OCR2 = (uint8_t)(acc >> 24);
if(TIFR & _BV(ICF1)) {
TIFR |= _BV(ICF1);
contvco = ICR1;
dif = contvco - ucontvco;
ucontvco = contvco;
error = ((int32_t)dif * (int32_t)(BITS_FREC) * (int32_t)((ESCALA) / (DIV_HW))) - ds;
}
acc &= 0x00ffffff;
acc += vco;
11
2011, La kehuelga radio.
}
void modo_debug()
{
amp = 0x00;
acc = 0x80000007;
funmain = debug_main;
funinter = debug_inter;
}
int32_t calcds(int16_t frec)
{
ldiv_t debe_ser;
int32_t dsint;
debe_ser = ldiv(((long)(FREC_CPU)*(long)(ESCALA)),(long)frec);
dsint = debe_ser.quot * (BITS_FREC);
debe_ser = ldiv((debe_ser.rem * (BITS_FREC)),(long)frec);
dsint += debe_ser.quot;
return dsint;
}
4.2. modos.h
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODOS_H
#define MODOS_H
/* para definir un modo, hay que escribir 3 elementos:
1. las funciones que corren en main y en la interrupción del pwm. Estas 2
12
2011, La kehuelga radio.
funciones tienen la forma
void nombre_main(void)
void nombre_inter(void)
2. una función para inicializar el modo, con la forma
void modo_nombre(void)
3. Un comando del puerto serial definido en serial.rl para entrar en el
modo. Y quizás más comandos para usarlo.
Para ver ejemplos, mira los que están en serial.rl y modos.c
*/
extern void modo_debug();
extern void modo_pll();
extern void (*funinter)(), (*funmain)();
extern uint8_t pwmsema, estado, vestado, amp;
extern int16_t frec;
extern uint16_t veces, dif;
extern int32_t ds;
extern int32_t error;
extern uint32_t vco;
extern uint16_t nvfrec __attribute__((section (".eeprom")));
extern uint8_t nvamp __attribute__((section (".eeprom")));
extern uint8_t nvai __attribute__((section (".eeprom")));
extern uint8_t nvfi __attribute__((section (".eeprom")));
#endif
4.3. serial.h
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
13
2011, La kehuelga radio.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERIAL_H
#define SERIAL_H
extern uint8_t *btx, *brx, bufrx[], buftx[];
void init_UART();
void init_scaner();
void bufrx_inicio();
void envia_UART();
void leer_cmds();
#endif
4.4. serial.rl
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* -*-c-*- */
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "vaca.h"
14
2011, La kehuelga radio.
#include "modos.h"
/* para transmitir datos solo es necesaria la función printf */
char *btx, *brx, bufrx[(CARS_BUFRX)];
char buftx[(CARS_BUFTX)] = "La Vaca: Muuuu!\r";
int8_t cs, act, hay=0;
char *ts, *te=0, *p=bufrx, *pe=bufrx, *eof=0;
uint8_t resadch, resadcl, bitc;
uint16_t argnum;
uint32_t argnum32;
%%{
machine cmds;
action err_cmd {
strcat(buftx, "KE?\r");
}
main := |*
# Cambiar la Amplitud:
( [Aa] (xdigit{2} @{sscanf((ts+1),"%02x", &argnum);}) (’\r’)) =>
{
amp = (uint8_t)argnum;
OCR0 = amp;
sprintf((buftx+strlen(buftx)), "A%02X\r", amp);
};
# Reportar la Amplitud:
( [Aa] (’?’) (’\r’)) =>
{
sprintf((buftx+strlen(buftx)), "A%02X\r", amp);
};
# Guardar la Amp. en la EEPROM:
( [Gg] [Aa] (’\r’)) =>
{
eeprom_write_byte(&nvamp, amp);
sprintf((buftx+strlen(buftx)), "GA%02X\r", amp);
};
# Restaurar la Amp. de la EEPROM:
( [Rr] [Aa] (’\r’)) =>
{
amp = eeprom_read_byte(&nvamp);
15
2011, La kehuelga radio.
_delay_us(100);
OCR0 = amp;
sprintf((buftx+strlen(buftx)), "RA%02X\r", amp);
};
# Amplitud de Inicio = Memoria
# (si dipsw #7 = 1, cuando estado = 1, la amplitud se inicia con el valor de la nvram):
( [Ii] [Aa] [Mm] (’\r’) ) =>
{
eeprom_write_byte(&nvai, ’M’);
sprintf((buftx+strlen(buftx)), "IAM\r");
};
# Amplitud de Inicio = cero
# (si dipsw #7 = 1, cuando estado = 1, la amplitud no se prende sola):
( [Ii] [Aa] (’0’) (’\r’) ) =>
{
eeprom_write_byte(&nvai, 0x00);
sprintf((buftx+strlen(buftx)), "IA0\r");
};
# Reportar fuente de la amplitud de inicio:
( [Ii] [Aa] (’?’) (’\r’) ) =>
{
argnum = eeprom_read_byte(&nvai);
sprintf((buftx+strlen(buftx)), "IA%1c\r", (argnum)? ’M’ : ’0’);
};
# Cambiar la Frecuencia:
( [Ff] (digit{4}) @{sscanf((ts+1), "%04d", (int *)&argnum);} (’\r’)) =>
{
if((argnum >= 879) && (argnum <= 1079)) {
veces = 0;
estado = 0;
frec = argnum;
ds = calcds((uint16_t)frec);
sprintf((buftx+strlen(buftx)), "F%04d\r", frec);
} else {
sprintf((buftx+strlen(buftx)), "ERROR: Frec. MALA!\r");
}
};
# Reportar la Frecuencia:
( [Ff] (’?’) (’\r’)) =>
{
sprintf((buftx+strlen(buftx)), "F%04d\r", frec);
16
2011, La kehuelga radio.
};
# Guardar la frecuencia seleccionada en la EEPROM:
( [Gg] [Ff] (’\r’)) =>
{
eeprom_write_word(&nvfrec, frec);
sprintf((buftx+strlen(buftx)), "GF%04d\r", frec);
};
# Restaurar la frecuencia de la EEPROM:
( [Rr] [Ff] (’\r’)) =>
{
argnum = eeprom_read_word(&nvfrec);
if((argnum >= 879) && (argnum <= 1079)) {
veces = 0;
estado = 0;
frec = argnum;
ds = calcds((uint16_t)frec);
sprintf((buftx+strlen(buftx)), "RF%04d\r", frec);
} else {
sprintf((buftx+strlen(buftx)), "ERROR: Frec. MALA!\r");
}
};
# Frecuencia de inicio de los dipswitch:
( [Ii] [Ff] [Ss] (’\r’) ) =>
{
eeprom_write_byte(&nvfi, 0x00);
sprintf((buftx+strlen(buftx)), "IFS\r");
};
# Frecuencia de inicio de la nvram:
( [Ii] [Ff] [Mm] (’\r’) ) =>
{
eeprom_write_byte(&nvfi, 0x01);
sprintf((buftx+strlen(buftx)), "IFM\r");
};
# Reportar fuente de la frecuencia de inicio:
( [Ii] [Ff] (’?’) (’\r’) ) =>
{
argnum = eeprom_read_byte(&nvfi);
sprintf((buftx+strlen(buftx)), "IF%1c\r", (argnum) ? ’M’ : ’S’);
};
# Reportar los interruptores:
17
2011, La kehuelga radio.
( [Ss] (’?’) (’\r’)) =>
{
sprintf((buftx+strlen(buftx)), "S%02X\r", leer_dipsw());
};
# Cambiar un pin de control:
( [Pp] ([0-3] @{argnum = *(ts+1) - ’0’;}) ([01] @{bitc = *(ts+2);}) (’\r’) ) =>
{
if(bitc - ’0’) {
PINES_CONTROL |= _BV(PCIZQ + (uint8_t)argnum);
} else {
PINES_CONTROL &= ~(_BV(PCIZQ + (uint8_t)argnum));
}
sprintf((buftx+strlen(buftx)), "P%1X%1c\r", argnum, bitc);
};
# Reportar un pin de control:
( [Pp] ([0-3] @{argnum = *(ts+1) - ’0’;}) (’?’) (’\r’) ) =>
{
printf((buftx+strlen(buftx)), "P%1X%1c\r",
argnum, (PINES_CONTROL & _BV(PCIZQ + argnum)) ? ’1’ : ’0’);
};
# Reportar un canal del ADC:
( [Vv] ([0-7] @{sscanf((ts+1),"%1x", &argnum);}) (’?’) (’\r’) ) =>
{
ADMUX &= 0xf8;
ADMUX |= ((uint8_t) argnum);
/* un poco más tiempo para el muestreo */
_delay_us(100);
ADCSRA |= _BV(ADSC);
loop_until_bit_is_clear(ADCSRA, ADSC);
resadcl = ADCL;
resadch = ADCH;
sprintf((buftx+strlen(buftx)), "V%1X%01X%02X\r", argnum, resadch, resadcl);
};
# Cambiar el vco:
( [Pp] [Vv] (xdigit{8} @{sscanf((ts+2),"%08lx", &argnum32);}) ’\r’) =>
{ /* espera la próxima consulta del UART antes de cambiar el
apuntador del bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
vco = argnum32;
sprintf((buftx+strlen(buftx)), "PV%08lX\r", argnum32);
18
2011, La kehuelga radio.
};
# Reportar el vco:
( [Pp] [Vv] ’?’ ’\r’) =>
{ /* espera la próxima consulta del UART antes de cambiar el
apuntador del bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
argnum32 = vco;
sprintf((buftx+strlen(buftx)), "PV%08lX\r", argnum32);
};
# Reportar el error:
( [Pp] [Ee] ’?’ ’\r’) =>
{ /* espera la próxima consulta del UART antes de cambiar el
apuntador del bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
argnum32 = error;
sprintf((buftx+strlen(buftx)), "PE%08lX\r", argnum32);
};
# Reportar el contador:
( [Pp] [Cc] ’?’ ’\r’) =>
{ /* espera la próxima consulta del UART antes de cambiar el
apuntador del bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
argnum = dif;
sprintf((buftx+strlen(buftx)), "PC%04d\r", argnum);
};
# Reportar el estado del pll::
( [Ee] ’?’ ’\r’) =>
{
sprintf((buftx+strlen(buftx)), "E%1X\r", estado);
};
# Cambiar al modo debug:
( [Mm] [Dd] ’\r’ ) =>
{
cli();
modo_debug();
19
2011, La kehuelga radio.
sei();
strcat(buftx, "MD\r");
};
# Cambiar al modo pll:
( [Mm] [Pp] ’\r’ ) =>
{
cli();
modo_pll();
sei();
strcat(buftx, "MP\r");
};
*|;
}%%
%% write data;
void init_scaner()
{
ts = bufrx;
te=0;
p=bufrx;
pe=bufrx;
eof=0;
%% write init;
}
void init_UART()
{
UBRRH = (uint8_t)((BAUD) >> 8);
UBRRL = (uint8_t)(BAUD);
UCSRB = (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << URSEL) | (3 << UCSZ0);
brx = bufrx;
btx = buftx;
}
void envia_UART()
{
/* UART TX: */
if(*btx) {
if(UCSRA & (1<<UDRE)) {
UDR = *btx++;
}
20
2011, La kehuelga radio.
} else {
btx = buftx;
*btx = 0;
}
}
void bufrx_inicio()
{
uint8_t bipwmsema;
/* espera una interrupción de captura */
bipwmsema = pwmsema;
while(pwmsema == bipwmsema)
;
brx = p = pe = bufrx;
}
void err_bufrx()
{
bufrx_inicio();
strcat(buftx, "ERROR: BUFRX LLENO!\r");
}
void leer_cmds()
{
uint8_t lcpwmsema;
int8_t espacio=((CARS_BUFRX)-hay);
/* ¿hay algo nuevo? */
if(pe == brx) return;
/* error, se ha llenado el bufrx: */
if(espacio == 0) {
err_bufrx();
return;
}
/* espera la próxima consulta del UART antes de cambiar el apuntador del
bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
pe = brx;
%%write exec;
21
2011, La kehuelga radio.
if(cs == cmds_error) {
strcat(buftx, "KE?\r");
init_scaner();
bufrx_inicio();
}
if(ts == 0) {
hay = 0;
bufrx_inicio();
}
else {
/* espera la próxima consulta del UART antes de cambiar el apuntador del
bufrx */
lcpwmsema = pwmsema;
while(pwmsema == lcpwmsema)
;
hay = brx - ts;
if(brx-bufrx > 12) {
brx = bufrx + hay;
memmove(bufrx, ts, hay);
te = bufrx + (te-ts);
p = bufrx +(p - ts);
ts = bufrx;
}
}
}
4.5. vaca.c
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
22
2011, La kehuelga radio.
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "vaca.h"
#include "serial.h"
#include "modos.h"
/*
FUSES =
{
.low = 0xff,
.high = (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_SPIEN & FUSE_JTAGEN & FUSE_OCDEN)
};
*/
void init_pines()
{
DDRB |= _BV(PB0);
PORTB &= ~_BV(PB0);
PINES_CONTROL &= ~(0x0f << (PCIZQ));
PC_DDR |= (0x0f << (PCIZQ));
}
void init_dipsw()
{
/* activar pull-ups para el dipswitch: */;
SFIOR &= ~_BV(PUD);
DDRC = 0;
PORTC = 0xff;
PINC = 0xff;
}
void init_adc()
{
DDRA = 0;
PORTA = 0;
ADMUX = (ADCREF);
ADCSRA = (ADCPRE);
/* una conversión para tirar */
23
2011, La kehuelga radio.
ADCSRA |= _BV(ADSC);
}
void init_timers()
{
DDRB |= _BV (PB3);
DDRD |= _BV (PD7);
PORTB |= _BV (PB3);
PORTD |= _BV (PD7);
TCCR1A = 0x0;
TCCR1B = 0x01;
TCCR2 = 0x61;
TCCR0 = 0x69;
TIMSK = 0x40; /* cambia a 0x60 para habilitar capture de timer1 */
}
uint8_t leer_dipsw()
{
return (PINC);
}
ISR(BADISR_vect)
{
}
/* el timer2 genera el pwm para controlar la frecuencia */
ISR(TIMER2_OVF_vect)
{
(*funinter)();
/* UART rcp: */
if(UCSRA & (1<<RXC)) {
*brx++ = UDR;
}
pwmsema++;
}
int main()
{
/* inicialización de los periféricos */
init_pines();
24
2011, La kehuelga radio.
init_adc();
init_dipsw();
init_timers();
init_UART();
/* scaner de los comandos que llegan por el puerto serial */
init_scaner();
/* modo inicial: */
modo_pll();
sei();
while (1) {
leer_cmds();
envia_UART();
(*funmain)();
}
return 0;
}
4.6. vaca.h
/*
Copyright 2010, la kehuelga radio.
This program is free software: you can redistribute it and/or modify qit under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef VACA_H
#define VACA_H
#define F_CPU 16000000UL
/* estado inicial programado en la lnvram: */
#define NV_FREC 1029
25
2011, La kehuelga radio.
#define NV_AMP 0xff
#define NV_IF 0x01
#define NV_IA ’M’
/* valores para el pll */
#define KV 1
#define KS 16
#define KRAPIDO 8
/* unos valores para el reloj de UART, UBRR, con fosc=16MHz, UB2x = 0 */
#define BAUD_2400 416
#define BAUD_4800 207
#define BAUD_9600 103
#define BAUD_19200 51
#define BAUD_38400 25
#define BAUD BAUD_9600
/* ref defs en ADMUX: */
#define ADCREF _BV(REFS0)
/* ADC preescaler etc en ADCSRA */
#define ADCPRE _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0)
/* pines para controlar otros equipos */
#define PINES_CONTROL PORTD
#define PC_DDR DDRD
#define PCIZQ 2
/* tamaños de los buffers */
#define CARS_BUFTX 32
#define CARS_BUFRX 32
/* valor máximo del error del VCO para considerar fija la frecuencia */
#define ERROR_MAX 5000000
/* cuantas veces el error del VCO tiene que ser menor que ERROR_MAX para
considerar fija la frecuencia */
#define ERROR_ESPERA 300
/* frecuencia del cpu en multiplos de 100kHz: */
#define FREC_CPU 160
/* divisor de vco en hardware: */
#define DIV_HW 4096
26
2011, La kehuelga radio.
/* Potencia mínima de 2 más grande que la frec. máxima en multiplos de
100kHz: */
#define BITS_FREC 0x400
/* factor escalador de frec. para aprovechar la precisión máxima de un
int32_t: */
#define ESCALA 0x800000
int32_t calcds(int16_t frec);
uint8_t leer_dipsw();
#endif
4.7. Makefile
###############################################################################
# La vaca: MUUUU! la vaca
###############################################################################
## General:
PROJECT = vaca
MCU = atmega32
TARGET = vaca.elf
CC = avr-gcc
###############################################################################
# Opciones para los varios programadores / debug:
###############################################################################
## HFUSE debe ser 0x10 para usar el JTAG, y 0xd8 para usar los dipswitch.
## OR con 0x01 para deshabilitar el bootloader;
## OR con 0x02 para tener espacio de bootloader de 1k en lugar de 2k;
## AND con 0xf7 para preservar el eeprom a pesar del "chip erase";
## LOCK totalmente deshabilitado es 0xff;
## OR con 0x7f para proteger el bootloader (deshabilitar la instrucción SPM
## en la sección del bootloader)
PORT=’/dev/ttyUSB0’
BAUD=9600
HEXFILE=vaca.hex
EEPROMFILE=vaca.eep
PROGRAMMER=avr109
DIRBOOT="avrprog_boot_v0_85"
# Deshabilita el modo seguro, el bootloader no podrá restaurar los fusibles
27
2011, La kehuelga radio.
# de ningun modo
DIS_SAVE=-u
## Opciones de Ragel:
RAGEL_OPCIONES = -C -G1
## Opciones comunes a las reglas para compilar, ligar y ensamblar
COMMON = -mmcu=$(MCU)
## Opciones de compilación
CFLAGS = $(COMMON)
CFLAGS += -Wall -pedantic -g -O3 -funsigned-char -funsigned-bitfields \
-fpack-struct -fshort-enums
CFLAGS += -Wp,-M,-MP,-MT,$(*F).o,-MF,dep/$(@F).d
## Banderas del ensamblador
ASMFLAGS = $(COMMON)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Banderas del linker
LDFLAGS = $(COMMON)
LDFLAGS += -lm
## Banderas para producir un archivo Intel Hex
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0
INCLUDES = -I/usr/avr/include/
## Objetos necesarios para ligar
OBJECTS = vaca.o serial.o modos.o
##
all: $(TARGET) vaca.hex vaca.eep
boot:
$(MAKE) -C $(DIRBOOT)
programar: all
avrdude $(DIS_SAVE) -p $(MCU) -P $(PORT) -c $(PROGRAMMER) -b $(BAUD) \
-v -U flash:w:$(HEXFILE) -U eeprom:w:$(EEPROMFILE)
## Compilar
28
2011, La kehuelga radio.
vaca.o: vaca.c
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
modos.o: modos.c
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
serial.o: serial.c
$(CC) $(INCLUDES) $(CFLAGS) -O0 -c $< -o $@
# Ragel:
serial.c: serial.rl
ragel $(RAGEL_OPCIONES) $<
## Ligar
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
%.hex: $(TARGET)
avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET)
avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@
%.lss: $(TARGET)
avr-objdump -h -S $< > $@
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) vaca.elf serial.c dep/ vaca.hex vaca.eep
## Otras dependencias
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
2011. Publicado por la kehuelga radio, bajo la licencia Creative Commons (Atribución – No comercial– Licenciamiento Recíproco 2.5).Disponible en http://creativecommons.org/licenses/by-nc-sa/2.5/mx
29