Lectura_Practica

14
Introducción C ha sido distinguido por la eficiencia del código que produce no solo por la potencialidad de los comandos y estructuras de datos sino también por su portabilidad para migrar entre plataformas y dispositivos DSP. Es el lenguaje de programación más popular para crear desarrollos de software, para crear aplicaciones y para la programación de microcontroladores de todo tipo. Se trata de un lenguaje medio nivel pero con muchas características de bajo nivel. Dispone de las estructuras típicas de los lenguajes de alto nivel pero, a su vez, dispone de construcciones del lenguaje que permiten un control a muy bajo nivel. Los compiladores suelen ofrecer extensiones al lenguaje que posibilitan mezclar código en ensamblador con código C o acceder directamente a memoria o dispositivos periféricos. El compilador C traduce programas de alto nivel a lenguaje de máquina que puede ser ejecutado por procesadores como TMS320C55x. Los ambientes de programación incluyen programas de depuración (debugger) para identificar errores en programas fuente. El propósito de la programación DSP es manipular señales digitales para una aplicación específica de procesamiento. Para conseguir esto los programas DSP deben ser capaces de: Organizar las variables ( diferentes tipos de datos) Describir las acciones (Operadores) Controlar las operaciones (Flujo del programa) Mover los datos de adentro y afuera entre el mundo exterior y el programa (Entradas/Salidas) El presente documento tiene como objetivo hacer un compendio de los elementos requeridos sobre este lenguaje, considerando su sintaxis, estructura y uso de sus instrucciones, sin embargo no cubre todos los elementos en su totalidad. Contenido: 1. Estructura de un programa en C. 2. Punteros, funciones, archivos y operaciones I/O 3. Estructuras de control del programa y bucles o ciclos 4. Tipos de datos soportados por la serie TMS320C55x Nota: A lo largo del documento y para los efectos del laboratorio se insertaran códigos en C, estos estará dispuestos dentro de lo que llamaremos “cuadros de código”. Elaborada por: Br. Manuel De Oliveira - Revisado: 25/02/15 Lectura recomendada / Practica 0

description

lectura practica

Transcript of Lectura_Practica

Page 1: Lectura_Practica

Introducción C ha sido distinguido por la eficiencia del código que produce no solo por la potencialidad de los comandos y estructuras de datos sino también por su portabilidad para migrar entre plataformas y dispositivos DSP. Es el lenguaje de programación más popular para crear desarrollos de software, para crear aplicaciones y para la programación de microcontroladores de todo tipo. Se trata de un lenguaje medio nivel pero con muchas características de bajo nivel. Dispone de las estructuras típicas de los lenguajes de alto nivel pero, a su vez, dispone de construcciones del lenguaje que permiten un control a muy bajo nivel. Los compiladores suelen ofrecer extensiones al lenguaje que posibilitan mezclar código en ensamblador con código C o acceder directamente a memoria o dispositivos periféricos. El compilador C traduce programas de alto nivel a lenguaje de máquina que puede ser ejecutado por procesadores como TMS320C55x. Los ambientes de programación incluyen programas de depuración (debugger) para identificar errores en programas fuente. El propósito de la programación DSP es manipular señales digitales para una aplicación específica de procesamiento. Para conseguir esto los programas DSP deben ser capaces de:

Organizar las variables ( diferentes tipos de datos)

Describir las acciones (Operadores)

Controlar las operaciones (Flujo del programa)

Mover los datos de adentro y afuera entre el mundo exterior y el programa (Entradas/Salidas)

El presente documento tiene como objetivo hacer un compendio de los elementos requeridos sobre este lenguaje, considerando su sintaxis, estructura y uso de sus instrucciones, sin embargo no cubre todos los elementos en su totalidad.

Contenido: 1. Estructura de un programa en C. 2. Punteros, funciones, archivos y operaciones I/O 3. Estructuras de control del programa y bucles o ciclos 4. Tipos de datos soportados por la serie TMS320C55x

Nota: A lo largo del documento y para los efectos del laboratorio se insertaran códigos en C, estos estará dispuestos dentro de lo que llamaremos “cuadros de código”.

Elaborada por: Br. Manuel De Oliveira - Revisado: 25/02/15

