Professional Documents
Culture Documents
Elementos básicos
/* Este es un comentario */
// Este es un comentario
Inicio y fin de bloque, permite agrupar un número de instrucciones las que pueden
ser ejecutadas con cierta prioridad. Se usa {para iniciar bloque y } para finalizar
bloque.
{ // Inicio de bloque
// Instrucciones
} // Final de bloque
Tipo, es una palabra reservada definida que indica el tipo de variable que se ha de
definir y su alcance numérico, esto de acuerdo a la Tabla 1.
Tabla 1.
Char j,i;
Float x,r;
Long a,b,c,d;
Void función_1 ( )
}
Void main ( )
} Void función_2 ( )
}
Fig.1. Esquema de un programa
El siguiente código fuente contempla la declaración de las variables y el módulo
principal.
Void main ()
Void main ()
Void main ( )
Void funcion_1 ( )
{
}
Void funcion_2 ( )
Instrucciones básicas
Asignaciones
Void main ( )
i=10;
j=20;
Los valores asignados a las variables tipo char o int pueden tener distintos
formatos ya sea decimal, octal, hexadecimal o binario. Esto es muy útil dado que
en el más bajo nivel siempre se trabaja en binario.
Independencia de la representación
Char dato;
Dato = 49;
Dato
0 0 1 1 0 0 0 1
Formatos de asignación
1Tabla 2.
Note que el número codificado hexadecimal comienza con 0x, es decir 31H será
0x31 y el binario comienza con 0b, es decir, 00110001 será 0b00110001 (este
segundo formato corresponde al entregado por el compilador CCS. El caso de las
variables tipo char se tiene el siguiente ejemplo, se inicializa una variable con el
valor 1 ASCII, sin embargo esto se puede realizar de varias formas.
Char c;
Void main ( )
c=0x31; // en hexa
c=49; // en decimal
Int d;
Long x;
Void main()
d=0xA031; // en hexa
x=49000L; // en long
Operaciones Matemáticas
Char i,j, k;
Void main ( )
i=10;
j=20;
}
Operaciones Lógicas
Se realizan con variables enteras y afectan directamente al bit del dato, se tienen
los operadores lógicos y los desplazamientos a la Izquierda y a la derecha.
Char i,j, k;
Void main ( )
}
Sentencias de control
Tabla 3.
== Igual
!= Distinto
&& Operador Y
|| Operador O
La condición verdadera puede ser también de la siguiente forma: Si se quiere
preguntar por una variable que es mayor que cero solo se coloca la variable si se
quiere preguntar si es falsa entonces se niega, usando el operador !.
Sentencia if-else
Char i,j,k,h;
Void main ( )
i=10;
j=20;
else k=2;
if(i==10) {
k=20;
j=10;
else
k=40;
j=20;
h=k+j;
k=20;
j=10;
Sentencia while
While (condición) {
instrucción_1;
...
Instrucción_n;
Char i,j,k,h;
Void main ( )
{
h=k+j;
k--;
i=k;
En el ejemplo sólo se evalúa la condición verdadera, pero nunca sele del ciclo.
Char i,j,k,h;
Void main()
i=1;
k=40;
j=20;
h=k+j;
Para salir de un ciclo donde no existe posibilidad de que la condición sea alterada,
se puede usar la sentencia break.
Char i,j,k,h;
Void main ( )
i=0;
While (1)
{
i++;
Void main ()
Char i;
i=10;
do
i--;
Esta instrucción se usa cuando se deben seleccionar entre varias opciones tipo
numéricas. Es básicamente un selector.
Char c;
Void main ()
Switch(c)
{
Break;
Break;
Break;
Sentencia for
For(expr_1;expr_2;expr_3)instrucción;
For(expr_1;expr_2;expr_3)
instrucción_1;
...
Instrucción_n;
Tabla 4.
Descripción
expr_3 Indica lo que hay que hacer cada vez que se termina el bucle,
puede haber varias instrucciones separadas por una coma.
El código fuente muestra que la variable i se inicializa en cero, una vez realizadas
las instrucciones dentro del bloque, en este caso, hacer j igual a cero, se ejecuta la
instrucción incremento en uno para la variable i.
Char i,j;
Void main ( )
Las funciones que no devuelven valor son declaradas usando la palabra Void junto
al nombre de ésta, los paréntesis y el punto y coma ;. Son llamadas directamente
a través del nombre o identificador correspondiente. La siguiente función primero
se declara para luego ser llamada desde el programa principal no recibe
argumento ni tampoco retorna un valor.
Void main ( )
Void activar_sensores ( )
// Instrucciones
Void activar_sensores ( )
// Instrucciones
}
Void main()
Las que devuelven valor deben ser llamadas a través de una asignación, en donde
el nombre de la función es asignado a una variable que recibirá el resultado
devuelto por la función. La función en este caso debe ser declarada (o definida)
considerando el tipo de valor que ha de retornar o devolver. La siguiente función
es declarada tipo char, retorna el valor correspondiente, por lo tanto al ser
llamada, la función inmediatamente debe ser asignada a una variable del mismo
tipo a ser retornada.
Char lee_sensores ( );
Void main ( )
Char sensor;
Char lee_sensores ( )
Char x;
// Instrucciones
Char x;
// Instrucciones
Void main ( )
Char sensor;
Para el paso de los argumentos, estos son definidos entre los paréntesis de la
función considerando el tipo de la variable requerida. La siguiente función recibe
un parámetro tipo char por valor y no retorna valor.
// Instrucciones
Void main()
Char sensor;
}
El siguiente ejemplo muestra una función que recibe parámetros y retorna un
valor. El valor retornado a su vez puede ser usado por una sentencia de control
para tomar alguna decisión.
Return (status);
Void main()
Char estado_com;
While (1)
estado_com=enviar (0xaa);
if(estado_com!=1) break;
Punteros
¿Qué quiere decir puntero a char o puntero a int ?. Simple, cuando un puntero a
char se incrementa, la dirección almacenada en la variable se incrementa en una
posición de memoria en cambio en un puntero a int se incrementa de 2 posiciones.
En el caso de que fuera a una variable tipo long, la dirección se incrementaría en 4
posiciones de memoria.
Void main ( )
void main()
Uno de los usos de los punteros es para el paso de variables por referencia a una
función, es decir, el valor de la variable que se pasa como argumento a la función
cambia si es que en el interior de la función cambia.
Esto ocurre a que en vez de pasar el valor del argumento a la función, se pasa su
dirección. Esto se podrá realizar si se utiliza un puntero. El siguiente ejemplo es
solo ilustrativo, ya que si se va a devolver un valor, puede usar la instrucción
Return ().
*p=(*p)*2;
Void main ( )
Dato =10;
Pdato =&dato;
Duplicar (pdato);
Arreglos y matrices
Char cadena [10];// define una var string llamada cadena de 10 char
Int datos [15]; // define una var string llamada datos de 15 int
Los arreglos pueden contener números o caracteres, pueden ser usados para
manejo de cadenas de caracteres o string. Es conveniente siempre inicializar con
un valor los arreglos. El primer elemento del arreglo corresponderá al almacenado
en la posición 0 y el n-ésimo elemento corresponderá al almacenado en la
posición n-1 del arreglo. Cuando se definen los arreglos, estos ocupan zonas
completas de memoria, con direcciones consecutivas.
Inicialización de arreglos
Void main ()
Los arreglos pueden ser inicializados con mensajes, estos son formados por
cadenas de caracteres llamados cadenas o string. Habitualmente, se usan las
comillas para establecer o limitar el mensaje.
// C estándar
Char x [7]={"Juan\xd"};
Char c[]={"popo"};
H O L A 0X00
msg[0] msg[1] msg[2] msg [3] msg[4]
Las cadenas comúnmente pueden ser usadas con caracteres de control tales
como el 0x0d (CR) o el 0x0a (LF). Estos caracteres pueden ser incorporados al
final de la cadena en forma directa en la posición correspondiente o de la siguiente
forma:
Arreglos y punteros
Los punteros pueden ser inicializados con la dirección inicial del arreglo, de esta
forma se tiene
//Formas equivalentes
Pcad=&cad [0];
Pcad=&cad;
Pcad=cad;
Los punteros pueden usarse para apuntar al primer elemento de una cadena y se
pueden inicializar de acuerdo al siguiente ejemplo.
Char *p="chao";
Char x;
While (1)
x=*porig;
*pdest=x;
If (*porig==0x00)
Break;
Pdes t++;
Porig ++;
Void main ( )
Copiando del contenido de una cadena en otra, está codificado para CCS
Char x;
While (1)
x=*po;
*pd=x;
if(*po==0x00) break;
pd++;
po++;
Void main ( )
Cad [0]='C';
Cad [1]='H';
cad [2]='A';
cad [3]='O';
copy_str (msg,cad);
Char *pcad=”HOLA\x0”;
Char i;
i=0;
While (i)
{
Void main ( )
Char msg[10]={“HOLA”};
Char *pm;
pm=&msg[0];
enviar_msg (pm);
}
El μControlador y el compilador CCS
Arquitectura del μC
PORT B
CPU
PORT C
U1
X1 9
OSC1/CLKIN RB0/INT
21
CRYSTAL 10 22
OSC2/CLKOUT RB1
23
RB2
C1 2
RA0/AN0 RB3/PGM
24
22uF 3 25
RA1/AN1 RB4
4 26
RA2/AN2/VREF-/CVREF RB5
C2 5
RA3/AN3/VREF+ RB6/PGC
27
22uF 6 28
RA4/T0CKI/C1OUT RB7/PGD
7
RA5/AN4/SS/C2OUT
11
RC0/T1OSO/T1CKI
1 12
MCLR/Vpp/THV RC1/T1OSI/CCP2
13
RC2/CCP1
R1 RC3/SCK/SCL
14
15
RC4/SDI/SDA
16
R RC5/SDO
17
RC6/TX/CK
18
RC7/RX/DT
PIC16F873A
Entorno de desarrollo
PRACTICA #1
(Prender y Apagar un LED)
2. Ahora debemos indicarle al programa el valor del cristal que vamos a utilizar
esto se hace en la siguiente instrucción: #use delay(clock=xxxxxx), en nuestro
caso el cristal será de 8Mhz por lo tanto la instrucción queda de la siguiente
manera: #use delay(clock=8000000), ya tenemos dos instrucciones.
#include <18f2550.h>
#use delay(clock=8000000)
3. Después de escoger el micro y el valor del cristal empezamos con la función
principal, se denomina función principal porque es el inicio de todo programa; al
iniciar una rutina el programa siempre va a buscar esta función y a empezar desde
la primera instrucción que este contenga, esta función se escribe de la siguiente
manera: void main (void), y lo que se escriba dentro de esta función tiene que ir
dentro de unos corchetes { }, mas adelante se explicara un ejemplo.
#include <18f2550.h>
#use delay(clock=8000000)
4. Ya todo está listo ahora encendamos el led; podemos escoger cualquier puerto
y cualquier pin, nosotros usaremos el puerto B y el pin B0, usamos la instrucción
output_high(pin_b0); , esta instrucción nos enciende el led; output significa salida,
high significa alto, y pin_b0 es el pin que vamos a utilizar; uniéndola significa que a
la salida del pin_b0 hay un alto (voltaje positivo), que permite encender el led.
#include <18f2550.h>
#use delay(clock=8000000)
output_high(pin_b0);
#include <18f2550.h>
#use delay(clock=8000000)
output_high(pin_b0);
delay_ms(1000);
#include <18f2550.h>
#use delay(clock=8000000)
output_high(pin_b0);
delay_ms(1000);
outout_low(pin_b0);
delay_ms(1000);
while(true), esta instrucción hace que lo que esta dentro de ella siempre se va a
hacer hasta que la condición sea falsa, pero como nosotros le dimos la orden de
que la condición es verdadera siempre me va a repetir la rutina de prender y
apagar el led; y lo que se escriba dentro de este while también debe ir dentro de
unos corchetes { }.
#include <18f2550.h>
#use delay(clock=8000000)
while(true)
output_high(pin_b0);
delay_ms(1000);
outout_low(pin_b0);
delay_ms(1000);
*Nota:
*Forma 1
1. Iniciamos indicando que micro vamos a trabajar y el valor del cristal a utilizar.
#include <18f2550.h>
#use delay(clock=8000000)
#include <18f2550.h>
#use delay(clock=8000000)
output_high(pin_b0);
delay_ms(1000);
outout_low(pin_b0);
delay_ms(1000);
Pero nosotros necesitamos hacerlo 8 veces y lo único que vamos a cambiar es el
pin, por ejemplo: pin_b0, pin_b1, pin_b2….. y esto lo haremos hasta llegar al pin
b7.
#include <18f2550.h>
#use delay(clock=8000000)
output_high(pin_b0);
delay_ms(1000);
outout_low(pin_b0);
delay_ms(1000);
output_high(pin_b1);
delay_ms(1000);
outout_low(pin_b1);
delay_ms(1000);
output_high(pin_b2);
delay_ms(1000);
outout_low(pin_b2);
delay_ms(1000);
output_high(pin_b3);
delay_ms(1000);
outout_low(pin_b3);
delay_ms(1000);
output_high(pin_b4);
delay_ms(1000);
outout_low(pin_b4);
delay_ms(1000);
output_high(pin_b5);
delay_ms(1000);
outout_low(pin_b5);
delay_ms(1000);
output_high(pin_b6);
delay_ms(1000);
outout_low(pin_b6);
delay_ms(1000);
output_high(pin_b7);
delay_ms(1000);
outout_low(pin_b7);
delay_ms(1000);
4. Ya esta listo el programa solo que tenemos el mismo problema que se nos
presento en el programa pasado, y como recordaremos solo le tenemos que
agregar un “while” y se soluciona este problema.
#include <18f2550.h>
#use delay(clock=8000000)
While(true)
output_high(pin_b0);
delay_ms(1000);
outout_low(pin_b0);
delay_ms(1000);
output_high(pin_b1);
delay_ms(1000);
outout_low(pin_b1);
delay_ms(1000);
output_high(pin_b2);
delay_ms(1000);
outout_low(pin_b2);
delay_ms(1000);
output_high(pin_b3);
delay_ms(1000);
outout_low(pin_b3);
delay_ms(1000);
output_high(pin_b4);
delay_ms(1000);
outout_low(pin_b4);
delay_ms(1000);
output_high(pin_b5);
delay_ms(1000);
outout_low(pin_b5);
delay_ms(1000);
output_high(pin_b6);
delay_ms(1000);
outout_low(pin_b6);
delay_ms(1000);
output_high(pin_b7);
delay_ms(1000);
outout_low(pin_b7);
delay_ms(1000);
Nota:
-Recordamos que este es un ejemplo de cómo prender y apagar varios leds, pero
se puede hacer cualquier tipo de secuencia todo es cuestión de creatividad.
*Esa es una forma de realizar una secuencia de leds ahora vamos a aprender otra
forma de hacer la misma secuencia.
*Forma 2
#include <18f2550.h>
#use delay(clock=8000000)
-Una variable es donde podemos almacenar ciertos valores que a medida que el
programa avance estos van a ir cambiando su valor, una variable se puede llamar
de cualquier forma, existen varios tipos de variables, de 8 bits, de 16 bits, y
variables decimales; estas variables se declaran de la siguiente forma:
*float xxxx; (esta es la única variable que trabaja con números decimales, aunque
también puede trabajar con números enteros, y trabaja cualquier cantidad de bits).
int x=1,aux[15];
La otra variable aux utiliza vectores en este caso son 14 vectores que se van a
usar pero tenemos que escribir una mas (15) para que el programa no marque
error.
#include <18f2550.h>
#use delay(clock=8000000)
int x=1,aux[15];
Entre las llaves se escribe el numero del vector, en nuestro caso son 14 vectores
por lo tanto van a haber 14 combinaciones diferentes.
En lo personal prefiero el código binario ya que se puede ver la secuencia que uno
esté realizando.
aux[2]=0b00000010;
aux[3]=0b00000100;
aux[4]=0b00001000;
aux[5]=0b00010000;
aux[6]=0b00100000;
aux[7]=0b01000000;
aux[8]=0b10000000;
aux[9]=0b01000000;
aux[10]=0b00100000;
aux[11]=0b00010000;
aux[12]=0b00001000;
aux[13]=0b00000100;
aux[14]=0b000000010;
#include <18f2550.h>
int x=1,aux[15];
aux[1]=0b00000001;
aux[2]=0b00000010;
aux[3]=0b00000100;
aux[4]=0b00001000;
aux[5]=0b00010000;
aux[6]=0b00100000;
aux[7]=0b01000000;
aux[8]=0b10000000;
aux[9]=0b01000000;
aux[10]=0b00100000;
aux[11]=0b00010000;
aux[12]=0b00001000;
aux[13]=0b00000100;
aux[14]=0b000000010;
En un for debemos indicar en que numero iniciamos la “cuenta”, hasta que numero
debe contar, y si queremos aumentar o disminuir. Recordemos que estos números
debemos almacenarlos en una variable.
Vamos a iniciar el for en 1, que cuente hasta 14 y que aumente; esto queda así:
for (x=1;x<=14;++x)
for (x=1;x<=14;++x)
{
output_b(aux[x]);
delay_ms(1000);
Aquí utilizamos nuestro aux, le indicamos al programa que a la salida del puerto B
ponga el valor del vector y el valor del vector está determinado por la variable x,
por lo tanto cada vez que se repita un for la x va aumentando de uno en uno y
cada repetición va siendo un vector diferente ya que cada vez la x va a tener un
valor diferente y siempre la salida al puerto B va cambiando prendiendo y
apagando los leds indicados.
#include <18f2550.h>
int x=1,aux[15];
aux[1]=0b00000001;
aux[2]=0b00000010;
aux[3]=0b00000100;
aux[4]=0b00001000;
aux[5]=0b00010000;
aux[6]=0b00100000;
aux[7]=0b01000000;
aux[8]=0b10000000;
aux[9]=0b01000000;
aux[10]=0b00100000;
aux[11]=0b00010000;
aux[12]=0b00001000;
aux[13]=0b00000100;
aux[14]=0b000000010;
while (true)
for (x=1;x<=14;++x)
output_b(aux[x]);
delay_ms(1000);