Está en la página 1de 47

Tema 2

Lenguaje C
Microprocesadores
PIC32MX230F064D
para programación
en bajo nivel
3º GITT

Curso
Francisco Martín
2022/2023
Esquema del tema

▪ Tipos de datos enteros


▪ Conversiones de tipos
▪ Manipulación de bits
▪ Campos de bits - Registros de un microcontrolador
▪ Uniones
▪ If/else/else if
▪ Bucles for/while/do-while
▪ Vectores
▪ Punteros
▪ Funciones
▪ Extensiones del lenguaje
▪ Ejercicios

2
Tema 02 Microprocesadores GITT | Comillas ICAI
Teoría

Tema 02 Microprocesadores GITT | Comillas ICAI


Introducción de datos
▪ Un mismo valor se puede introducir en decimal, hexadecimal o char.

▪ Se escribirá de la forma que sea más fácil de entender en el código.

4
Tema 02 Microprocesadores GITT | Comillas ICAI
Repaso de Hexadecimal
Decimal sin signo Binario Hexadecimal
0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F

5
Tema 02 Microprocesadores GITT | Comillas ICAI
Tipos de variables
Micros de 8, 16 y 32 bits

¿Cuánta memoria ocupa un int?


▪ El tipo int ha de ser del tamaño “natural” de la máquina.
Tipos de Datos
▪ Microcontrolador de 16 bits (dsPIC33) ➔ int ≡ 16 bits
boolean ▪ Microcontrolador de 32 bits (PIC32MX) ➔ int ≡ 32 bits
unsigned char Bits Rango (unsigned): 𝟎 ↔ 2𝒏 − 𝟏 Rango (signed) −2𝒏−𝟏 ↔ 2𝒏−𝟏 − 𝟏

byte / char 8 0 ↔ 255 -128 ↔ 127


16 0 ↔ 65535 -32 768 ↔ 32 767
Unsigned int / int 32 0 ↔ 4 294 967 296 - 2 147 483 648 ↔ 2 147 483 647
word
Por tanto cuanto, ¿cuánto ocupa un short int y un long int?
long int
▪ Sigue sin estar definido. Solo se sabe que:
unsigned long
𝑠ℎ𝑜𝑟𝑡 𝑖𝑛𝑡 ≤ 𝑖𝑛𝑡 ≤ 𝑙𝑜𝑛𝑔 𝑖𝑛𝑡
short int ¿Qué pasa si se cambia de arquitectura de microcontrolador en mitad de un
double / float proyecto?
▪ Hay que dedicar muchas horas en garantizar que las variables caben en la
nueva arquitectura si no se ha garantizado la portabilidad.

6
Tema 02 Microprocesadores GITT | Comillas ICAI
Conversión de tipos
Portabilidad
Librería <stdint.h>
▪ int8_t, int16_t, int32_t e int64_t: Definen variables enteras con signo
de 8, 16, 32 y 64 bits respectivamente.
▪ uint8_t, uint16_t, uint32_t y uint64_t son idénticas a las anteriores
pero para enteros sin signo.

¿Qué pasa al mezclar tipos?


Si se esta seguro de que el valor entra, hay que indicarlo con un cast:
uint32_t u_largo;
uint16_t u_corto;
u_corto = u_largo; //Posible overflow
u_corto = (uint16_t) u_largo; //Correcto

Otros usos del cast: Asignaciones de Memoría dinámica


float * pd; ...
pd = (float *)calloc(20, sizeof(float));

7
Tema 02 Microprocesadores GITT | Comillas ICAI
Conversión de tipos
Signo
Los números pueden tener o no tener signo
▪ En C, todas las variables son con signo salvo que vayan precedidas de la palabra
clave unsigned o se usen las variables unsigned de stdint.h
▪ Los números negativos se codifican en complemento a 2 (Negar cada bit y
sumar 1)

En los números con signo, el signo viene determinado por el bit más significativo
(MSB)
• 0 Positivo
• 1 Negativo
int a = 0x7FFF; // a = 32767
int b = 0xFFFF; // b = -1
unsigned int c = 0xFFFF; // c = 65535

