PDF de programación - Elementos de C para Sistemas Embebidos

Imágen de pdf Elementos de C para Sistemas Embebidos

Elementos de C para Sistemas Embebidosgráfica de visualizaciones

Publicado el 24 de Junio del 2021
727 visualizaciones desde el 24 de Junio del 2021
363,6 KB
33 paginas
Creado hace 13a (03/09/2010)
Elementos de C para Sistemas 

Embebidos

Andrés Djordjalian <[email protected]>
Seminario de Sistemas Embebidos
Facultad de Ingeniería de la U.B.A.

17:14

1 de 33

Estándares de C
Cada estándar es un “dialecto” diferente

O sea, en grandes términos es lo mismo, pero
existen diferencias que afectan la portabilidad.

“K&R C” (1978)

La primera estandarización no fue institucional,

sino que ocurrió cuando la comunidad adoptó
como estándar la descripción hecha por
Kernighan y Ritchie en su libro clásico de 1978.

“ANSI C” (o “ISO C” o “C90”) (1990)

Corresponde al estándar ISO/IEC 9899:1990
Es el más popular en la actualidad (el K&R C es obsoleto)
Es una descripción más exhaustiva que la del K&R C

“C99” (1999)

Es la revisión de 1999 del estándar anterior
No todos los compiladores actuales lo soportan al 100%
Tiene elementos tomados de C++

• …que los compiladores C/C++ suelen soportar aunque no sean

100% compatibles con C99

17:14

2 de 33

Tamaño de los Tipos de Datos
Los compiladores C tienen cierta libertad para elegir

el tamaño de los tipos de datos comunes
Lo suelen hacer en base a consideraciones de eficiencia, que

Tienen que respetar ciertos requisitos:

dependen de cada procesador
1. sizeof(char) <= sizeof(short) <= sizeof(int) <=
2. char por lo menos de tamaño suficiente para el conjunto de
3. short al menos de 16 bits
4. long al menos de 32 bits

sizeof(long)
caracteres básico

En programación de bajo nivel, a veces queremos

explicitar el tamaño exacto del dato
Por ejemplos, en casos como estos:

• Entrada/Salida
• Optimización de la utilización de memoria
• Rutinas en Assembly embebidas

¿Definir siempre un tamaño exacto? ¿O sólo a veces?

17:14

• Es un tema polémico.

3 de 33

Tipos de Datos de Tamaño Fijo
El C99 incluye los tipos de datos:

int8_t, int16_t, int32_t, int64_t (con signo)
uint8_t, uint16_t, uint32_t, uint64_t (sin signo)
int8_t es un entero de 8 bits incluyendo signo,
int16_t es uno de 16 bits, etc.
stdint.h
Ejemplo:

Estas definiciones están en un header llamado

