Programacion en C 2da Parte

10

Click here to load reader

Transcript of Programacion en C 2da Parte

Page 1: Programacion en C 2da Parte

PROGRAMAS CONVERSION EN C Muchos microcontroladores más nuevos tienen un reloj en tiempo real (RTC), donde se

guardan la fecha y hora, incluso cuando el equipo está apagado. Muy a menudo la RTC ofrece

la fecha y hora en BCD empaquetado. Para visualizarlos, sin embargo, hay que convertirlos a

ASCII. En esta sección se muestra la aplicación de la lógica y las instrucciones de rotación

utilizadas en la conversión de BCD y ASCII.

Números ASCII

En los teclados ASCII, cuando el "0" es presionado, la computadora proporciona el valor "0011

0000" (0x30). Similarmente proporciona el 0x31 (0011 0001) para la tecla "1", y así

sucesivamente, como se muestra a continuación:

Código ASCII de los dígitos 0-9

Tecla ASCII (hex) Binario BCD (desempaquetado)

O 0x30 011 0000 00000000

1 0x31 011 0001 00000001

2 0x 32 011 0010 00000010

3 0x 33 011 0011 00000011

4 0x 34 011 0100 00000100

5 0x 35 011 0101 00000101

6 0x 36 011 0110 00000110

7 0x 37 011 0111 00000111

8 0x 38 011 1000 0000 1000

9 0x 39 011 1001 0000 1001

Conversión de BCD empaquetado a ASCii

El RTC ofrece la hora del día (hora, minuto, segundo) y la fecha (año, mes, día) de forma

continua, independientemente de si la alimentación está encendida o apagada. Estos datos se

proporcionan en BCD empaquetado. Para convertir de BCD empaquetado a ASCII, primero

debe convertir a BCD desempaquetado. Entonces, el BCD desempaquetado se etiqueta con

011 0000 (0x30). Lo siguiente muestra la conversión de BCD empaquetado a ASCII.

BCD empaquetado BCD desempaquetado ASCII

0x29 0x02, 0x09 0x32, 0x39 00101001 00000010,00001001 00110010,00111001

Converslon ASCII a BCD empaquetado

Para convertir ASCII a BCD empaquetado, primero debe convertir a BCD desempaquetado

(para deshacerse del 3), y luego combinar los números para hacer BCD empaquetado. Por

ejemplo, 4 y 7 en el teclado da 0x34 y 0x37, respectivamente. El objetivo es producir 0x 47 o

"01000111", que está en BCD empaquetado.

Tecla ASCII BCD desempaquetado BCD empaquetado

4 0x34 00000100

7 0x37 00000111 01000111 or 0x47

Page 2: Programacion en C 2da Parte

Escribir Un programa para convertir BCD a ASCII 0x29 y mostrar los bytes en PORTB y PORTC

#include <avr/io.h>

int main (void)

{

unsigned char x, y;

unsigned char mybyte=0x29;

DDRB = DDRC = 0xFF; // Puertos B y C como salidas

x = mybyte & 0x0F; //enmascara los 4 bits superiores

PORTB = x | 0x30; //forma un ASCII

y = mybyte & 0xF0; // enmascara los 4 bits inferiores

y = y >> 4; // desplaza los 4 bits inferiores

PORTC = y | 0x30; // forma un ASCII

while(1);

return 0;

}

Escribir un programa en C para convertir dígitos ASCII '4' y '7' a BCD empaquetados y

mostrarlos en PORTB.

#include <avr/io.h>

int main (void) {

unsigned char bcdbyte;

unsigned char w='4';

unsigned char z = '7';

DDRB = 0xFF; // Puerto B como salida

w =w & 0x0F; //enmascara los 4 bits superiores para eliminar el 3

w = w << 4; //desplaza los 4 bits superiores para crear digito BCD

z = z & 0x0F; //enmascara los 4 bits superiores para eliminar el 3

bcdbyte = w | z; //combina para hacer el BCD empaquetado

PORTB = bcdbyte;

while(1);

return 0;

}

Suma de comprobación de byte en ROM

Para asegurar la integridad de los datos, cada sistema debe realizar el cálculo de suma de

comprobación. Al transmitir datos de un dispositivo a otro, o al guardar y restaurar los datos a

un dispositivo de almacenamiento se debe realizar el cálculo de la suma de comprobación para

asegurar la integridad de los datos. La suma de comprobación detectara cualquier alteración

de los datos.

Para asegurar la integridad de los datos, el proceso de suma de comprobación utiliza lo que se