8
Tema 02 Microprocesadores GITT | Comillas ICAI
Conversión de tipos
Degradación y Promoción
Degradación: Paso de un tamaño mayor a uno menor
uint32_t u_largo;
uint16_t u_corto;
u_corto = u_largo; //Posible overflow
u_corto = (uint16_t) u_largo; //Correcto

Degradación: Coma Flotante a Entero


int i = 4.6; //Se pierde la parte decimal i = 4

Promoción: Entero a Coma Flotante


float f = 4; //Se pierde tiempo en el cambio de la codificación entre el 4 entero
// a un número de coma flotante.

Promoción: Paso de un tamaño menor a uno mayor


int32_t i_largo;
int16_t i_corto;
i_largo = i_corto; //Se añaden los bits más significativos, se extiende el signo

9
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Operadores a nivel de bit

▪ Operadores de desplazamiento. Los operadores << y >>. Multiplicar por y


dividir por 2𝑛
a=0xA=1010 b = a << 4 = 10100000 =0xA0; b = a >> 1 = 101 = 0x5;

unsigned char a = 0xA9; char a = 0xA9;


unsigned char b = a>>2; //0x2A char b = a>>2; //0xEA

▪ Operador ~(NOT – complemento a 1) NOT


si a=0xF0, ~a valdrá 0x0F A Ā
0 1
1 0
10
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Operadores a nivel de bit

▪ Operadores lógicos a nivel de bit de dos operandos. Los operadores & (AND), |
(OR) y ^ (XOR)
int b, a = 0x5555;
b = a & 0xFF; // b = 0x0055
b = a | 0xFF; // b = 0x55FF
a= 1;
a^=1; //a =0
a^=1; //a =1;

AND OR XOR
A B A·B A B A+B A B A⨁B
0 0 0 0 0 0 0 0 0
0 1 0 0 1 1 0 1 1
1 0 0 1 0 1 1 0 1
1 1 1 1 1 1 1 1 0
11
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits Un registro en C es como una
variable de tipo unsigned int.
Máscaras 1 bit
Las máscaras permiten modificar bits individuales usando los operadores y hay 4
casos típicos:

▪ Lectura de un bit de un registro / variable:


(T1CON >> 2) & 1 // Ver el valor del Bit 2

▪ Escribir un 1 T1CON |= (1 << 15) // bit 15 = 1;


▪ Escribir un 0 T1CON &= ~(1 << 15) // bit 15 = 0;
▪ Invertir Valor T1CON ^= (1 << 15) // bit 15 se invierte;

Si se define el bit queda mas legible:


#define ON (1<<15) // El ON está en el bit 15
T1CON |= ON // ON = 1;
T1CON &= ~ON // ON = 0;

12
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Máscaras n bits
Las máscaras permiten modificar varios bits:

• Lectura de varios bits: tckps = (T1CON >> 4) & 3;


• Escribir T1CON &= ~(0x3 << 4); // Se borra lo anterior;
T1CON |= (tckps & 0x3) << 4; // Se escribe lo nuevo;

• Si se definen los bits queda mas legible:


#define ON (1<<15) // El ON está en el bit 15
#define TCS (1<< 1)
T1CON |= ON | TCS // ON = 1, TCS = 1;
T1CON &= ~(ON | TCS) // ON = 0, TCS = 0;

13
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Campos de bits
▪ Es una estructura donde se especifica el ▪ En los registros de configuración se
tamaño de los bits de cada variable que definen posiciones de memoria en vez de
estructuras.
puede ser signed, unsigned o bool
(1bit): #define T1CON T1CON
typedef struct{ extern volatile uint32_t T1CON
__attribute__((section("sfrs"), address(0xBF800600)));
unsigned dig0 : 4;
unsigned dig1 : 4; typedef union {
}BCD2_t; struct {
int main (void){ uint32_t :1;
BCD2_t miCampoBits = {2, 7}; uint32_t TCS:1;
miCampoBits.dig0 = 4; uint32_t TSYNC:1;
miCampoBits.dig1 = 2; uint32_t :1;
} uint32_t TCKPS:2;
uint32_t :1;
uint32_t TGATE:1;
▪ Microchip ha definido en el archivo uint32_t :3;
<xc.h> estructuras similares en sus uint32_t TWIP:1;
uint32_t TWDIS:1;
registros: (T1CONBits, PORTxBits, uint32_t SIDL:1;
LATxBits, TRISxBits…).
uint32_t :1;
Ej: T1CONBits.TON = 1; uint32_t ON:1;
};
} __T1CONbits_t;
extern volatile __T1CONbits_t T1CONbits __asm__
("T1CON") __attribute__((section("sfrs"),
address(0xBF800600)));