#include <stdint.h>
int16_t g_posicion = 0;
int16_t leer_posicion(void) {

unsigned int intentos = 0;
etcétera…

Si el compilador no es C99 compatible, podemos usar

los mismos tipos definiéndolos con typedef

17:14

4 de 33

typedef
typedef le da un nombre al tipo de dato que
typedef <tipo de dato> <nombre>

indiquemos (que puede ser compuesto):

Ejemplos:

typedef signed char
typedef unsigned char

int8_t;
uint8_t;

Así, podemos definir esos tipos en stdint.h, y
usarlos aunque nuestro compilador no sea C99
compatible
Si stdint.h no existe, lo creamos
Pero muchos compiladores para embebidos ya lo traen
Usamos tipos de datos estándar de los cuales sabemos la

longitud para el procesador en cuestión
• Como con char en el ejemplo de arriba

Por otro lado, aprovechen las sentencias typedef

para clarificar el código

17:14

5 de 33

Conversión Automática de Tipos
C permite realizar operaciones

Ejemplo:

entre variables de diferente
tamaño, o combinando con y
sin signo

unsigned char a = 200;
int b = -20;
a = a+b;

Los compiladores generalmente cambian cada tipo a

uno de más bits que incluye todos los valores posibles
del original
En el ejemplo anterior, a es convertido a int durante la operación,
y el resultado es pasado de vuelta a unsigned char, quedando
igual a 180, como resulta lógico

Gracias a esto, el programador frecuentemente ni se da

cuenta de que hay una conversión de tipos
Es más, muchos compiladores convierten tipos aunque no sea

necesario, para simplificar la compilación

17:14

6 de 33

Ej.: Si a es unsigned int y

Ejemplo:

Conversión Automática de Tipos
Sin embargo, las reglas de C son más complejas que lo
mostrado en la diapositiva anterior, porque tienen en
cuenta la performance
la aritmética en long es
ineficiente en este procesador,
¿qué conviene hacer?
1. ¿Convertir todo a long?
2. ¿O usar int a pesar de perderse rango?
3. ¿O usar unsigned int a pesar de perderse el signo de b?

unsigned int a = 200;
int b = -20;
a = a+b;

Los compiladores generalmente optan por la número

3, pero estas situaciones no están bien definidas
Por eso, traen riesgos de errores y problemas de portabilidad

17:14

7 de 33

Conversión Automática de Tipos
Recomendaciónes:
1. No mezclar valores con signo con valores sin signo
Si se lo hace, prescindir de la conversión automática lo más

que se pueda
• Por ejemplo, si a es unsigned y b es signed, en lugar de

if (a+b < 0) { … };

Escribir:if ((b < 0) && (-b > a)) { … };

2. No hacer asignaciones que puedan perder

información
En el primer ejemplo, además
de no cumplir la regla anterior,
estábamos sumando un int y
poniendo el resultado en un
char. Evitemos eso.

Ejemplo:

unsigned char a = 200;
int b = -20;
a = a+b;

17:14

8 de 33

Operaciones Sobre Bits
Para operar sobre bits individuales, escribamos las

constantes en hexadecimal
Porque cada dígito hexa corresponde a 4 bits y se hace fácil de

leer

• Ej.,

0xC8 = 11001000b

0xC8 = 11001000b

Operadores de a bits:

AND: & • OR: | • NOT: ~ • XOR: ^
Operan “bit a bit”, así que no confundirlas con las operaciones

lógicas &&, || y !

Testeo de bits: if (0x0020 & reg) { … };
Encendido de bits: reg |= 0x0003;
Apagado de bits: reg &= 0x00FF;
“Toggling” de bits: reg ^= 0x0001;
Desplazamiento: << n y >> n

17:14

9 de 33

Punto Flotante
En muchas aplicaciones (científicas, de procesamiento

de señales, etc.) necesitamos representar números
reales con:
Rango amplio
Error de representación bajo en términos relativos
Parte fraccionaria (no entera)
Sin que se necesiten muchos bits para representarlos

La manera típica de hacerlo es mediante algún formato

de punto flotante (o floating point o coma flotante)

Consiste en descomponer el número así:

número = mantisa x base exponente

La base y la posición de la coma en la mantisa están
establecidos por el sistema de punto flotante que se
haya elegido
Noten que, por lo tanto, sólo se necesitan guardar los dígitos de la
mantisa y los del exponente, junto con sus respectivos signos, para
representar el número en memoria
10 de 33

17:14

Punto Flotante

número = mantisa x base exponente

Ej:

18,375 = 1,8375 x 101
-0,07514 = -7,5140 x 10-2
982312014 ≅ 9,8231 x 108
-0,00000000415147 ≅ -4,1514 x 10-9

Noten que no usamos más que cinco dígitos para la

mantisa y uno para el exponente (más sendos signos)
y sin embargo logramos gran rango y bajo error
relativo

Podíamos haber establecido otra posición para la

coma, por ej.:

18,375 = 183,75 x 10-1 ≅ 0,0184 x 10-3 ≅ etc.

Pero lo típico es usar un sistema normalizado con un y sólo un

dígito entero

17:14

11 de 33

Punto Flotante
El ejemplo es en base 10. En un circuito digital

normalmente se usa base igual a 2

¿Cómo se escribe 18,375 en binario?

18,37510 = 10010,0112

• Porque las posiciones a partir de la coma valen 2-1, 2-2, 2-3, etc.

– O sea, 0,5; 0,25; 0,125; etc.

Ejemplos en binario y base igual a 2:

18,375 = 1,0010011b x 2100b
-0,07514 ≅ -1,1110101b x 2-100b
982312014 ≅ 1,1101010b x 211101b
-0,00000000415147 ≅ -1,0001110b x 2-11100b

Noten que el 1 entero es redundante (sólo el 0 no lo

tiene), así que no hace falta guardarlo
…siempre que exista alguna convención para guardar un cero
Cuando no se lo guarda, a ese 1 se le llama implícito u oculto

17:14

12 de 33

Estándar IEEE 754
Se usa muy extensivamente. Define varios tipos de

punto flotante, principalmente:

1. Simple precisión

Normalmente es el típico tipo float de lenguaje C
Usa 32 bits en total para cada número:

1 para el signo
23 para la mantisa (sin contar el 1 implícito)
8 para el exponente (en lugar de ser signado tiene un bias de 127)

2. Doble precisión

Normalmente es el tipo double de lenguaje C
Usa 64 bits:

1 para el signo
52 para la mantisa (sin contar el 1 implícito)
11 para el exponente (con bias igual a 1023)

Los dos son normalizados y usan base igual a 2

17:14

13 de 33

Punto Flotante
Las operaciones con punto flotante no son tan básicas

como las de enteros. Ej.:
Para sumar, se alinean las mantisas, se suman, se toma el

exponente más grande, y se normaliza el resultado

Para multiplicar, se multiplican las mantisas, suman los

exponentes, y normaliza el resultado

Etcétera
Cuando un programador necesita números con parte
fraccionaria, frecuentemente los define como float
(o algo similar) y listo
Se logra un error de representación pequeño para un rango muy
grande, así que sólo excepcionalmente hay que analizar si es lo
suficientemente bueno (ej., aplicaciones científicas)

El compilador y las librerías implementan todo, usando

operaciones enteras o de la unidad de punto flotante (floating-
point unit o FPU) si es que se cuenta con este hardware

17:14

14 de 33

Números no enteros en Sist. Emb.
Sin embargo, muchas de esas veces no se requiere el
amplio rango y el bajo error relativo del punto fijo. Se
paga así un precio que, en sistemas embebidos, puede
ser caro
  • Links de descarga
http://lwp-l.com/pdf19342

Comentarios de: Elementos de C para Sistemas Embebidos (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad