Upload
hadat
View
215
Download
0
Embed Size (px)
Citation preview
Computadora
Se dispone de un S.O.
El S.O. inicia y configura los periféricos.
El S.O. brinda al usuario subrutinas para utilizar los periféricos ( system calls ).
Microcontrolador
No posee un S.O.
El firmware debe iniciar los periféricos.
El usuario debe crear sus propias subrutinas para utilizar los periféricos.
Llamada a la función main
A pesar que main es el punto de entrada al programa, el firmware realiza tareas previas a main. Entre ellas.
Cargar registros de configuración.Limpiar zonas de RAM.Cargar el puntero de pila SP.
Código en ensamblador
ORG $EE00
…configuraciconfiguracióónn de los de los perifperifééricosricos……
….
BRA $
Código en C
ORG $EE00
…código de inicialización…
CALL/JMP main
void main(void){
…código escrito por el usuario…
while(1){}
}
Pasaje de parámetros
Al igual que en un computadora, la pila se utiliza para el pasaje de parámetros:
int funcion(char a, int b, float c,….)
Ejemplo de pasaje de parámetros usando la pila
void main(void){
int dunga, donga;
dunga = 3;donga = 5;
dunga = suma(dunga, donga);
donga = resta(dunga, donga);}
int sum(int s1, int s2){
return s1 + s2;}
int resta(int r1, int r2){
return r1 – r2;}
Pasaje de parámetros usando la pila
Desventajas:Llamados anidados a funciones pueden limitar la RAM libre.
Ventajas:Al retornar de la función se libera el espacio de memoria.
Uso del heap
Se hace declarando variables estáticas externas, mas conocidas como VARIABLES GLOBALES.
Ejemplo de pasaje de parámetros usando el heap
iInt dunga, donga;
void main(void){
dunga = 3;donga = 5;suma();resta();
}
int suma(void){
dunga = dunga + donga;}
int resta(void){
dunga = dunga - donga;}
Pasaje de parámetros usando el heap
Ventajas:Pueden anidarse los llamados a funciones sin que crezca la pila enormemente.
Desventajas:La memoria usada en el heap no puede liberarse.
Uso de las funciones recursivas
void factorial(int n){
if(n == 1)return 1;
elsereturn factorial(n-1) *
n;}
factorial(8);
Tipos de datos básicos
En PC:char: 1 byteint: 2 ó 4 bytesfloat: 4 bytes
En microcontroladores:char: 1 byteint: 2 bytesfloat: 4 bytes
Variantes de los tipos básicos
Se admiten los modificadores signed y unsigned.También los modificadores short y long.El float puede no estar contemplado en versiones gratuitas de los compiladores.
No necesariamente existe en ensamblador una instrucción para realizar cierta operación aritmética. Ej: Los PIC 16F no cuentan con instrucciones de
multiplicación.En ese caso el compilador debe
generar un algoritmo en assemblerque ejecute esa operación.
Alternativas al tipo float
En general queremos representar cifras del tipo: 20,3 mVSe trata de un número decimal de punto fijo.Tampoco se dispone de representación en punto fijo.
Solución:Trabajar las mangintudes
multiplicadas x10, x100, …La cifra 20,3 se almacena como
203. Así puede contenerse en un tipo int.
Manejo de bits como variables
Es válida aplicar una asignación a un bit.Son válidas las operaciones lógicas entre bits |, & y ^.Ejemplos:
Freescale:PTAD_PTAD4 = 1;PIC:PORTBbits.RB4 = 0;
Volatile
Código en Cvoid findecuenta(void){
…if(time == 100){
time = 0;…
}}
Posible compilación en ensamblador:
findecuenta:LDA time…CMP #!100BNE …CLR time…
Volatile
Si time no cambia antes del if, la compilación anterior es válida.Si time proviene del módulo timer puede modificarse entre que es cargada y el if.
Solución
Código en C:volatile int time;
void findecuenta(void){
…if(time == 100){
time = 0;…
}}
Compilación en ensamblador:
findecuenta:…
LDA timeCMP #!100BNE …CLR time
Reseña de punteros
Se declaran y usan de la forma convencional:
int *p;char *p;int hola;p= &hola;*p = 3; ( hola = 3 )
Punteros a ROM
char *p;char texto[20] = “Hola mundo”;
p = texto;
p apunta a una posición en ROM (FLASH).
Arquitectura Von Neumann( Freescale )
La RAM y ROM están en un mismo mapa. Pueden accederse por una única clase de punteros.
Arquitectura Harvard ( PIC )
La RAM y ROM están en mapas diferentes. Se deben indicar a que
mapa apunta el puntero.
Punteros en micros Hardvard
Punteros a RAM:
char hola;char *p;p = &hola;
Punteros a ROM:
const char rom texto[20] = “me duermo”;char rom *p;p = texto;
En la computadora
Acceso al I/O de entrada:a = getch();Acceso al I/O de salida:printf(“Hola mundo”);
Sistema dedicado
Crear bibliotecas de funciones:
LCD_printf(char *texto);LCD_Dato(char caracter);LCD_gotoxy(char x, char y);
sprintf resuelve todo
Genera textos.
Convierte datos int a BCD.Convierte datos floata BCD.Permite generar salidas en formatos muy complejos.
sprintf(texto, “Chau”);sprintf(texto, “%d”, a);sprintf(texto, “%f”, d);sprintf(texto, “V = %02.1f mV”, voltios);
Uso de los puertos de E/S
Acceso a pines individuales:
struct{
byte PTAD0:1byte PTAD1:1byte PTAD2:1byte PTAD3:1byte PTAD4:1byte PTAD5:1byte PTAD6:1byte PTAD7:1
}Bits;
Bits.PTAD0 = 1;
Mas sobre puertosAcceso a todo el puerto:
typedef union{
byte Byte;struct{
byte PTAD0:1byte PTAD1:1byte PTAD2:1byte PTAD3:1byte PTAD4:1byte PTAD5:1byte PTAD6:1byte PTAD7:1
}Bits;}PTADSTR;
PTADSTR.Byte = 0xff;
PTADSTR.Bits.PTAD0 = 1;
PTAD_PTAD0 = 1;
Manejo de periféricos
En PC usando system calls.En microcontroladores:
Freescale:Asistentes de configuración ( Processor Expert )Funciones de biblioteca.
En PIC:Bibliotecas.
Processor Expert
Genera el código de inicializaciónGenera funciones para el manejo de módulo.Genera vectores de interrupción.
Demoras cortas
Intercalando código en ensamblador:
unsigned char contador_1;
asm{LDA #$32STA contador_1
dem_100us_1:NOPNOPNOP
DBNZ contador_1,dem_100us_1
}
Ttotal = 50 x 2µs = 100µs
Tint = 10 ciclos x 200ns = 2µs
Demoras largasIntercalando código en ensamblador:
unsigned char contador_1;unsigned char contador_2;unsigned char contador_3;
for(contador_3 = 0; contador_3 < 100; contador_3++)for(contador_2 = 0; contador_2 < 20;
contador_2++) {
asm{
LDA #$C8STA contador_1
dem_1s_1:NOPNOPNOPDBNZ contador_1,dem_1s_1
}}
Ttotal = 100 x 10ms = 1s
Text = 20 x 500µs = 10ms
Tint = 250 x 2µs = 500µs
Demoras largas
Módulo timer con interrupciones:
void main(void){TI1_SetPeriodSec(1);}
ISR(TI1_Interrupt){
(void)TPM1C0SC;TPM1C0SC = 0x80;
(código del usuario)}
Código bloqueante
Durante el llamado a una función el programa no continúa su ejecución hasta retornar de ella.
Ej:
void main(void){
demora_seg(1);}
Código no bloqueante
El programa puede continuar con otras tareas mientras una función no entregue los resultados deseados.
Ej:void main(void){…}
ISR(TI1_Interrupt){
(void)TPM1C0SC;TPM1C0SC = 0x80;
(código del usuario)}
Timer tick de la PC
Produce interrupciones cada 1ms.El usuario puede generar eventos por timer tick.El usuario no debe atender la interrupción.
void __fastcall TForm1::Timer1Timer(TObject*Sender)
{( código del usuario )
}
Eventos de timer con microcontroladores
La velocidad del timer tick es determinada por el firmware.Pueden generarse eventos por timertick.El usuario no debe atender la interrupción.
void TI1_OnInterrupt(void){
( código del usuario )}
Arquitectura PIC
Existen 1 ó 2 vectores de interrupción.El usuario debe determinar con un if que periférico disparó la interrupción.
#pragma code low_vector=0x18void interrupt_at_low_vector(void){_asm
GOTO low_isr_endasm}
#pragma code#pragma interruptlow low_isrvoid low_isr(void) {}
Arquitectura Freescale
El Processor Expert resuelve buena parte del código.Existen vectores independientes para cada evento y periférico.El usuario no debe atender una interrupción. El Processor Expert genera el código que lo hace.
Evento de conversión A/D
word AD1_OutV;
ISR(AD1_Interrupt){
((TWREG*)(&AD1_OutV))->b.high = ADC1RH; ((TWREG*)(&AD1_OutV))->b.low = ADC1RL; OutFlg = TRUE;AD1_OnEnd();ModeFlg = STOP;
}
void AD1_OnEnd(void){
unsigned int medicion;}