14
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Campos de bits - Inconvenientes
▪ Es menos eficiente: si se modifican N campos, hay que escribir N líneas que se
traduce en N desplazamientos y N escrituras.

▪ La definición de estas estructuras depende de si el compilador es Little Endian


o Big Endian.

El PIC32MX es Little endian.

Menos eficiente y disminuye la portabilidad….

… Mejor aprender máscaras

15
Tema 02 Microprocesadores GITT | Comillas ICAI
Manipulación de bits
Uniones vs Campo de Bits
• Una unión es similar a una estructura salvo que en lugar de reservarse una zona
de memoria para cada miembro de la estructura, se reserva una sola zona de
memoria a compartir por todos los miembros de la unión.
typedef struct{ uint16_t swap(uint16_t ent) {
uint8_t byte1; U_WORD_BYTE_t uwb;
uint8_t temp;
uint8_t byte2;
}DOSBYTES_t; uwb.palabra = ent;
temp = uwb.bytes.byte1;
typedef union{
uwb.bytes.byte1 = uwb.bytes.byte2;
uint16_t palabra; uwb.bytes.byte2 = temp;
DOSBYTES_t bytes;
return uwb.palabra;
}U_WORD_BYTE_t;
}

Como se puede ver en la unión, ambas


apuntan a la misma dirección de memoria
pues ambas son del mismo tamaño.

16
Tema 02 Microprocesadores GITT | Comillas ICAI
Instrucciones de Control
if, else if, else
Operadores lógicos
c = a && b Resultado Razón
if (condición) { a = 1, b=14 c = true Ambos distinto
// si se cumple a condición de 0
} a = 0, b=14 c = false a igual a 0
c = a || b Resultado Razón
if (condición) {
a = 0, b=14 c = true b distinto de 0
// si se cumple a condición
} else { a = 0, b=0 c = false Ambos igual a 0
// si no se cumple a condición c = ! b Resultado Razón
}
b=0 c = true b igual a 0

if (condición 1) {
b=14 c = false b distinto 0
// si se cumple a condición 1 c= a == b Resultado Razón
} else if(condición 2) { b=a=0 c = true b igual a
// si se cumple a condición 2
b= 2, a=0 c = false b != a
} else {
// si no se cumple ninguna c= a > b Resultado Razón
(similar<=,<,>,>=)
}
a=2, b=0 c = true b > a
b= 0, a=2 c = false b < a

17
Tema 02 Microprocesadores GITT | Comillas ICAI
Instrucciones de Control
if or switch

//Máquina de estados con if y switch


if (estado == 0) { switch (estado) {
// estado 0 case 0: // estado 0
} else if(estado == 1) { break;
// estado 1 case 1: // estado 1
} else if(estado == 2) { break;
// estado 2 case 2: // estado 2
} else { break;
// default default:
} break;
}

18
Tema 02 Microprocesadores GITT | Comillas ICAI
Bucles
for, while, do-while
for(sentencia inicial ; condición ; sentencia final ){
// aquí mientras la condición sea true
}

while (condición) {
// aquí mientras la condición sea true
}

do {
// se hace una vez y se mantiene mientras la condición sea true
} while (condición);

OJO: Usar con precaución dentro del while (1) del bucle scan.

19
Tema 02 Microprocesadores GITT | Comillas ICAI
Vectores
float vec[10]; // Declaración del array de float de 10 posiciones 0-9
vec[0]=54.23; // Primer elemento del vector
*vec=4.5; // Primer elemento del vector
vec=4.5; // ERROR–vec será la dirección de memoria de la primera posición de vec
vec[10]=98.5; // ERROR – acceso a una posición que no pertenece a vec