Lectura recomendada / Practica 0

Page 2: Lectura_Practica

1. Estructura de un programa en C

Un programa en C, consta de varias secciones en donde se determinarán que variables y funciones tendrá el programa, así como la tarea que tendrá que realizar. Los caracteres que se encuentren entre "/*" y "*/", son comentarios y no tienen efecto para la compilación, también puede usarse // para iniciar un comentario por línea. Aunque son opcionales, los comentarios detallados son muy importantes en el mantenimiento de software DSP

Figura 1 Compilación, enlace y ejecución del programa en C

1.1. Instrucciones para el compilador El preprocesador es el primer paso del compilador C, como esta descrito en la figura 1. Se lee en los archivos de código fuente C como entrada y produce archivos de salida para el compilador. Las tareas de preprocesador son eliminar los comentarios, interpretar archivos (include). Las directivas del preprocesador dan instrucciones al compilador que son preformadas antes de compilar el programa. Cada directiva de preprocesador comienza con el carácter “#” seguido de la palabra clave del preprocesador. Por ejemplo, el programa puede contener las siguientes directivas:

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#define K 1024

Page 3: Lectura_Practica

La directiva (#include <file>) copia el archivo de un directorio dentro del

compilador estándar, mientras si se usara (#include 'file') a menos que se haya especificado una ruta directamente, copia el archivo del directorio de trabajo actual para la compilación. Por otro lado la directica (#define) le específica a él preprocesador reemplazar con cada repetición de (K) el valor constante de (1024).

#define name Asocia el símbolo name con la definición #include “file” Copia el directorio especifico file a la compilación actual #include <file> Incluye file de la librería estándar de C

1.2. Programa Principal (Main)

El programa principal contiene las instrucciones y llamadas a funciones que se ejecutan en primera instancia. Un programa en C puede constar de una o más funciones y una y sólo una función llamada main() con la que el sistema comenzará a ejecutar. Después de iniciar la aplicación, la función main() se ejecuta primero, y por lo general es responsable del control del programa. Esta función se puede escribir para devolver un valor, o puede ser escrita como una función void que no devuelve un valor. El cuerpo de la función está encerrado entre llaves como se muestra en el ejemplo main.c.

Como se muestra en el ejemplo, todas las instrucciones en C terminan con un punto y coma (;). La función contiene dos tipos de declaraciones, las declaraciones que definen las posiciones de memoria que se utilizarán en el programa y declaraciones que especifican las acciones a tomar.

1.3. Variables y Operadores de Asignación Antes de que una variable se pueda utilizar en un programa C, debe ser declarada para informar al compilador el nombre y el tipo de la variable. Una variable en C es definida mediante la declaración de que una secuencia de caracteres sean tratados como un particular tipo de dato. Las constantes en C son valores específicos que se incluyen en las sentencias, mientras que las variables son posiciones de memoria que se asignan un nombre o identificador. La declaración de variables usa la siguiente sintaxis:

En el ejemplo del programa principal de la primera sección se muestra unsigned long int i donde se indica el tipo de variable que será almacenada como

void main()

{ unsigned long int i = 1;

short int x ; //Declaraciones para definir variables

x = 2 * i ; //Declaraciones para ejecutar programas

}

Tipo_de_dato Nombre;

Page 4: Lectura_Practica

un valor de dato entero (integer) Un identificador o nombre puede ser cualquier secuencia de caracteres (normalmente con un poco restricción de longitud) que comienza con una letra o un guion bajo, y no puede ser cualquiera de las palabras claves reservadas del compilador C. Como veremos mas adelante incluso los arreglos y punteros de cada tipo de variable deben ser declarados y usados también. Las posiciones de memoria deben definirse antes de que otras sentencias la utilicen. Los valores iniciales también se pueden especificar en el mismo momento en que se definen las ubicaciones de memoria. En el cuadro de código se define la variable N como un entero, y le asigna con el valor 256 El más básico operador de asignación en C es el signo igual sencillo (=), donde el valor a la derecha del signo igual es asignado a la variable de la izquierda. La forma general de la declaración de asignación es: identificador = expresión; donde la expresión puede ser una constante, otra variable, o el resultado de una operación.

C también permite que varias expresiones puedan ser colocadas dentro de una declaración separándolas con las comas. Cada expresión se evalúa de izquierda a derecha, y toda la expresión asume el valor de la última expresión que se evalúa por ejemplo:

Nota: este leguaje en particular es sensitivo a mayúsculas haciendo que las variables DSP, DsP, y dSP sean diferentes.

1.4. Arreglos Un arreglo es una serie de variables distintas del mismo tipo, bajo un solo nombre. Un arreglo de una sola dimensión se puede visualizar como una lista de valores dispuestos en una fila o bien una columna. Se puede asignar un identificador a un arreglo, y luego distinguir entre elementos o valores en el utilizando subíndices. Los subíndices siempre comienzan con 0 y se incrementa en 1. En C, todos los tipos de datos pueden ser declarados como un arreglo colocando el número de elementos a ser asignado a un arreglo entre corchetes después de su nombre.

int i=j=k;

int N = 256;

Page 5: Lectura_Practica

Un arreglo unidimensional se declara como:

Donde el array_name es el nombre de una serie de N elementos del tipo de datos especificados. Arreglos multidimensionales (matrices) se pueden definir simplemente añadiendo más llaves que contengan el tamaño de la matriz en cada dimensión, donde i y j son índices de fila y de columna, respectivamente.

Un arreglo puede ser inicializado cuando se define, o los valores se pueden asignar

a él utilizando sentencias de programa. Para inicializar la matriz al mismo tiempo cuando se define, los valores se especifican en una secuencia que está separado por comas y encerrada con las llaves:

2. Punteros, Funciones, Archivos y operaciones I/O.

2.1. Punteros (Pointers) Además de los tipos de variables mencionados en el documento, C posee otro tipo de variable llamada puntero, un puntero es una variable que almacena una dirección de algún dato, estos son utilizados principalmente para los siguientes propósitos:

Apuntar a diferentes elementos de datos dentro de un arreglo o array.

Permitir a un programa crear nuevas variables mientras el programa se está ejecutando (Posicionamiento dinámico de la memoria).

Acceder a diferentes posiciones en una estructura de datos. Son requeridos dos operadores especiales para manipular adecuadamente los punteros: el operador de inderección (*) es usado cuando es requerido el dato almacenado en la dirección al que apunta el puntero, y el operador de dirección (&) se utiliza para apuntar a la dirección de una variable.

La primera sentencia declara a i como un entero de valor 5 la

segunda declara ptr como un puntero a una variable del tipo integer, la tercera hace que el ptr apunte a la dirección de i, y finalmente la última sentencia cambia el valor contenido de la dirección apuntada de 5 a 8.

Tipo_de_dato array_name[N];

int matriz [i][j];

int y[5]= {1.0, 0.0, 0.0, 0.0, 0.0};

int i = 5;

int *ptr;

ptr = &i;

*ptr = 8;

Page 6: Lectura_Practica

En C, el nombre de un arreglo se puede utilizar como un puntero o puede ser utilizado para hacer referencia a elementos del arreglo por ejemplo en la siguiente sentencia: En el cuadro de código se define a ptr como un puntero a una variable del tipo

integer, por lo que *ptr y ptr[0] son exactamente equivalente, aunque el significado de ptr[0] es con frecuencia mas claro. Nota: Se puede apreciar que la diferencia que existe entre un puntero y un arreglo es que el arreglo tiene una cantidad de memoria propia, mientras que el puntero no.

2.2. Funciones

Como discutimos en las sección 1.2 todos los programas en C tienen una o más funciones incluyendo el main(). En C las funciones o subrutinas estas disponibles en las librerías, estas funciones son un conjunto de sentencias que típicamente ejecutan una operación. Para mantener la simplicidad y la legibilidad en aplicaciones complicadas, se desarrollan programas que usen una función main() añadiendo otras adicionales, en vez de usar una sola función main muy larga. Una función consiste de una definición de sentencia seguida por el cuerpo de la función, la primera parte define el nombre de la función y el tipo de valor que es devuelto por ella y una segunda dentro de un par de paréntesis contiene los argumentos, mientras que las llaves contienen las sentencias ejecutables. Por ejemplo: La primera línea declara la función llamada fir que devuelve un valor del tipo signed long int al programa principal. Note que las variables declaradas como argumentos de la función son en realidad punteros. Adicionalmente variables locales (yn,i) se declaran en el cuerpo de la función, la sentencia return(yn)devuelve el resultado a la función que hizo el llamado. Tenga en cuenta que el tipo de expresión debe coincidir con el tipo de retorno indiciado en la definición de la función, si la función no devolviese un valor, el tipo es void.

signed long int fir(int *x, int *h, int ntap)

{

short int yn = 0.0;// salida del filtro FIR

int i; // índice

//más sentencias

return(yn); // devuelve el valor de y(n) a el main

}

int *ptr;

Page 7: Lectura_Practica

La declaración de una sentencia de función define los parámetros que son requeridos por la función y estos parámetros se denominan parámetros formales. Cualquier declaración que llama a la función debe incluir los valores que corresponden a los parámetros y estos son llamados parámetros actuales. Los parámetros formales y actuales correspondientes deben coincidir en número, el tipo y el orden. Tomando la sentencia del ejemplo anterior: La sentencia desde el programa principal que llama a la función es

Así, las variables:

x, h, ntap son los parámetros formales.

xn, bn, k son los parámetros actuales.

Cuando las referencias a la función fir se ejecutan en el programa principal main, los valores de los parámetros actuales son copiados a los parámetros formales, y

las sentencias en la función fir son ejecutadas usando los nuevos valores en x, h, ntap.

2.3. Archivos y operaciones I/O. En DSP en particular las funciones para interacción con el usuario no son utilizadas, sin embargo con ciertas funciones podremos interactuar con el procesador y sus periféricos. Para usar el estándar de funciones (input/output) provista por el compilador C, debemos tener la directiva del procesador #include <stdio.h> que incluyen los archivos de cabecera del estándar I/O para la declaración de funciones. Las funciones más usadas identifican los archivos para lectura o escritura con el uso de archivos punteros para almacenar la dirección de la información requerida para acceder al archivo. Las funciones como printf()y scanf() ejecutan entradas y salidas formateadas, lo que hace referencia al control de como el dato es leído o escrito, lo que permite convertir por ejemplo una entrada a un tipo de variable especifico (int, char, etc) o escribir una salida de cierta manera. Son usadas del siguiente modo: En cuanto al formato para printf hace referencia a un string que contiene el

texto que va a salir en pantalla, por otro lado las funciones scanf proporcionan una entrada formateada para lectura, por ejemplo en el cuadro de código la sentencia lee desde consola una variable mediante el operador de dirección &.

printf("formato",variable_1, variable_2);

scanf("formato",&variable_1, &variable_2);

signed long int fir(int *x, int *h, int ntap)

Yn = fir(xn, bn, k); // salida del filtro FIR

Page 8: Lectura_Practica

Las funciones de formato I/O también reconocen los siguientes formatos:

%d - Para entero decimal (integer)

%f - Para flotante (float)

%lf - Para double

%c - Para char

%x – Para hexadecimales

\n - Saltos de línea (return) La función fwrite escribe datos binarios. Es decir, fwrite escribe bloques de datos sin formato a un archivo que se ha abierto en modo binario. Los datos escritos pueden ser enteros o números de punto flotante en formato binario (ellos pueden representar sonidos digitales o imágenes). Por el contrario, la función de fread se utiliza para leer datos de un archivo sin formato binario. La función de fread requiere cuatro argumentos. Por ejemplo, las sentencias de ambas funciones serian de la forma:

3. Estructuras de control del programa y bucles o ciclos

El lenguaje C tiene un conjunto completo de características de control del programa que permiten la ejecución condicional o la repetición de declaraciones en bucles basados en el resultado de una expresión.

3.1. Estructuras de Control El lenguaje C proporciona dos métodos básicos para la ejecución de una declaración o serie declaraciones condicionales: la declaración (if) y (switch-case). Declaración If La declaración if nos permite probar una condición y luego ejecutar sentencias en función de si la condición dada es verdadera o falsa. El presente diagrama de flujo indica la lógica asociada al uso de esta estructura de control: Si la condición es verdadera las sentencias dentro de los llaves serán ejecutas de lo contrario serán omitidas.

if(condición)

{ sentencia1;

sentencia2;

}

fread(&xn, sizeof(int), 1, fpin);

fwrite(&yn, sizeof(int), 1, fpout);

Page 9: Lectura_Practica

Declaración if / else Una declaración if/else permite ejecutar un conjunto de sentencias si la condición es verdadera y un conjunto diferente si por el contrario es falsa.

Declaración switch-case Cuando un programa tiene que elegir entre varias alternativas, el if/else es inconveniente y algo ineficaz. Cuando se eligen más de cuatro alternativas desde una sola expresión, la declaración switch-case es muy útil.

El control del programa salta a la sentencia si la etiqueta (case) con la constante (que puede ser un carácter entero o solo entre comillas) coincide con el resultado de la expresión de

entero en la sentencia switch. Si no coincide con el valor constante de la expresión, el control pasa a la instrucción que sigue con la etiqueta (default). Cuando se produce una coincidencia, se ejecutarán las

instrucciones que siguen a la etiqueta (case) correspondiente.

El programa de ejecución continuará hasta que el final de la sentencia switch es conseguida, o una declaración (break) redirija el control hasta el final de la sentencia switch-case. Una declaración (break) se debe incluir en cada (case) y no se requiere después del último (case) o sentencia (default).

switch(expresión entera)

{ case constante_1:

sentencia;

break;

case constante_2;

sentencia;

break;

...

default:

sentencia;

}

if(condición)

{ sentencia A;

}

else

{ sentencia B;

}

Page 10: Lectura_Practica

3.2. Bucles o ciclos (Loops)

El lenguaje C proporciona tres tipos deferentes de estructuras de bucles o ciclos que permiten que una sentencia o un grupo de estas sean repetidas un número fijo o variable. Bucle For Muchas operaciones DSP requieren ciclos que son basados en el valor de la variable que es incrementada o decrementada (contador del ciclo), cuando este alcanza un valor especifico se desea que el programa en ejecución salga del ciclo. El bucle for combina una declaración de inicialización, una de finalización y una de acción, ejecutada al final de cada ciclo, es una de las estructuras de control fundamentales para DSP.

Las instrucciones dentro de las llaves se repetirán

varias veces. Inicialmente K tomará el valor 1 Cada vez

que se repita el ciclo, K aumentará en 1 hasta que K sea igual a N.

Nota: El algoritmo previo describe que el entero K es incrementado si la condición k<N es

verdadera, cuando el bucle finaliza los elementos del arreglo y son fijados a cero desde

y[1] hasta y[N-1]. Bucle While Este bucle repetirá las sentencias hasta que la condición sea probada como falsa o cero, lo que quiere decir que mientras sea verdadera seguirá ejecutándose. Para diseñar esas condiciones pueden utilizarse los operadores lógicos (Ver Apéndice A). La condición se evalúa antes que se ejecuten las sentencias dentro del ciclo. Si la condición es falsa, las sentencias de dentro del bucle se omiten, y la ejecución

continúa con la declaración después del bucle while. Si la condición es verdadera, entonces las sentencias de bucle se ejecutan, y la condición se evalúa de nuevo. Esta repetición continúa hasta que la condición es falsa. Tenga en cuenta que la decisión de ir entrar al bucle se hace antes que el bucle inicie. Debido a esto es posible que el bucle nunca se ejecute. Bucle Do/While

Este bucle es usado cuando un grupo de sentencias necesitan ser repetidas y la condición de salida debe ser probada al final del lazo el formato general es que se muestra en los cuadros de código

for(k=1; k<N; k++)

{ y[k]= 0.0;

}

do{ Sentencia;

}

while(condición);

while (condición)

{ sentencias

}

Page 11: Lectura_Practica

4. Tipos de datos soportados por el TMS320C55x La serie de procesadores TMS320C55x soportan la programación en el estándar C, en él se identifican ciertas características definidas de implementación que pueden diferir de otros compiladores de C, dependiendo del tipo de procesador, el entorno de tiempo de ejecución DSP, y el ambiente que aloja el compilador. El C55x es diseñado para aplicaciones en tiempo real. El tipo de dato más común es el tipo entero (integer) de punto fijo de 16 bits, debido a esto una importante diferencia en la definición del tipo de datos que utiliza el C55x y algún otro compilador C es el tamaño entre datos del tipo. En la siguiente tabla se listan:

Tipo de datos Tamaño Representación Rango

Char 16-bit ASCII [-32768, 32767] Unsigned char 16-bit ASCII [0, 65 535] Short 16-bit Complemento a 2 [-32768, 32767] Unsigned short 16-bit Binaria [0, 65 535] Int 16-bit Complemento a 2 [-32768, 32767] Unsigned int 16-bit Binario [0, 65 535] Long 32-bit Complemento a 2 [-2147483648, 2147483647]

Unsigned long 32-bit Binario [0, 4294967295] Float 32-bit IEEE 32-bit [1.175494 ,3.40282346 ] Double 32-bit IEEE 32-bit [1.175494 ,3.40282346 ] Long double 32-bit IEEE 32-bit [1.175494 ,3.40282346 ] Enum 16-bit Complemento a 2 [-32768, 32767] Data pointer 16-bit Memoria small [0x0, 0xFFFF] Data pointer 23-bit Memoria large [0x0, 0x7FFFFF] Program pointer 24-bit Función [0x0, 0xFFFFFF]

De la tabla debemos considerar lo siguiente:

Los tipos de datos de signo usan representación en complemento a 2.

Es responsabilidad del programador / ingeniero / estudiante, definir y utilizar los tipos de datos correctamente al escribir el programa.

Al portar aplicaciones de un procesador a otro es igualmente importante que la conversión sea aplicada.

Page 12: Lectura_Practica

A. Apéndice A. Operadores A.1. Aritméticos Los operadores aritméticos binarios usuales (son binarios por que realizan las operaciones en dos operadores) los primeros cuatro son definidos para todas las variables, mientras que el ultimo solo para operadores enteros, estos utilizan en C los siguientes símbolos.

Operadores Aritméticos Descripción

Multiplicaciones División Adición Sustracción Modulo (Resto entero después de la división)

C también incluye operadores de incremento (++) y decremento (--) para las variables por ejemplo, la sentencia i++ es igual a la sentencia i=i+1.

Los operadores en C permiten ser combinados con el operador de asignación = , por lo que cualquier sentencia de la forma: x=x+y; es igual a la sentencia x+=y;

Algunas implementaciones en compiladores pueden generar código que es mas eficiente si el operador combinado es usado, los operadores combinados incluyen +, -, *, /,%, y algunos operadores lógicos.

Nota: C no cuenta con el operador de exponenciación sin embargo en la librerías se cuenta con pow(x,y) y puede ser usada para computar . A.2. Lógicos Los operadores lógicos son aquellos que devuelven un valor falso o verdadero. Podría utilizarse para comparar dos valores, si el resultado de una operación lógica es verdadera (true) esta tendrá un valor diferente de cero, por lo contrario si es falso (false) esta valdrá 0.

Operadores Lógicos Descripción

Menor que Mayor que Menor o igual que Igual a Mayor o igual que No igual que AND lógico Or lógico Not lógico

Page 13: Lectura_Practica

A.3. Bit a Bit (Bitwise) Estos operadores a nivel de bits hacen de la programación en C un lenguaje de programación eficiente para aplicaciones DSP.

Operadores Bit a Bit Descripción

AND bit a bit

Or bit a bit

Or exclusivo bit a bit Desplazamiento a la izquierda (del número de bits operando) Desplazamiento a la izquierda (del número de bits operando) Not bit a bit

Page 14: Lectura_Practica

Referencias [1] P. M. Embree, C Algorithms for Real-Time DSP, Englewood Cliffs, NJ: Prentice-Hall, 1995. [2] P. M. Embree and B. Kimble, C Language Algorithms for Digital Signal Processing, Englewood Cliffs, NJ: Prentice-Hall, 1991. [3] S. P. Harbison and G. L. Harbison, C: A Reference Manual, Englewood Cliffs, NJ: Prentice-Hall, 1987.