llama control de suma de comprobación de un byte. La suma de comprobación de un byte es

un byte adicional que se fija en el extremo de una serie de bytes de datos. Para calcular el byte

de suma de comprobación de una serie de bytes de datos, los pasos siguientes pueden ser

tomados:

Page 3: Programacion en C 2da Parte

1. Sume todos los bytes juntos y no tome en cuenta el acarreo.

2. Tome el complemento a 2 de la suma total. Este es el byte de suma de comprobación, que

se convierte en el último byte de la serie.

Para realizar la operación de suma de comprobación, se suman todos los bytes, incluyendo el

byte de suma de comprobación. El resultado debe ser cero. Si no es cero, uno o más bytes de

datos han sido cambiados (dañado).

Ejemplo :

Supongamos que disponemos de 4 bytes de datos hexadecimales: 0x25, 0x62, 0x52H y 0x3F.

(a) Determinar el byte de suma de comprobación, (b) realizar la operación de suma de

verificación para garantizar la integridad de los datos, y (c) Si el segundo byte, 0x62, se ha

cambiado a 0x22, muestre cómo la suma de comprobación detecta el error.

Solución:

(a) Encuentre el byte de suma de comprobación.

0x25

+ 0x62

+ 0x3f

+ 0x52

Suma total 1 0x18 (no tomando en cuenta el acarreo)

Complemento a dos 0xE8

(b) Realizamos la suma de comprobación para detectar la integridad de los datos

0x25

+ 0x62

+ 0x3f

+ 0x52

+ 0xE8

2 0x00(no tomando en cuenta el acarreo)

(c) Si el segundo byte 0x62 es cambiado por 0x22, muestre como la suma de

comprobación detecta el error.

0x25

+ 0x22

+ 0x3f

+ 0x52

+ 0xE8

1 0xC0

(no tomando en cuenta el acarreo da 0x C0, significa que la data esta corrupta)

Page 4: Programacion en C 2da Parte

Escriba un programa C de para calcular la suma de comprobación de bytes de los datos

correspondientes al ejemplo anterior.

#include <avr/io.h>

int main(void)

unsigned char mydata[] ={ 0x2 5, 0x62, 0x3F, 0x52} ;

unsigned char sum = 0;

unsigned char X;

unsigned char chksumbyte;

DDRD=DDRB=DDRC = 0xFF; //Port D , Port B y Port C son salidas

for(x=0; x<4; x++) {

PORTD mydata[x] ; //enviar cada byte al PORTA

sum = sum + mydata[ xl ; //sumarlos juntos

PORTB = sum; //enviar la suma al PORTB

}

chksumbyte = ~sum + 1; //Complemento a dos

PORTC = chksumbyte; // enviar la suma de comprobación al PortC

while(1);

return 0;

}

Escriba un programa en C para realizar el paso de chequeo del ejemplo anterior. Si el datos

bueno, envía carácter ASCII 'G' al PORTD. En caso contrario, enviar 'B' a PORTD.

#include <avr/io.h>

int main(void)

unsigned char mydata[] ={ 0x2 5, 0x62, 0x3F, 0x52,0xE8} ;

unsigned char checksum = 0;

unsigned char X;

DDRA = 0xFF; //PortD salidas

for(x=0; x<5; x++)

checksum=checksum + mydata[x] ;

if (checksum == 0)

PORTD = 'G';

else

PORTD = 'B';

while(1);

return 0;

}

Cambie uno o dos valores de la matriz mydata y simular el programa para ver los resultados.

Page 5: Programacion en C 2da Parte

Conversión de Binario (hex) a decimal y ASCII en C

La función printf es parte de la biblioteca estandar l/O en C y puede hacer muchas cosas,

incluyendo la conversión de datos binarios (hex) a decimal, o viceversa. Pero printf toma

mucho espacio en la memoria y aumenta el hex sustancialmente. Por esta razón, en los

sistemas basados en el microcontrolador AVR, es mejor saber cómo escribir nuestra propia

función de conversión en vez de usar printf

Una de las conversiones más ampliamente utilizadas es la conversión binario a decimal.

En dispositivos tales como ADCs (analógico-a-digital), los datos se proporcionan al

microcontrolador en binario. En algunos RTCs, la hora y la fecha también se proporcionan en

binario. Con el fin de mostrar datos binarios, tenemos que convertirlo a decimal y luego a

ASCII. Debido a que el formato hexadecimal es una manera conveniente de representar datos

binarios, se refieren a los datos binarios como hexadecimal, datos binarios 00-0xFF convertido