▪ ¡OJO! En ocasiones no hay error/warning de acceso a posiciones equivocas y es


difícil de detectar el cuelgue.

▪ Para inicializar hay 2 opciones:


#define MAX 5
int main() {
int Iniciado[]={1,5,8,4,3};
int SinIni[MAX];
int i;
for (i=0; i<MAX; i++)
SinIni[i] = Iniciado[i];
}

20
Tema 02 Microprocesadores GITT | Comillas ICAI
Punteros
▪ Los punteros almacenan direcciones de memoria.
int *pti;
char *ptc;

▪ Ambos almacenan una dirección de memoria y por tanto ocupan lo mismo. La


diferencia es que pti apunta aun entero y ptc apunta a un char que si que
ocupan distinto.

▪ En los vectores, el nombre de la variable apunta a la primera dirección del


vector.

21
Tema 02 Microprocesadores GITT | Comillas ICAI
Punteros
Operador & y Operador *
▪ Operador & ➔ permite obtener la dirección de memoria
int i; /* variable entera */
int v_i[20]; /* vector de enteros */
int *pti; /* puntero a entero */
i=78; /* inicializo i */
pti=&i; /* pti apunta a i */
pti=v_i; /* pti apunta a v[0] */

▪ Operador * ➔ llamado operador de indirección, permite acceder al valor por


medio del puntero.
int i; /* variable entera */
int *pti; /* puntero a entero */
pti=&i; /* pti apunta a i */
*pti=78; /* i=78 */

22
Tema 02 Microprocesadores GITT | Comillas ICAI
Punteros
Operaciones
▪ ¡OJO! que el puntero admite operaciones y hay que saber que se hace:
• *pti += 32; //Añade 32 al entero al que apunta, i+=32
• pti += 32; //Incrementa en 32 la dirección de memoria a la que apunta.

▪ Operador ++: Útil para recorrer vectores


• ptx++; //Apunta a la siguiente dirección de memoria, avanza el tamaño a
lo que apunte el puntero, es decir, sizeof (x), x{int, char,…}

▪ Ejemplo:
#define MAX 5
int main(void) {
int VWord[MAX]; char VByte[MAX]; int *pti; char *ptc; int i, suma; suma
= 0;
pti = VWord; ptc = VByte;
for (i=0; i<MAX; i++){
suma += *pti++;
suma += *ptc++;
}
}

23
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones
Divide y vencerás
▪ Modularizar - Metodología Top-Down
• La manera más elegante y fácil de construir un programa es dividir la tarea a
realizar en otras tareas más simples.
• Si estas tareas más simples no son aún lo suficientemente sencillas, se
vuelven a dividir.

▪ Ventajas
• Complejidad menor
• Modular
▪ Fácil de repartir el trabajo
▪ Fácil de probar por separado
• Reutilizable

¡¡Hacer funciones cortas y que hagan una sola cosa!!

24
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones
#include <xc.h>
#include <stdint.h>

type function(parameters); //Declaración de la función

type global_variable; //Variable global en este .c

• Las variables creadas dentro de
int main(void) { las funciones no están disponibles
type local_variable_1=1;
global_variable = 3;
fuera de ellas.
if(local_variable_1){ • Una función solo devuelve un
type c = 0;
}
valor coincidente con el tipo
c=2; // ERROR c ya no existe (int32_t, uint8_t, float…) de su
local_variable_1 = function(parameters);
declaración.
local_variable_2 = 0; // ERROR no accesible
}
type function(parameters) { //Definición de la función
type local_variable_2;
global_variable = 3;

return local_variable_2; //Solo se devuelve un valor
}

25
Tema 02 Microprocesadores GITT | Comillas ICAI
¿Dónde se programa?
Vamos a usar dos tipos de archivos:

▪ Fuente – Source (.c)


• #include de archivos que vayamos
a usar.
▪ Del sistema: <nombre.h>
▪ Nuestros: “nombre.h”
• #define parámetros
• Declaraciones de funciones que
solo se usan en ese .c
• Definición de funciones

▪ Cabeceras – Header (.h)


