Professional Documents
Culture Documents
Sintaxis de programa
Estructura general: rs232_buffer.c
- Comentarios
- Definciones de datos
- Definiciones de funciones
Todo programa en C debe tener una función principal (main) que es el punto de partida de la ejecución del
progama.
Comentarios: rs232_buffer.c
Los caracteres entre /* y */ se ignoran al igual que los escritos después de // hasta que finalice la línea.
Cuando hay muchos archivos en un proyecto, todos pueden ser incluidos utilizando #INCLUDE en el archivo
main o en los sub-archivos mediante el linker incluido en el compilador. Por ejemplo, si tenemos los archivos
main.c, x.c, x.h, y.c, y.h y z.h en un proyecto:
En este ejemplo hay 8 archivos y una unidad de compilación. Main.c es el único archivo compilado.
Ejemplo:
Aquí tenemos un ejemplo de programa utilizando CCS C para leer unas muestras de un conversor analógico-
digital a través de RS-232:
#fuses XT,NOWDT,NOPROTECT,NOLVP // directiva del pre-procesador que define los fusibles del PIC
#use delay(clock=4000000) //directiva del pre-procesador que define la velocidad del reloj
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // directiva del pre-procesador que incluye las librerías
de RS-232
do { // do/while
min=255; // expresión
max=0;
valor = read_adc(); // esta función lee el valor digital del conversor analógico-digital
if(valor<min) // if
min=valor;
if(valor>max) // if
max=valor;
} while (TRUE);
Directivas
Las directivas/sentencias a tratar son: if, while, do, do-while, for, switch,
return y goto.
IF: rs232_buffer.c
if (condición 1)
instrucciones 1;
else
instruciones 2;
else-if: La directiva else-if se utiliza para realizar múltiples decisiones. La sintaxis es:
if (condición 1)
instrucciones 1;
else if (condción 2)
instruciones 2;
......
else
instrucciones n;
Se evaluan las condiciones en orden, si alguna es verdadera se ejecutan las instrucciones correspondientes, si
todas son falsas se ejecutan las instrucciones n.
Ejemplo:
if (y==5)
y=1;
else
y=y+1;
WHILE:
La sintaxis es:
while (condición)
instrucciones
Las instrucciones son ejecutadas mientras la condición es verdadera. Si la condición es falsa la ejecución del
programa continúa después de las instrucciones.
Ejemplo:
while (i<10)
i++
DO:
La sintaxis es:
do
instrucciones
while (condición)
Ejemplo:
do
i++
while (i<10)
DO-WHILE: se diferencia de los bucles for y while en que la condición se testea al final. Por lo tanto las
instrucciones se ejecutan al menos una vez.
La sintaxis es:
do
instrucciones
while (condición)
Ejemplo:
do
i++
while (i<10)
La sintaxis es:
instrucciones
expresión 1: inicialización
expresión 2: condición
expresión 1: re-inicialización
Ejemplo:
La sintaxis es:
switch (expresión) {
break;
........
default: instrucciones
break;
Cada caso(case) comienza donde hay un case y finaliza donde hay un break. Si no escribimos un break el
programa sigue con el siguiente case.
Ejemplo:
int numero;
switch( numero ) {
break;
break;
RETURN: permite una salida inmediata de un bucle, switch o función y siempre devuelve un valor.
La sintaxis es:
return (expresión);
Ejemplo:
return (1) ;
La sintaxis es:
goto etiqueta;
Ejemplo:
goto BUCLE ;
Expresiones
OPERADORES:
+ Suma
+= Suma y asignación , x += y, es lo mismo que x = x+y
&= And y asignación , x &= y, es lo mismo que x = x&y
& Operador de dirección
& And
^= And exclusivo y asignación , x ^= y, es lo mismo que x = x^y
^ And exclusivo
l= And inclusivo y asignación , x l= y, es lo mismo que x = xly
l And inclusivo
?: Operador de expresión condicional
-- Decremento
/= División y asignación, x /= y, es lo mismo que x = x/y
/ División
== Igualdad
> Mayor que
>= Mayor e igual que
++ Incremento
* Operador de indirección
!= Inigualdad
<<= Shift a la izquierda y asignación, x <<= y, es lo mismo que x = x<<y
< Menor que
<< Shift a la izquierda
<= Menor e igual que
&& AND lógico
! Negación logica
ll OR lógico
%= Módulo y asignación x %= y, es lo mismo que x = x%y
% Módulo
*= Multiplicación y asignación, x *= y, es lo mismo que x = x*y
* Multiplicación
~ Complemento a 1
>>= Shift a la derecha , x >>= y, es lo mismo que x = x>>y
>> Shift a la derecha
-> Operador de puntero a estructura
-= Resta y asignación
- Resta
sizeofDetermina el tamaño en bytes de un operando
PRECEDENCIA DE OPERADORES:
En precedencia descendente
(expr)
!expr ~expr ++expr expr++ - expr - -
-expr
(type)expr *expr &value sizeof(type)
expr*expr expr/expr expr%expr
expr+expr expr-expr
expr<<expr expr>>expr
expr<expr expr<=expr expr>expr expr>=expr
expr==expr expr!=expr
expr&expr
expr^expr
expr | expr
expr&& expr
expr || expr
expr ? expr: expr
lvalue = expr lvalue+=expr lvalue-=expr
lvalue*=expr lvalue/=expr lvalue%=expr
lvalue>>=expr lvalue<<=expr lvalue&=expr
lvalue^=expr lvalue|=expr expr, expr
Definciones de datos
TIPOS BÁSICOS :
Rango
Calificadores de tipos
unsigned
DECLARACIONES:
Una declaración especifica un calificador y un especifcador de tipo y es seguido por una lista de una o más
variables de ese tipo.
Ejemplo:
int a,b,c,d;
mibit e,f;
mibyte g[3][2];
char *h;
colores j;
static int i;
extern long j;
Dato constante:
El calificador CONST inserta las variables en la memoria de programa. Si se utiliza la palabra CONST antes
de un identificador, este es tratado coo una consante. Las constantes se inicializan y no pueden ser
modificadas en tiempo de ejecucuón.
El calificador ROM inserta datos en la memoria de programa (3 bytes por instrucción). La dirección utilizada
para ROM no es física.
Ejemplo:
cpac =string ;
La directiva #ORG puede ser utilizada para insertar constantes en un segmento de dirección especifico:
DIRECTIVA #ROM:
Ubicar un string:
FUNCIONES:
write_program_eeprom(dirección , dato);
DEFINICIÓN DE FUNCIONES:
- void
- especificador de tipo
- #separate
- #inline
- #int_..
Ejemplo:
...
lcd_putc ("Hola.");
Ejemplo:
#byte status = 3
#byte b_port = 6
#CASE: hace que el compilador sea sensible a mayusculas. Por defecto no lo es.
Ejemplo:
#case
int ESTADO;
void funcion() {
int estado;
...
#DEFINE:
La sintaxis es:
#define id texto
Se utiliza para reemplazar una cadena (id) por el texto desde ese punto del progama en adelante.
Ejemplo:
#define BITS 3
Las opciones dependen del dispositio utilizado. Algunas opciones comunes son:
· WDT, NOWDT
· PROTECT, NOPROTECT
· BROWNOUT, NOBROWNOUT
#IF expresión:
La sintaxis es:
#if expresión
código
código
#else // opcional
código
#endif
expresión es una expresión(condición) con constantes, operadores e/o identificadores del pre-procesador.
Ejemplo:
long valor;
#else
int valor;
#endif
#INCLUDE:
La sintaxis es:
#include <nombre_del_archivo>
Ejemplos:
#include <16F876.H>
#include <C:\misdocumentos\pic\ejemplo.C>
Estas directivas especifcan que la siguiente función es de interrupción . El compilador generará un código
para saltar a la función cuando se detecta la interrupción. Se genera un código para guardar y volver al estado
en que estaba la máquina antes de la interrupción.
Ejemplo:
#int_ad
manejo_adc() {
adc_activo=FALSE;
}
#USE DELAY: #use_delay (clock=velocidad) donde velocidad es una constante 1-100000000 (1 a 100MHz).
Le dice al compilador la velocidad del procesador y habilita la utilización de las funciones delay_ms() y
delay_us().
Ejemplo:
#use fast_io(A)
void main() {
output_low(PIN_B0);
output_low(PIN_B1);
....
#USE FIXED_IO: #use fixed_io (port_outputs=pin, pin?) donde port es A-G, pin es uno de los pines
definidos es dispositivo.h. Afecta a como el compilador generará código para las instrucciones de entrada y
salida. El método fijo hace que el compilador genere código para hacer que cada pin sea de entrada o salida
cada vez que se utilice.
#USE I2C:
Utiliza dos hilos para transmitir información. Uno para los datos (SDA) y otro para el reloj o clock (SCL). Un
tercer hilo de masa (GND) suele ser necesario.
Ejemplo de bus:
SDA y SCL so drenador abierto, por lo tanto son necesarias resistencias de pull-up.
Los dispositivos conectados al bus pueden ser MAESTRO o ESCLAVO y poseen una única dirección. El
maestro inicia el intercambio de datos y es el que genera la señal de clock (SCL).
Cada esclavo compara la dirección enviada por el maestro con su propia dirección. El esclavo seleccionado
envía un bit de ACK y entonces el maestro puede comenzar la comunicación. El maestro envía la dirección
del registro del esclavo que quiere leer(A0=0) o escribir(A0=1). El esclavo envía otro bit de ACK. El maestro
comienza a leer o escribir bytes (8 bits). Cada byte debe ser reconocido por un bit de ACK ya sea del maestro
o del esclavo.
A pesar de que el maestro controla la señal de clock, un esclavo de baja velocidad puede forzar el clock a
nivel lógico bajo. Entonces el maestro espera, en este momento no envía/recibe datos.
Cuando finaliza la comunicación, el maestro envía una condición de STOP y el bus queda libre.
I2C en CCS
Sintaxis: #use i2c(opciones)
donde las opciones van separadas por coma (,) y algunas pueden ser:
Funciones:
i2c_start : genera una condición de START. Después del START, el reloj se mantiene a nivel lógico bajo
hasta que se llame a la función i2c_write(). Si se produce un nuevo i2c_start() en la misma función antes que
se produzca un i2c_stop(), se genera un reinicio.
Sintaxis: i2c_start();
Ejemplo:
i2c_start();
i2c_start(); // Reinicio
i2c_stop();
i2c_read : lee un byte a través de la interfase I2C. En modo MASTER esta función generará el CLOCK y en
modo ESCLAVO esperará por el CLOCK.
Sintaxis:
data = i2c_read();
data=i2c_read(ack);
0 indica no ACK.
1 indica ACK.
Ejemplo:
i2c_start();
i2c_write(0xa1);
data1=i2c_read();
data2=i2c_read();
i2c_stop();
i2c_write : envía un byte a través de la interfase I2C. En modo MASTER esta función generará el CLOCK
con los fatos y en modo ESCLAVO esperará por el CLOCK del master.
Sintaxis:
i2c_write (data)
Ejemplo:
long comando;
...
i2c_start();
i2c_stop();
Sintaxis:
i2c_stop ()
Ejemplo:
i2c_start();
#USE STANDARD_IO: #use standard_io (port) donde port es A-J o todos. Afecta a como el compilador
generará código para las instrucciones de entrada y salida. Es el método por defecto.
Interrupciones
Las siguientes funciones permiten el manejo de interrupciones en los microcontroladores. Con estas
funciones, las interrupciones pueden ser habilitadas, deshabilitadas y borradas.
Funciones relevantes:
ext_int_edge(): habilta una interrupción externa por flanco, el cual puede ser de subida o bajada (L_TO_H o
H_TO_L)
clear_interrupt(): borra la bandera(flag) de interrupción. Puede ser utilizada si una isr(interrupt service
routine) global es utilizada o para prevenir que una interrupción sea servida.
Ejemplo:
#int_timer0
void timer0interrupt() // #int_timer asocia la siguiente funión con la rutina
// de servicio de interrupción que será llamada
enable_interrupts(TIMER0); // habilita la interrupción TIMER0
disable_interrtups(TIMER0);// deshabilita la interrupción TIMER0
clear_interrupt(TIMER0); // borra el flag de la interrupción TMER0
EJEMPLO
Descripción:
Este dispositivo tiene un registro de desplazamiento de 8 bits (entrada serial / salida paralela) que alimenta un
registro de almacenamiento de 8 bits del tipo D. El registro de almacenamiento posee 8 salidas (3 estados).
Relojes (clocks) independientes se utilizan para ambos registros (almacenamiento y desplazamiento) El
registro de desplazamiento tiene un pin para cascada.
Diagrama de pines :
Tabla de verdad :
Descripción de pines :
Pin: 10 Símbolo: SCLR negado Función: entrada de borrado del registro de desplazamiento
Diagrama en Proteus:
Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7
0 1 1 1 1 1 1 0 0
1 0 1 1 0 0 0 0 0
2 1 1 0 1 1 0 1 0
3 1 1 1 1 0 0 1 0
4 0 1 1 0 0 1 1 0
5 1 0 1 1 0 1 1 0
6 1 0 1 1 1 1 1 0
7 1 1 1 0 0 0 0 0
8 1 1 1 1 1 1 1 0
9 1 1 1 1 0 1 1 0
Programa en CCS :
#INT_EXT
void RB0_isr(){
AumentarCuenta();
}
void main(){
set_tris_a(0x00); // todas salidas
set_tris_b(0x01); // RB0 entrada, las demás salidas
port_b_pullups(TRUE);
enable_interrupts(int_ext);
ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
while(1){};
}
void AumentarCuenta(void){
int j,i;
for(j=0;j<8;j++){
if((TABLA[i]&mascara[j])==0){
output_low(DATA);
}
else{
output_high(DATA);
}
output_high(CLOCK);
output_low(CLOCK);
}
output_high(STROBE); //efectivizar valores enviados en
output_low(STROBE); //las salidas de los registros
i=i+1;
if(i==10){
i=0;
}
}