a decimal nos da 000 a 255. Una forma de hacerlo es dividimos por 10 y guardamos el resto.

Por ejemplo, 11111101 o 0xFD es 253 en decimal. La siguiente es una versión de un algoritmo

para la conversión de hex (binario) a decimal:

Hex Cociente Resto

FD/OA 19 3 (digito bajo) LSD

19/0A 2 5 (digito medio)

2 (digito alto) (MSD)

Escribir un programa C para convertir 11111101 (hex FD) a decimal y mostrar los dígitos en

PORTB, PORTC, y PORTD.

#include <avr/io.h>

int main(void)

unsigned char x, binbyte, d1, d2, d3;

DDRB = DDRC = DDRD =0xFF; //Ports B, C, y D salidas

binbyte = 0xFD; // byte binario (hex)

x = binbyte / 10; //divide por 10

d1= binbyte % 10; //obtiene el resto de la division (LSD)

d2 = x % 10; // digito medio

d3 = x/10; // digito mas significativo (MSD)

PORTB d1;

PORTC d2;

PORTD d3;

while(1);

Return 0;

}

Page 6: Programacion en C 2da Parte

Muchos compiladores tienen algunas funciones predefinidas para convertir tipos de datos. En

la siguiente Tabla se puede ver algunas de ellas. Para utilizar estas funciones, el archivo stdlib.h

deben ser incluido. Tenga en cuenta que estas funciones pueden variar en diferentes

compiladores.

TabIa: Funciones de conversión de tipos de datos en C

Funciones Descripción de la función

int atoi (char * str) Convierte la cadena str a un entero.

long atoi (char * str) Convierte la cadena str a entero largo .

void itoa (int n, char * str) Convierte el número entero n a una cadena de caracteres str.

void ltoa (int n, char * str) Convierte el numero entero largo n a cadena de caracteres str.

float atof (char * str) Convierte los caracteres de la cadena str a un valor flotante.

SERIALlZACION DE DATOS EN C

Serializar datos es una forma de enviar un byte de datos un bit a la vez a través de un único pin

de un microcontrolador. Hay dos maneras de transferir un byte de datos en serie:

l. Usando el puerto serie. En el uso del puerto serie, el programador tiene un control

muy limitado sobre la secuencia de transferencia de datos. Los detalles del puerto

serie del AVR y la transferencia de datos se discuten mas adelante.

2. El segundo método de serialización de datos es la transferencia de datos un bit de

una vez y controlar la secuencia de datos y espacios entre ellos. En muchas nuevas

generaciones de dispositivos tales como LCD, ADC, y EEPROM, las versiones serie están

llegando a ser popular debido a que ocupan menos espacio en una placa de circuito

impreso. Aunque podemos utilizar estándares como I2C, SPI y CAN, no todos los

dispositivos son compatibles con dichas normas. Por esta razón tenemos que estar

familiarizado con la serialización de datos utilizando el lenguaje C.

Examine los siguientes cuatro ejemplos para ver cómo la serialización de datos se hace en C.

Page 7: Programacion en C 2da Parte

Escribir un programa para enviar el valor 0x44 en serie, un bit a la vez a través PORTC, pin 3. El

LSB debería ir en primer lugar.

#include <avr/io.h>

#define serPin 3

int main(void) {

unsigned char conbyte = 0x44;

unsigned char regALSB;

unsigned char x;

regALSB = conbyte;

DDRC |= (1<<serPin);

for(x=0;x<8;x++) {

if(regALSB & 0x01)

PORTC |= (1<<serPin);

else

PORTC &= ~(1<<serPin);

regALSB = regALSB >>1;

}

while(1);

return 0;

}

Escriba un programa en C para enviar el valor 0x44 serialmente un bit a la vez vía PORTC, pin3.

El bit MSB debe ir en primer lugar.

#include <avr/io.h>

#define serPin 3

int main(void) {

unsigned char conbyte = 0x44;

unsigned char regALSB;

unsigned char x;

regALSB = conbyte;

DDRC |= (1<<serPin);

for(x=0;x<8;x++) {

if(regALSB & 0x80)

PORTC |= (1<<serPin);

else

PORTC &= ~(1<<serPin);

regALSB = regALSB <<1;

}

while(1);

return 0;

}

Page 8: Programacion en C 2da Parte

Escriba un programa C para obtener a un byte de datos en serie un bit a la vez a través de

PORTC, pin 3. El LSB debe venir primero.

#include <avr/io.h>

#define serPin 3