• Declaraciones de funciones que
queramos usar en varios .c

26
Tema 02 Microprocesadores GITT | Comillas ICAI
¿Dónde se programa?
Hay un archivo .c “principal” llamado main.c donde se define la
función en la que se inicia el micro y donde se encuentra el bucle
scan:

int main(void) {
// Inicialización del sistema, configurar entradas y salidas, así como
// el resto de periféricos
while (1) { // Bucle infinito, no puede bloquearse
// Leer entradas
// Ejecutar algoritmos de control
// Actualizar salidas
}
return 0; // Nunca debería llegar aquí
}

Esta función no necesita de declaración.


Este archivo no tiene .h asociado.
27
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones
Paso por valor
• En C SIEMPRE se pasan los parámetros por valor a las funciones; es decir, se
hace una copia cada variable y se pasa la propia copia a la función.
• Crea nuevas variables usando más memoría.
• En este ejemplo b y n no podrían ser modificadas desde la función.
#include <xc.h>
#include <stdint.h>
int power(int base, int n); //Declaración de la función
int main(void) {
int b=2, n=4, res;
res = power(b,n);
}
int power(int base, int n) { //Definición de la función
int i, p;
p = 1;
for (i=1; i<=n; i++)
p = p * base;
return p; //Solo se devuelve un valor
}

28
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones
Paso por referencia
• Permite devolver varios resultados al usar punteros.
• Los vectores se pasan SIEMPRE por "referencia"; es decir, cualquier función
puede modificar el valor de cada componente de un vector.
• Permite reducir el uso de memoria de datos al no crear nuevas variables, pero
hay que saber lo que se hace
#include <xc.h>
void swap(int *px, int *py); //Declaración de la función
int main(void) {
int x=2, y=4;
swap (&x,&y);
}
void swap(int *px, int *py) { //Definición de la función
int temp;
temp = *px;
*px = *py;
*py = temp;
return;
}

29
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones – Vectores – Punteros
Manejo tipo vector

#include <xc.h>
#define MAX 50
void get_vector_discreto(int min, int max, int v[]);
int main(void) {
int vector[MAX];
get_vector_discreto(1, 4, vector);
}
/* función que devuelve un vector con los valores enteros comprendidos entre min y
max*/
void get_vector_discreto(int min, int max, int v[]){
int i;
for (i=0; i<=max-min; i++)
v[i] = min+i;
}

30
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones – Vectores – Punteros
Manejo tipo puntero

#include <xc.h>
#define MAX 50
void get_vector_discreto(int min, int max, int* v);
int main(void) {
int vector[MAX];
get_vector_discreto(1, 4, vector);
}
/* función que devuelve un vector con los valores enteros comprendidos entre min y
max*/
void get_vector_discreto(int min, int max, int* v){
int i;
for (i=0; i<=max-min; i++)
*(v+i) = min+i;
}

31
Tema 02 Microprocesadores GITT | Comillas ICAI
Funciones – Vectores – Punteros
Manejo tipo puntero con postincremento

#include <xc.h>
#define MAX 50
void get_vector_discreto(int min, int max, int* v);
int main(void) {
int vector[MAX];
get_vector_discreto(1, 4, vector);
}
/* función que devuelve un vector con los valores enteros comprendidos entre min y
max*/
void get_vector_discreto(int min, int max, int* v){
int i;
for (i=0; i<=max-min; i++)
*(v++) = min+i;
}

32
Tema 02 Microprocesadores GITT | Comillas ICAI
Extensiones del lenguaje
Ensamblador
▪ Una vez conozca el lenguaje puede escribir directamente usando la función
asm():

void DesplazaLEDsPuertoB(void) {
PORTB = PORTB << 1;
asm(" NOP");//Gasta un ciclo de operación del micro – Tema 3
PORTB &= ~(1<<12);
}

uint16_t swap(uint16_t ent) {


asm("wsbh v0, %0" : "+r"(ent));
// Voltea el dato de entrada
// y lo copia a v0, que es el
// valor de retorno de la función
}

La instrucción wsbh hace lo que hicimos en la función swap pero el compilador no


la usa al transformar el código anterior.

33
Tema 02 Microprocesadores GITT | Comillas ICAI
Extensiones del lenguaje
Ensamblador
uint16_t swap(uint16_t ent) { 42: uwb.bytes.byte1 = uwb.bytes.byte2;
9D00015C 27BDFFF0 ADDIU SP, SP, -16 9D000180 93C20005 LBU V0, 5(FP)
9D000160 AFBE000C SW FP, 12(SP) 9D000184 A3C20004 SB V0, 4(FP)
9D000164 03A0F021 ADDU FP, SP, ZERO 43: uwb.bytes.byte2 = temp;
9D000168 00801021 ADDU V0, A0, ZERO 9D000188 93C20000 LBU V0, 0(FP)
9D00016C A7C20010 SH V0, 16(FP) 9D00018C A3C20005 SB V0, 5(FP)
36: U_WORD_BYTE_t uwb; 45: return uwb.palabra;
37: uint8_t temp; 9D000190 97C20004 LHU V0, 4(FP)
39: uwb.palabra = ent; 46: }
9D000170 97C20010 LHU V0, 16(FP) 9D000194 03C0E821 ADDU SP, FP, ZERO
9D000174 A7C20004 SH V0, 4(FP) 9D000198 8FBE000C LW FP, 12(SP)
40: temp = uwb.bytes.byte1; 9D00019C 27BD0010 ADDIU SP, SP, 16
9D000178 93C20004 LBU V0, 4(FP) 9D0001A0 03E00008 JR RA
9D00017C A3C20000 SB V0, 0(FP)
41:

34
Tema 02 Microprocesadores GITT | Comillas ICAI
Extensiones del lenguaje
Interrupciones
▪ Interrupciones Vectorizadas ▪ Interrupciones en modo “single
(dspic33 o Coldfire) vector”
En la versión original del MIPS32,
Se construye en la memoria un vector cuando se produce una interrupción se
de direcciones de forma que cuando se salta siempre a una misma dirección
produce la interrupción número n se de memoria y hay que averiguar quien
salta a la posición n del vector. ha interrumpido.