int maín (void) {

unsigned char x;

unsigned char REGA=0;

DDRC &= ~(1<<serPin); //serPin es una entrada

for(x=0; x<8; x++) //repite para cada bit de REGA

{

REGA = REGA >> 1; //desplaza REGA hacia la derecha un bit

REGA |= (PINC & (1<<serPin))<< (7-serPin); //copia el bit en el pin serPin

} //del PORTC al MSB de REGA.

while(1);

return 0;

}

Escriba un programa C para obtener a un byte de datos en serie un bit a la vez a través de

PORTC, pin 3. El MSB debe venir primero.

#include <avr/io.h>

#define serPin 3

int maín (void) {

unsigned char x;

unsigned char REGA=0;

DDRC &= ~(1<<serPin); //serPin es una entrada

for(x=0; x<8; x++) //repite para cada bit de REGA

{

REGA = REGA << 1; //desplaza REGA hacia la izquierda un bit

REGA |= (PINC & (1<<serPin)) >> serPin; //copia el bit en el pin serPin

} //del PORTC al LSB de REGA.

while(1);

return 0;

}

Para adaptarlos a la realidad estos programas deberían tener unos retardos para la lectura o

escritura del pin.

ASIGNACIÓN DE MEMORIA EN C

Usando el espacio de programa (código) para datos predefinidos fijos es una opción muy

utilizada en el AVR y en los microcontroladores. Veremos cómo utilizar los programas en

lenguaje C para acceder a los datos almacenados en la memoria ROM.

Page 9: Programacion en C 2da Parte

Espacio de datos en Flash, RAM y EEPROM del AVR

En el AVR tenemos tres espacios en que se almacenan los datos. Son los siguientes:

1. Los bytes del espacio en SRAM de 64K tienen un rango de dirección de 0000-0xFFFF.

Como hemos visto en antes, muchos de los chips de AVR tienen menos de 64K bytes

para la SRAM.

2. El espacio de programas (código). Este espacio en la ROM Flash del chip se utiliza

para almacenamiento de los programas(opcodes) y por lo tanto esta directamente

bajo el control del contador programa (PC).

3. El espacio de EEPROM. Este espacio puede guardar los datos cuando el equipo está

apagado. Es por eso que utilizamos EEPROM para guardar variables que no debe

perderse cuando el equipo está apagado. Por ejemplo, el punto de ajuste de

temperatura de un sistema de enfriamiento debe ser cambiado por los usuarios y no

se puede almacenar en el espacio de programa. Asimismo, se deben guardar cuando el

equipo está apagado, por lo que se le coloca en la EEPROM. Además, cuando no hay

suficiente espacio de código, podemos colocar las variables permanentes en EEPROM

para ahorrar espacio de código.

Tamaño (Bytes) de memoria para algunos miembros de la familia ATmega

Flash SRAM EEPROM

8K 256 256

16K 1K 512

32K 2K 1K

64K 4K 2K

128K 8K 4K

Vamos a mostrar cómo leer o escribir desde y hacia la EEPROM mediante programación C. Se

debe tomar en cuenta que los diferentes compiladores de C tienen sus funciones incorporadas

o directivas para acceder a cada tipo de memoria. En CodeVision, para definir una variable

const en la memoria Flash, sólo tiene que poner la directiva Flash antes de ella. Además, para

definir una variable en la memoria EEPROM, puede poner la directiva eeprom delante :

Flash unsigned char myNum [] = "Hola"; // usar espacio código Flash

eeprom unsigned char = 7;// utilizar el espacio EEPROM

Escriba un programa en C para almacenar 'G' en la ubicación de EEPROM 0x005F.

#include <avr/io.h>

int main(void) {

while(EECR & (1<<EEWE)); // espera a que termine la escritura anterior

EEAR = 0x5f; //Coloca la direccion en el registro de direccion

EEDR = 'G'; //Coloca el dato en el registro de datos

EECR |= (1<<EEMWE);

EECR | = (1<<EEWE) ; //Arranca la escritura en la EEPROM

while(1);

return 0;

}

Page 10: Programacion en C 2da Parte

Escriba un programa en C para leer el contenido de la ubicación 0x005F de EEPROM en el

PORTB.

#include <avr/io.h>

int main(void) {

DDRB = 0xFF;

while(EECR & (1<<EEWE)); // espera a que termine la escritura anterior

EEAR = 0x5f; //Coloca la dirección en el registro de dirección

EECR |= (1<<EERE); //Inicia la lectura de la EEPROM escribiendo en EERE

PORTB= EEDR ; //Mueve el dato desde el registro de datos al puerto B

while(1);

return 0;

}