__attribute__((interrupt(no_auto_psv,
irq(XX) ) )) void
▪ La familia PIC32MX dispone de un
nombreEspecificoDeLaInterupcion(void) { controlador externo de
// … interrupciones.
} __attribute__((vector(#Vector),
interrupt(#PriorityLevel), nomips16))
void nombreDeLaInterupcion (void) {
// Se borra el flag
// Código de interrupción
}

35
Tema 02 Microprocesadores GITT | Comillas ICAI
Problemas

Tema 02 Microprocesadores GITT | Comillas ICAI


Ejercicios
1. Complete la tabla

Tipo Decimal Binario Hexadecimal


char -7
char 0x7A
unsigned char 1000 1100
int16_t 20000
int16_t 1111 1111 0000 0000
uint16_t 0x147E

37
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios
2. Complete – OPERADORES LÓGICOS

int a = 0x001B; // // ! (NOT) // > (Mayor o igual que)


int b = 0x0000; // !a ➔ _____ a >= d ➔ _____
int c = -2; !b ➔ _____
int d = 27; // < (Menor que)
// == (Igualdad) b < c ➔ _____
// && (AND) a == d ➔ _____
a && b ➔ _____ // <= (Menor o igual que)
c && d ➔ _____ // != (Desigualdad) b <= d ➔ _____
a != c ➔ _____
// || (OR) // Combinaciones
a || b ➔ _____ // > (Mayor que) (a > c) && (b < d) ➔_____
c || d ➔ _____ c > d ➔ _____ !((a && b) || c) ➔ _____

38
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios
3. Complete – OPERADORES A NIVEL DE BIT
int a = 0xDEAC;
int b = 0x1CA1;
int c = 0xF423;
unsigned int d = 0xFC07;

// & (AND) // ~ (NOT, compl. a uno) //>> (Despl. a la der.)


a & c ➔ ~c ➔ c >> 4 ➔
b & d ➔ d >> 6 ➔
// ^ (XOR)
// | (OR) a ^ d ➔ // Combinaciones
a | b ➔ b ^ c ➔ ((b << 4) ^ d) | c ➔
c | d ➔
//<< (Despl. a la izq.)
a << 2 ➔ ((a ^ c) | ~a) & b ➔
c << 8 ➔

39
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios
4. Sea una variable entera, a, de 16 bits. Con una sola línea de código:
a) Escriba un 0 en los bits 7 y 9 de a sin alterar los demás bits.

b) A partir del resultado anterior, escriba un 1 en los bits 6 y 8 sin modificar el resto.

c) Guarde en b el valor de los pines 8 a 11.

40
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios
5. ¿Qué valor toman las variables después de ejecutar cada una de las líneas del siguiente
programa?

int a = -2, b = 4, c;

c = a--; // a= b= c=
c >>= 1; // a= b= c=
c += b - a; // a= b= c=
a = ++b; // a= b= c=
c = b / 2; // a= b= c=
c = a % c; // a= b= c=
c *= b; // a= b= c=

41
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios
6. ¿Cuánto vale b?

// Código #1 // Código #2 // Código #3 // Código #4


int a = -1, b = 0; int a = 0, b = 0; int a = 0, b = 0; int a = 0, b = 0;
if (a) { if (a = 0) { if (a = 1) { if (a) {
b = 1; b = 1; b = 1; b = 1;
} } } }

b = b = b = b =

42
Tema 02 Microprocesadores GITT | Comillas ICAI
Un registro en c es como una variable
Ejercicios de tipo uint16_t. Se verá en tema 3

7. Evalúe el resultado de las dos expresiones:


• (5 || !3) && 6
• (5 | ~3) & 6

8. Se necesita poner a 1 el bit 4 de un registro denominado


R_SOLO_ESCRITURA, que como su propio nombre indica, es un registro de
sólo escritura; es decir, que si se lee de su dirección se obtendrán valores
aleatorios, pero no el último valor que se escribió. Escriba una función que
realice esta tarea.
Pista: Use una variable para almacenar el último valor escrito en el registro.

9. Siguiendo con el ejercicio anterior, escriba una función para modificar el bit 4
del registro R_SOLO_ESCRITURA. La función tendrá un único argumento que
será el valor a escribir en dicho bit.

10. Modifique la función del ejercicio anterior para que se pueda especificar el
número de bit a modificar y el valor que se desea escribir en el registro.
43
Tema 02 Microprocesadores GITT | Comillas ICAI
Un registro en c es como una variable
Ejercicios de tipo uint16_t. Se verá en tema 3

11. Escriba las sentencias necesarias para modificar los campos del registro
T1CON tal como se indica:
A. Poner el campo TCKPS a 10.
B. Poner a 1 los bits ON y TCS.
C. Poner a 0 el bit TGATE.

44
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios

12. Realice un programa que sume dos números en BCD2. En una primera
versión, los dos números se inicializarán en el código y en una segunda
versión se pedirán al usuario (dígito a dígito). Recuerde que el algoritmo para
sumar números en BCD es el siguiente:
• Los números se suman dígito a dígito, empezando por los dos dígitos menos
significativos.
• Si el resultado de sumar dos dígitos es mayor de 9 o si se produce un acarreo al
siguiente dígito, se suma 6 a dicho resultado. En cualquiera de estos dos casos, es
necesario sumar 1 (acarreo) a los dos dígitos siguientes.

197
284
481

En la suma del primer dígito (7 + 4) se produce un resultado mayor que 9, por


lo que se suma 6 a la cifra obtenida y se acarrea un 1 a las siguientes dos
cifras (9 y 8). En la suma de estas dos cifras se produce un acarreo a la tercera
cifra, por lo que también ha sido necesario sumar 6.
45
Tema 02 Microprocesadores GITT | Comillas ICAI
Sumador de BCD

46
Tema 02 Microprocesadores GITT | Comillas ICAI
Ejercicios

13. Escriba de nuevo la función swap usando desplazamientos y máscaras en


lugar de una unión.

14. Escriba una función para convertir una palabra de 32 bits de formato Little
Endian a formato Big Endian.

47
Tema 02 Microprocesadores GITT | Comillas ICAI

También podría gustarte