Estructura de un programa en C
Tomaremos Tomaremos en cuenta este sencillísimo compiladores AVR IAR C y C y AVR GCC. GCC.
ejemplo,
escrito
para
los
/************************** /*************************************** ************************** ************************** ************************* ************** * FileName main.c * !urpose
"#$ parpadeant%e
* !rocessor ATmel AVR AVR * Compiler AVR IAR C & AVR AVR GCC '(inAVR) * Autor
+a%n onson. ttp//%%% ttp// %%%.curso .cursomicros.com. micros.com.
************************* ************************************** ************************** ************************** ************************* *************/ */ -include ar0compiler. //*************************** //**************************************** ************************* ************************* ************************ *********** // delay0ms //*************************** //**************************************** ************************* ************************* ************************ *********** oid delay0ms'unsi1ned int t) 2 %ile't33)
delay0us'4555)6
7 //*************************** //**************************************** ************************* ************************* ************************ *********** // Funci8n principal //*************************** //**************************************** ************************* ************************* ************************ *********** int main'oid) 2 $$R9 : 5;546
=or' 66 )
// Con<1urar pin !95 como salida
2 !>RT9 ?: 5;546 // !oner 4 en pin !95 delay0ms'@55)6 // !>RT9 &: 5;F#6 // !oner !oner 5 en pin !95
delay0ms'55)6 7
7 No ay Bue ser muy perspica para descuDrir lo Bue ace este pro1rama con<1ura el pin !95 como salida y lue1o lo setea y lo limpia tras pausas. #s como acer parpadear un "#$ conectado al pin !95. !arpadea porBue el DloBue de %ile se ejecuta cíclicamente. cíclicamente. "os elementos mEs notaDles de un pro1rama en C son las sentencias, las =unciones, las directias, los comentarios y los DloBues. A continuaci8n, una Dree descripci8n de ellos. Los comentarios
"os comentarios tienen el mismo prop8sito Bue en ensamDlador documentar y adornar el c8di1o. #s todo es te;to Bue si1ue a las Darritas // y todo lo Bue estE entre los si1nos /* y */. +e identi
/* Hsta es una una =orma de comentar comentar arias líneas a la e. +ire muco para enmascarar DloBues de c8di1o. */ Las sentencias
n pro1r pro1ram ama a en C, en lu1ar lu1ar de instru instrucci ccione ones, s, se ejecut ejecuta a por senten sentencia cias. s. na sentencia es al1o así como una me1a instrucci8n, Bue ace lo Bue arias instrucciones del ensamDlador.
2 !>RT9 ?: 5;546 // !oner 4 en pin !95 delay0ms'@55)6 // !>RT9 &: 5;F#6 // !oner !oner 5 en pin !95
delay0ms'55)6 7
7 No ay Bue ser muy perspica para descuDrir lo Bue ace este pro1rama con<1ura el pin !95 como salida y lue1o lo setea y lo limpia tras pausas. #s como acer parpadear un "#$ conectado al pin !95. !arpadea porBue el DloBue de %ile se ejecuta cíclicamente. cíclicamente. "os elementos mEs notaDles de un pro1rama en C son las sentencias, las =unciones, las directias, los comentarios y los DloBues. A continuaci8n, una Dree descripci8n de ellos. Los comentarios
"os comentarios tienen el mismo prop8sito Bue en ensamDlador documentar y adornar el c8di1o. #s todo es te;to Bue si1ue a las Darritas // y todo lo Bue estE entre los si1nos /* y */. +e identi
/* Hsta es una una =orma de comentar comentar arias líneas a la e. +ire muco para enmascarar DloBues de c8di1o. */ Las sentencias
n pro1r pro1ram ama a en C, en lu1ar lu1ar de instru instrucci ccione ones, s, se ejecut ejecuta a por senten sentencia cias. s. na sentencia es al1o así como una me1a instrucci8n, Bue ace lo Bue arias instrucciones del ensamDlador.
+al +alo o caso casoss part partic icul ular ares es,, dond donde e su uso uso es opci opcion onal al,, una una sent senten enci cia a deDe deDe RT9 ?: 5;546 delay0ms'@55)6 delay0ms'@55)6 !>RT9 !>RT9 &: 5;F#6 delay0ms'55)6 delay0ms'55)6 7 7 L+orprendidoM !odrEs deducir Bue los espacios y las taDulaciones solo siren para para darl darle e un aspe aspect cto o orde ordena nado do al c8di c8di1o 1o.. #s una una Duen Duena a prEc prEcti tica ca de pro1ramaci8n pro1ramaci8n aprender a acomodarlas. "as sentencias se pueden clasi
n DloBue estaDlece y delimita el cuerpo de las =unciones y al1unas sentencias mediante llaes '27). Como Como es en el ejemp ejemplo lo de arriD arriDa, a, las =unci =uncione oness main main y pausa pausa tiene tienen n sus DloBues, así como los Ducles %ile y =or. Creo Bue e;a1erJ con los comentarios, pero siren para mostrarnos d8nde empiea y termina cada DloBue. !odrEs er c8m c8mo las las taDu taDula laccion iones ayud ayudan an a dist distin in1 1uir uir unos nos DloB DloBu ues de otr otros. os. A=ortunadamente, los editores de los Duenos compiladores C pueden resaltar cuEl cuEles es son son las las lla llaes es de inic inicio io y de cier cierre re de cada cada DloB DloBue ue.. Te serE serE =Eci =Ecill acostumDrarte a usarlas. Las directivas
+on +on cono conoci cida dass en el len1 len1ua uaje je C como como dire direct cti ias as de prep prepro roce cesa sado dor, r, de preprocesador porBue son ealuadas antes de compilar el pro1rama. Como pasa pasaDa Da en el ensa ensamD mDla lado dor, r, las las dire direct cti ias as por por sí mism mismas as no son son c8di c8di1o 1o ejecutaDle. +uelen ser indicaciones soDre c8mo se compilarE el c8di1o. #ntre #ntre las pocas directias directias del C estEndar estEndar Bue tamDiJn tamDiJn son soportada soportadass por los compilado compiladores res C para AVR estEn -include -include 'para incluir incluir arcio arcios, s, parecido parecido al AssemDler), -de
las -i=, -eli=, -endi= y similares. Fuera de ellas, cada compilador maneja sus propias directias y serEn tratadas por separado. Las funciones
+i un pro1rama en ensamDlador se puede diidir en arias suDrutinas para su mejor estructuraci8n, un pro1rama en C se puede componer de =unciones. !or supuesto Bue las =unciones son mucísimo mEs potentes y, por cierto, al1o mEs complejas de aprender. !or eso ni siBuiera el 1ran espacio Bue se les dedica mEs adelante puede ser su
#n ensamDlador todas las ariaDles de pro1rama suelen ser re1istros de la RA crudos, es decir, datos de O Dits sin =ormato. #n los len1uajes de alto niel estos re1istros son tratados de acuerdo con =ormatos Bue les permiten representar nPmeros de O, 4Q 8 Dits 'a eces mEs 1randes), con si1no o sin Jl, nPmeros enteros o decimales. #sos son los tipos de datos DEsicos. "as ariaDles de los compiladores pueden incluso almacenar matrices de datos del mismo tipo 'llamadas arrays) o de tipos di=erentes 'llamadasestructuras). #stos son los tipos de datos complejos. "os si1uientes son los principales tipos de datos DEsicos del len1uaje C. >Dsera Bue la taDla los separa en dos 1rupos, los tipos enteros y los tipos de punto Sotante. TaDla de ariaDles y tipos de datos del len1uaje C Tipo de dato
TamaKo en Dits
Ran1o de adoptar
alores
car
O
5 a 8 34O a 4U
si1ned car
O
34O a 4U
unsi1ned car
O
5 a
'si1ned) int
4Q
3,UQO a ,UQU
unsi1ned int
4Q
5 a Q,Q
Bue
puede
TaDla de ariaDles y tipos de datos del len1uaje C Tipo de dato
TamaKo en Dits
Ran1o de adoptar
alores
Bue
puede
'si1ned) sort
4Q
3,UQO a ,UQU
unsi1ned sort
4Q
5 a Q,Q
'si1ned) lon1
3,4@U,@O,Q@O a ,4@U,@O,Q@U
unsi1ned lon1
5 a @,@,QU,
'si1ned) lon1 lon1 'int)
Q@
3 Q a Q 3 4
unsi1ned lon1 lon1'int)
Q@
5 a Q@ 3 4
Soat
W4.4O#3O a W.#XO
douDle
W4.4O#3O a W.#XO
douDle
Q@
W.#35O a W4.U#X5O
A=ortunadamente, a di=erencia de los compiladores para !IC, los compiladores para AVR suelen respetar Dastante los tipos estaDlecidos por el AN+I C. Al1unos compiladores tamDiJn manejan tipos de un Dit como Dool 'o Doolean) o Dit, pero con peBueKas dier1encias Bue pueden a=ectar la portaDilidad de los c8di1os ademEs de con=undir a los pro1ramadores. #sos tipos son raramente usados. !or de=ecto el tipo douDle es de Dits en los microcontroladores. #n ese caso es eBuialente al tipo Soat. "os compiladores mEs potentes como AVR IAR C y AVR GCC sin emDar1o o=recen la posiDilidad de con<1urarlo para Bue sea de Q@ Dits y poder traDajar con datos mEs 1randes y de mayor precisi8n. "os especi
este tipo para almacenar nPmeros de O Dits. #s decir es eBuialente a si1ned car o unsi1ned car, dependiendo de la con<1uraci8n estaDlecida por el entorno compilador. Y como es pre=eriDle dejar de lado estas cuestiones, si amos a traDajar con nPmeros lo mejor es poner el especi
TamaKo en Dits
Ran1o de alores Bue puede adoptar
intO0t
O
34O a 4U
uintO0t
O
5 a
int4Q0t
4Q
3,UQO a ,UQU
uint4Q0t
4Q
5 a Q,Q
int0t
3,4@U,@O,Q@O a ,4@U,@O,Q@U
uint0t
5 a @,@,QU,
intQ@0t
Q@
3Q a Q 3 4
TaDla de ariaDles y tipos de datos del len1uaje C Tipo de dato uintQ@0t
TamaKo en Dits
Ran1o de alores Bue puede adoptar 5 a Q@ 3 4
Q@
#s =Ecil descuDrir la estructura de estos tipos para =amiliariarse con su uso. !ara ello deDemos en primer lu1ar incluir en nuestro pro1rama el arcio stdint. con la si1uiente directia. -include [stdint.\ #sta inclusi8n ya estE eca en el arcio ar0compiler. Bue se usa en todos los pro1ramas de cursomicros, así Bue no es necesario olerlo a acer. AunBue el oDjetio de este arcio es permitir la compatiDilidad de c8di1os entre los compiladores AVR IAR C y AVR GCC, deDemos saDer Bue en AVR IAR C el arcio ar0compiler. solo estE disponiDle al usar la liDrería $"I9. Como las prEcticas de cursomicros traDajan soDre la liDrería C"I9, e eitado recurrir a los tipos e;tendidos de stdint.. Finalmente, e;isten ademEs de los istos arriDa otros tipos y especi
#sta parte es comparaDle, aunBue lejanamente a cuando se identi
// VariaDle para enteros de O Dits sin si1no
// VariaDle de O Dits 'para almacenar // caracteres ascii)
si1ned car c6
// VariaDle para enteros de O Dits con si1no
int i6
// i es una ariaDle int, con si1no
si1ned int j6
// j tamDiJn es una ariaDle int con si1no
unsi1ned int ]6
// ] es una ariaDle int sin si1no
TamDiJn es posiDle declarar arias ariaDles del mismo tipo, separEndolas con comas. Así nos aorramos al1o de tipeo. !or ejemplo Soat area, side6
// $eclarar ariaDles area y side de tipo Soat
unsi1ned car a, D, c6 // $eclarar ariaDles a, D y c como unsi1ned car Especicadores de tipo de datos
A la declaraci8n de una ariaDle se le puede aKadir un especi
// $eclarar constante a
// $eclarar ariaDle D
//... D : a6
// VElido
D : 456
// VElido
a : Q56
// #rror^ a es constante
a : D6
// #rror^ a es constante
!or mEs Bue las ariaDles constantes sean de solo lectura, ocuparEn posiciones en la RA del microcontrolador. #n CodeVisionAVR es posiDle con<1urar para Bue sí residan en F"A+_ pero por compatiDilidad se usa muy poco. !or eso mucas eces es pre=eriDle de
// $e
Sentencias selectivas
"lamadas tamDiJn sentencias de Di=urcaci8n, siren para rediri1ir el Sujo de un pro1rama se1Pn la ealuaci8n de al1una condici8n l81ica. "as sentencias i= e i= else son casi estEndar en todos los len1uajes de pro1ramaci8n. AdemEs de ellas estEn las sentencias i= else escalonadas y s%itc case. –
–
–
La sentencia if
"a sentencia i= 'si condicional, en in1lJs) ace Bue un pro1rama ejecute una sentencia o un 1rupo de ellas si una e;presi8n es cierta. #sta l81ica se descriDe en el si1uiente esBuema.
$ia1rama de Sujo de la sentencia i=. "a =orma codi
// +i e;pression04 es erdadera ejecutar
// este DloBue
sentencia46
sentencia6 7 else i= ' e;pression0 ) 2
// #n caso contrario y si e;pression0 es
// erdadera, ejecutar este DloBue
sentencia6
sentencia@6 7 else i= ' e;pression0 ) 2
// #n caso contrario y si e;pression0 es
// erdadera, ejecutar este DloBue
sentencia6
sentenciaQ6
7 else
// #n caso contrario, ejecutar este DloBue
2
sentenciaU6
sentenciaO6 76
// 6 opcional
// todo... "as e;presiones se ealPan de arriDa aDajo. Cuando al1una de ellas sea erdadera, se ejecutarE su DloBue correspondiente y los demEs DloBues serEn salteados. #l DloBue
"a sentencia s%itc Drinda una =orma mEs ele1ante de Di=urcaci8n mPltiple. !odemos considerarla como una =orma mEs estructurada de la sentencia i= – else – i= escalonada, aunBue tiene al1unas restricciones en las condiciones l81icas a ealuar, las cuales son comparaciones de alores enteros. !ara elaDorar el c8di1o en reseradas s%itc, case, Drea] y de=ault.
C
se
usan
las
palaDras
#l si1uiente esBuema presenta tres cases pero podría aDer mEs, así como cada DloBue tamDiJn podría tener mEs sentencias. s%itc ' e;pression ) 2 case constante4 // +i e;pression : constante4, ejecutar este DloBue
sentencia46
sentencia6
Drea]6 case constante // +i e;pression : constante, ejecutar este DloBue
sentencia6
sentencia@6
Drea]6 case constante // +i e;pression : constante, ejecutar este DloBue
sentencia6
sentenciaQ6
Drea]6 de=ault
// +i e;pression no =ue i1ual a nin1una de las // constantes anteriores, ejecutar este DloBue
sentenciaU6
sentenciaO6
Drea]6 7
sentencia`6 // todo... donde constante4, constante y constante deDen ser constantes enteras, por ejemplo, , 5;@, ba, etc. 'ba tiene c8di1o A+CII 4Q, Bue es, a
"as sentencias de control iteratias siren para Bue el pro1rama ejecute una sentencia o un 1rupo de ellas un nPmero determinado o indeterminado de eces. Así es, esta secci8n no aDla de otra cosa Bue de los Ducles en C. #l len1uaje C soporta tres tipos de Ducles, las cuales se construyen con las sentencias %ile, do %ile y =or. #l se1undo es una ariante del primero y el tercero es una ersi8n mEs compacta e intuitia del Ducle %ile. –
La sentencia !ile
#l cuerpo o DloBue de este Ducle se ejecutarE una y otra e mientras '%ile, en in1lJs) una e;presi8n sea erdadera.
$ia1rama de Sujo de las sentencia %ile. #l Ducle %ile en C tiene la si1uiente sinta;is y se lee así mientras '%ile) e;pression sea erdadera, ejecutar el si1uiente DloBue. sentenciaA6 %ile ' e;pression )
// ientras e;pression sea erdadera, ejecutar el
// si1uiente DloBue 2
sentencia96
sentenciaC6 // ... 76
sentencia`6
// #ste 6 es opcional
// ... Nota Bue en este caso primero se ealPa e;pression. !or lo tanto, si desde el principio la e;pression es =alsa, el DloBue de %ile no se ejecutarE nunca. !or otro lado, si la e;pression no deja de ser erdadera, el pro1rama se BuedarE dando ueltas para siempre. La sentencia do " !ile
Como dije antes, es una ariaci8n de la sentencia %ile simple. "a principal di=erencia es Bue la condici8n l81ica 'e;pression) de este Ducle se presenta al
$ia1rama de Sujo de las sentencia do – %ile. "a sinta;is para la sentencia do %ile es la si1uiente y se lee #jecutar 'do) el si1uiente DloBue, mientras '%ile) e;pression sea erdadera. –
sentenciaA6 do 2
sentencia96
sentenciaC6 // ... 7 %ile ' e;pression )6 // #ste 6 es mandatorio
sentencia`6 // ...
La sentencia for
"as dos sentencias anteriores, %ile y do %ile, se suelen emplear cuando no se saDe de antemano la cantidad de eces Bue se a a ejecutar el Ducle. #n los casos donde el Ducle inolucra al1una =orma de conteo
Hsta es la sinta;is 1eneral de la sentencia =or en C =or ' e;pression04 6 e;pression0 6 e;pression0 ) 2
sentencia46
sentencia6 // ... 76
// #ste 6 es opcional
Aora eamos por partes c8mo =unciona e;pression04 suele ser una sentencia de inicialiaci8n. e;pression0 se ealPa como condici8n l81ica para Bue se ejecute el DloBue. e;pression0 es una sentencia Bue deDería poner coto a e;pression0. !or la =orma y orden en Bue se ejecutan estas e;presiones, el Ducle =or es eBuialente a la si1uiente construcci8n, utiliando la sentencia %ile. !rimero se ejecuta e;pression04 y lue1o se ejecuta el DloBue indicado tantas eces mientras e;pression0 sea erdadera. e;pression046 %ile ' e;pression0 ) 2
sentencia46
sentencia6 // ...
e;pression06
7 No oDstante, de esa =orma se e mEs rara aPn6 así Bue, mejor, eamos estos ejemplos, Bue son sus presentaciones mEs clEsicas. 'i es una ariaDle y a y D son constantes o ariaDles) =or ' i : 5 6 i [ 45 6 iXX ) 2
sentencias6 7
+e lee para '=or) i i1ual a 5 asta Bue sea menor Bue 45 ejecutar sentencias. "a sentencia iXXindica Bue i se incrementa tras cada ciclo. Así, el DloBue de =or se ejecutarE 45 eces, desde Buei al1a 5 asta Bue al1a . #n este otro ejemplo las sentencias se ejecutan desde Bue i al1a 45 asta Bue al1a 5. #s decir, el Ducle darE 44 ueltas en total. =or ' i : 45 6 i [: 5 6 iXX ) 2
sentencias6 7
#l si1uiente Ducle =or empiea con i inicialiado a 455 y su DloBue se ejecutarE mientras i sea mayor o i1ual a 5. !or supuesto, en este caso i se decrementa tras cada ciclo. =or ' i : 455 6 i \: 5 6 i33 ) 2
sentencias6 7
+e pueden acer mucas mEs construcciones, todas coincidentes con la primera plantilla, pero tamDiJn son menos =recuentes. Sentencias con bloques simples
Cuando las sentencias selectias 'como i=) o de Ducles 'como %ile o =or) tienen cuerpos o DloBues Bue constan de solo una sentencia, se pueden omitir las llaes. Aun así, es aconsejaDle se1uir manteniendo las taDulaciones para eitarnos con=usiones.
!or ejemplo, las si1uientes sentencias i='a \ D) 2 a : 56 7
i='a :: D) 2
aXX6 7
else 2
D336 7
%ile' a \: D) 2 a : a X D6 7
=or'i:56 i[:456 iXX) 2 a : a*6 7 Dien se pueden escriDir de la si1uiente =orma i='a \ D)
a : 56
i='a :: D)
aXX6
else
D336
%ile' a \: D) a : a X D6
=or'i:56 i[:456 iXX) a : a*6
Los operadores
+iren para realiar operaciones aritmJticas, l81icas, comparatias, etc. +e1Pn esa =unci8n se clasi
AdemEs de los típicos operadores de suma, resta, multiplicaci8n y diisi8n, estEn los operadores de m8dulo, incremento y decremento. TaDla de >peradores aritmJticos >perador
Acci8n
X
+uma
3
Resta
*
ultiplicaci8n
/
$iisi8n
8dulo. Retorna el residuo de una diisi8n entera. +olo se deDe
TaDla de >peradores aritmJticos >perador
Acci8n usar con nPmeros enteros.
XX
Incrementar en uno
33
$ecrementar en uno
#jemplos int a, D, c6
// $eclarar ariaDles a, D y c
a : D X c6
// +umar a y D. Almacenar resultado en c
D : D * c6
// ultiplicar D por c. Resultado en D
D : a / c6
// $iidir a entre c. Colocar resultado en D
a : a X c D6
// +umar a y c y restarle D. Resultado en a
c : 'a X D) / c6
// $iidir aXD entre c. Resultado en c
D : a X D / c X D * D6 // +umar a mEs D/c mEs DfD. Resultado en D c : a D6 aXX6 D336 XXc6 33D6
// Residuo de diidir agD a c // Incrementar a en 4 // $ecrementar D en 4 // Incrementar c en 4 // $ecrementar D en 4
LTe recordaron a tus clases de El1eDra del cole1ioM A di=erencia de esas matemEticas, estas e;presiones no son ecuaciones6 si1ni
+i XX o 33 estEn antes del operando, primero se suma o resta 4 al operando y lue1o se ealPa la e;presi8n. +i XX o 33 estEn despuJs del operando, primero se ealPa la e;presi8n y lue1o se suma o resta 4 al operando. int a, D6
// $eclarar ariaDles enteras a y D
a : DXX6
// "o mismo Bue a : D6 y lue1o D : D X 46
a : XXD6
// "o mismo Bue D : D X 46 y lue1o a : D6
i= 'aXX [ 45) 2
// !rimero comprueDa si a [ 45 y lue1o // incrementa a en 4
// al1Pn c8di1o 7
i= 'XXa [ 45) 2
// !rimero incrementa a en 4 y lue1o // comprueDa si a [ 45
// al1Pn c8di1o 7 #peradores de bits
+e aplican a operaciones l81icas con ariaDles a niel Dinario. ABuí tenemos las clEsicas operaciones AN$, >R inclusia, >R e;clusia y la N#GACIhN. Adicionalmente, e incluido en esta cate1oría los operaciones de desplaamiento a la dereca y la iBuierda. +i Dien son operaciones Bue producen resultados anElo1os a los de las instrucciones de ensamDlador los operadores l81icos del C pueden operar soDre ariaDles de distintos tamaKos, ya sean de 4, O, 4Q 8 Dits. TaDla de operadores de Dits >perador
Acci8n
&
AN$ a niel de Dits
TaDla de operadores de Dits >perador
Acci8n
?
>R inclusia a niel de Dits
>R e;clusia a niel de Dits
Complemento a uno a niel de Dits
[[
$esplaamiento a la iBuierda
\\
$esplaamiento a la dereca
#jemplos car m6 int n6
// ariaDle de O Dits // ariaDle de 4Q Dits
m : 5;@O6
// m serE 5;@O
m : m & 5;5F6
// $espuJs de esto m serE 5;5O
m : m ? 5;@6
// $espuJs de esto m serE 5;F
m : m & 5D444455556 n : 5;FF556
// n serE 5;FF55
n : n6
// n serE 5;55FF
m : m ? 5D455555546 m : m & 5;F56
// +etear Dits 5 y U de ariaDle m
// "impiar niDDle Dajo de ariaDle m
m : m 5D554455556
m : 5D555445556 m : m \\ 6
// $espuJs de esto m serE 5;5
// Inertir Dits @ y de ariaDle m
// Car1ar m con 5D55544555 // $esplaar m posiciones a la dereca
// Aora m serE 5D55555445
n : 5;FF4F6 n : n [[ 46
// $esplaar n 4 posiciones a la iBuierda // Aora n serE 5;F5556
m : m [[ O6
// $espuJs de esto m serE 5;55
Fíjate en la semejana entre las operaciones de desplaamiento con \\ y [[ y las operaciones del rotaci8n del ensamDlador. Cuando una ariaDle se desplaa acia un lado, los Dits Bue salen por allí se pierden y los Dits Bue entran por el otro lado son siempre ceros. #s por esto Bue en la Pltima sentencia, m : m [[ O, el resultado es 5;55. !or cierto, en el len1uaje C no e;isten operadores de rotaci8n. _ay =ormas alternatias de realiarlas.
$esplaamientos producidos por los operadores [[ y \\.
#peradores relacionales
+e emplean para construir las condiciones l81icas de las sentencias de control selectias e iteratias, como ya emos podido apreciar en las secciones anteriores. "a si1uiente taDla muestra los operadores relacionales disponiDles. TaDla de >peradores relacionales >perador
Acci8n
::
I1ual
^:
No i1ual
\
ayor Bue
[
enor Bue
\:
ayor o i1ual Bue
[:
enor o i1ual Bue
#peradores lógicos
Generalmente se utilian para enlaar dos o mEs condiciones l81icas simples. !or suerte, estos operadores solo son tres y serEn e;plicados en las prEcticas del curso. TaDla TaDla de >peradores >peradores l81icos >perador
Acci8n
&&
AN$ l81ica
??
>R l81ica
^
Ne1aci8n l81ica
#jemplos i=' ^'a::5) )
// +i a i1ual 5 sea =also
2 // sentencias 7
i=' 'a[D) && 'a\c) )
// +i a[D y a\c son erdaderas
2 // sentencias 7
%ile' 'a::5) ?? 'D::5) ) // ientras a sea 5 8 D sea 5 2 // sentencias 7 Composición de operadores
+e utilia en las operaciones de asi1naci8n y nos permite escriDir c8di1o mEs aDreiado. "a =orma 1eneral de escriDir una sentencia de asi1naci8n mediante los operadores compuestos es
oDtect op: e;pression6 Bue es eBuialente a la sentencia oDject : oDject op e;pression6 op puede ser cualBuiera de los operadores aritmJticos o de Dit estudiados arriDa. arriDa. > sea, oppuede oppuede ser X, 3 , *, /, , &, ? , , , [[ 8 \\. \\. Nota Nota no deDe aDer nin1Pn espacio entre el operador y el si1no i1ual. #jemplos int a6
// $eclarar a
a X: 56
// #s lo mismo Bue a : a X 56
a X: 56
// TamDiJn si1ni
a *: 6
// #s lo mismo Bue a : a * 6
a &: 5;F56
// #s lo mismo Bue a : a & 5;F56
a [[: 46
// #s lo mismo Bue a : a [[ 46
%recedencia de operadores
na e;presi8n puede contener arios operadores, de esta =orma D : a * D X c / D6
// a, D y c son ariaDles
A di=erencia del len1uaje 9asic, donde la e;presi8n se ealPa de iBuierda a dereca, en esta sentencia no Bueda claro en BuJ orden se ejecutarEn las operaciones indicadas. _ay ciertas re1las Bue estaDlecen dicas prioridades6 por ejemplo, las multiplicaciones y diisiones siempre se ejecutan antes Bue las sumas sumas y resta restas. s. !ero !ero es mEs prEcti prEctico co emplea emplearr los parJnt parJntesi esis, s, los cuales cuales orden ordenan an Bue Bue primer primero o se ejecut ejecuten en las operac operacion iones es de los parJnt parJntesi esiss mEs internos. #so es como en el El1eDra elemental de la escuela, así Bue no pro=undiarJ. !or ejemplo, las tres si1uientes sentencias son di=erentes. D : 'a * D) X 'c / D)6 D : a * 'D X 'c / D))6 D : ''a * D) X c)/ D)6 TamDiJn TamDiJn se pueden pueden construir e;presiones e;presiones condicionales, condicionales, así i= ' 'a \ D) && ' D [ c) ) // +i a\D y D[c, ...
2 // ... 7
Las funciones
na =unci8n es un DloBue de sentencias identi
data0type4 =unction0name =unction0name 'data0type ar14, data0type ar1, ... ) 2 // Cuerpo de la =unci8n // ... return +ome$ata6 // Necesario solo si la =unci8n retorna al1Pn alor 7 $onde =unction0name es el nomDre un identi
de
la
=unci8n.
!uede
s er
data0type4 es un tipo de dato Bue identi
!ara una =unci8n Bue no reciDe ni deuele nin1Pn alor, la plantilla de arriDa se reduce al si1uiente esBuema oid =unction0name ' oid ) 2 // Cuerpo de la =unci8n 7 Y se llama escriDiendo su nomDre se1uido de parJntesis acíos, así =unction0name')6 "a =unci8n principal main es otro ejemplo de =unci8n sin parEmetros. $ondeBuiera Bue se uDiBue, siempre deDería ser la primera en ejecutarse6 de eco, no deDería terminar. oid main 'oid) 2 // Cuerpo de la =unci8n 7
&unciones con par'metros (por valor)
!or el momento, solo estudiaremos las =unciones Bue pueden tener arios parEmetros de entrada pero solo uno de salida. +i la =unci8n no tiene parEmetros de entrada o de salida, deDe escriDirse un oid en su lu1ar. #l alor deuelto por una =unci8n se indica con la palaDra reserada return. +e1Pn el comportamiento de los parEmetros de entrada de la =unci8n, estos se diiden enparEmetros por alor y parEmetros por re=erencia. "o e;puesto en este apartado corresponde al primer 1rupo porBue es el caso mEs ampliamente usado. Con esto en mente podemos se1uir. !ara llamar a una =unci8n con parEmetros es importante respetar el orden y el tipo de los parEmetros Bue ella reciDe. #l primer alor pasado corresponde al primer parEmetro de entrada6 el se1undo alor, al se1undo parEmetro6 y así sucesiamente si uDiera mEs.
Cuando una ariaDle es entre1ada a una =unci8n, en realidad se le entre1a una copia suya. $e este modo, el alor de la ariaDle ori1inal no serE alterado. ejor, plasmemos todo esto en el si1uiente ejemplo. int minor ' int ar14, int ar1, int ar1 ) 2 int min6 min : ar146
// $eclarar ariaDle min // Asumir Bue el menor es ar14
i= ' ar1 [ min ) // +i ar1 es menor Bue min min : ar16
// CamDiar a ar1
i= ' ar1 [ min ) // +i ar1 es menor Bue min min : ar16
return min6
// CamDiar a ar1
// Retornar alor de min
7 oid main 'oid) 2 int a, D, c, d6
// $eclarar ariaDles a, D, c y d
/* ABuí asi1namos al1unos alores iniciales a kak, kDk y kck */ /* ... */ d : minor'a,D,c)6 // "lamar a minor // #n este punto kdk deDería ser el menor entre kak, kDk y kck %ile '4)6
// 9ucle in
7 #n el pro1rama mostrado la =unci8n minor reciDe tres parEmetros de tipo int y deuele uno, tamDiJn de tipo int, Bue serE el menor de los nPmeros reciDidos.
#l mecanismo =unciona así siempre respetando el orden, al llamar a minor el alor de a se copiarE a la ariaDle ar146 el alor de D, a ar1 y el alor de c, a ar1. $espuJs de ejecutarse el c8di1o de la =unci8n el alor de retorno 'min en este caso) serE copiado a una ariaDle temporal y de allí pasarE a d. AunBue el C no es tan implacaDle con la comproDaci8n de tipos de datos como !ascal, siempre deDeríamos reisar Bue los datos pasados sean compatiDles con los Bue la =unci8n espera, así como los datos reciDidos, con los Bue la =unci8n deuele. !or ejemplo, estaría mal llamar a la =unci8n minor del si1uiente modo d : minor'34, 455, .4@)6 // "lamar a minor ABuí los dos primeros parEmetros estEn Dien, pero el tercero es un nPmero decimal 'de Dits), no compatiDle con el tercer parEmetro Bue la =unci8n espera 'entero de 4Q Dits). #n estos casos el compilador nos mostrarE mensajes de error, o cuando menos de adertencia.
%ar'metros por referencia
"a =unci8n Bue reciDe un parEmetro por re=erencia puede camDiar el alor de la ariaDle pasada. "a =orma clEsica de estos parEmetros se puede identitra =orma de pasar un parEmetro por re=erencia es mediante los punteros, pero eso lo dejamos para el
#l prototipo de una =unci8n le in=orma al compilador las características Bue tiene, como su tipo de retorno, el nPmero de parEmetros Bue espera reciDir, el
tipo y orden de dicos parEmetros. !or eso se deDen declarar al inicio del pro1rama. #l prototipo de una =unci8n es muy parecido a su encaDeado, se pueden di=erenciar tan solo por terminar en un punto y coma '6). "os nomDres de las ariaDles de entrada son opcionales. !or ejemplo, en el si1uiente Doceto de pro1rama los prototipos de las =unciones main, =unc4 y=unc declaradas al inicio del arcio permitirEn Bue dicas =unciones sean accedidas desde cualBuier parte del pro1rama. AdemEs, sin importar d8nde se uDiBue la =unci8n main, ella siempre serE la primera en ejecutarse. !or eso su prototipo de =unci8n es opcional. -include [ar.\
oid =unc4'car m, lon1 p)6 // !rototipo de =unci8n =unc4 car =unc'int a)6
// !rototipo de =unci8n =unc
oid main'oid)6
// !rototipo de =unci8n main. #s opcional
oid main'oid) 2 // Cuerpo de la =unci8n // $esde aBuí se puede acceder a =unc4 y =unc 7 oid =unc4'car m, lon1 p) 2 // Cuerpo de la =unci8n // $esde aBuí se puede acceder a =unc y main 7 car =unc'int a) 2 // Cuerpo de la =unci8n
// $esde aBuí se puede acceder a =unc4 y main 7 "a llamada a main, por supuesto, no tiene sentido6 solo lo pon1o para ilustrar. +i las =unciones no tienen prototipos, el acceso a ellas serE restrin1ido. #l compilador solo erE las =unciones Bue estEn implementadas encima de la =unci8n llamadora o, de lo contrario, mostrarE errores de =unci8n no de
oid main'oid) 2 // Cuerpo de la =unci8n // $esde aBuí no se puede acceder a =unc4 ni =unc porBue estEn aDajo 7 oid =unc4'car m, lon1 p) 2 // Cuerpo de la =unci8n // $esde aBuí se puede acceder a main pero no a =unc 7 car =unc'int a) 2 // Cuerpo de la =unci8n // $esde aBuí se puede acceder a =unc4 y main 7 !ara terminar, dado Bue los nomDres de las ariaDles en los parEmetros de entrada son opcionales, los prototipos de =unc4 y =unc tamDiJn se pueden escriDir asi oid =unc4'car, lon1)6
car =unc'int )6
Variables locales y variables globales
"os len1uajes de alto niel como el C =ueron diseKados para desarrollar los pro1ramas mEs 1randes y complejos Bue se puedan ima1inar, pro1ramas donde puede aDer cientos de ariaDles, entre otras cosas. LIma1inas lo Bue si1ni
int speed6
// !rototipo de =unci8n
// VariaDle 1loDal
const lon1 limit : 4556 // VariaDle 1loDal constante
oid inter'oid)
2 int count6
// VariaDle local
/* #ste count no tiene nada Bue er con el count de las =unciones main o =oo */
speedXX6
// Acceso a ariaDle 1loDal speed
ari : 56
// #sto darE #RR>R porBue ari solo pertenece // a la =unci8n =oo. No compilarE.
7 oid main'oid) 2 int count6
// VariaDle local count
/* #ste count no tiene nada Bue er con el count de las =unciones inter o =oo */ count : 56
// Acceso a count local
speed : 56
// Acceso a ariaDle 1loDal speed
7 car =oo'lon1 count)
// VariaDle local count
2 int ari6
// VariaDle local ari
7 Al1o muy importante a di=erencia de las ariaDles 1loDales, las ariaDles locales tienen almacenamiento temporal, es decir, se crean al ejecutarse la =unci8n y se destruyen al salir de ella. LZuJ si1ni
+i dentro de una =unci8n ay una ariaDle local con el mismo nomDre Bue una ariaDle 1loDal, la precedencia en dica =unci8n la tiene la ariaDle local. +i te con=unde, no uses ariaDles 1loDales y locales con el mismo nomDre. Variables static
Antes de nada deDemos aclarar Bue una ariaDle static local tiene di=erente si1ni
// $eclarar ariaDle a // Incrementar a
7 CualBuiera Bue aya sido su alor inicial, Lcrees Bue despuJs de llamar a esta =unci8n 45 eces, el alor de a se aDrE incrementado en 45M... !ues, no necesariamente. Cada e Bue se llame a increm se crea a, lue1o se incrementa y, al terminar de ejecutarse la =unci8n, se destruye. !ara Bue una ariaDle ten1a una locaci8n de memoria independiente y su alor no camDie entre llamadas de =unci8n tenemos dos caminos o la declaramos como 1loDal, o la declaramos comolocal estEtica. "os Duenos pro1ramadores siempre eli1en el se1undo. na ariaDle se ace estEtica anteponiendo a su declaraci8n el especi
// VariaDle static 'inicialiada a 5 por de=ecto)
static int ar : 56 // VariaDle static inicialiada a 5 #jemplos.
oid increm') 2 static int a : 6 // VariaDle local estEtica inicialiada a aXX6
// Incrementar a
7 oid main') 2 int i6
// $eclarar ariaDle i
// #l si1uiente c8di1o llama 45 eces a increm =or'i:56 i[456 iXX)
increm')6
// Aora la ariaDle a sí deDería aler 4 %ile'4)6
// 9ucle in
7 Variables volatile
A di=erencia de los ensamDladores, los compiladores tienen cierta inteli1encia. #s decir, piensan un poco antes de traducir el c8di1o =uente en c8di1o ejecutaDle. !or ejemplo, eamos el si1uiente pedao de c8di1o para saDer lo Bue suele pasar con una ariaDle ordinaria int ar6
// $eclarar ariaDle ar
//... ar : ar6
// Asi1nar ar a ar
#l compilador creerE 'proDaDlemente como nosotros) Bue la sentencia ar : ar no tiene sentido 'y BuiE ten1a ra8n) y no la tendrE en cuenta, la i1norarE. Hsta es solo una muestra de lo Bue si1ni
#l ejemplo anterior =ue al1o Durdo, pero aDrE c8di1os con redundancias aparentes y mEs di=íciles de localiar, cuya optimiaci8n puede ser contraproducente. #l caso mEs notaDle Bue destacan los manuales de los compiladores C para microcontroladores es el de las ariaDles 1loDales Bue son accedidas por la =unci8n de interrupci8n y por cualBuier otra =unci8n. !ara Bue un compilador no intente pasarse de listo con una ariaDle deDemos declararla comoolatile, anteponiJndole dico cali
oid interrupt'oid)
// count es ariaDle 1loDal olEtil
// Funci8n de interrupci8n
2 // C8di1o Bue accede a count 7
oid main'oid)
// Funci8n principal
2 // C8di1o Bue accede a count 7
*rrays y %unteros
!roDaDlemente Jste sea el tema Bue a todos nos a dado mEs de un dolor de caDea y Bue mEs emos releído para captarlo a caDalidad. _aDlo mEs Dien de los punteros. +i ellos el C no sería nada, perdería la potencia por la Bue las mejores empresas lo eli1en para crear sus so=t%ares de computadoras. !ero Dueno, re1resando a lo nuestro, estos temas se pueden complicar mucísimo mEs de lo Bue eremos aBuí. +olo eremos los arrays unidimensionales y los punteros 'Bue en principio pueden apuntar a todo tipo
de cosas) los aDocaremos a los datos DEsicos, incluyendo los mismos arrays. Aun así, te su1iero Bue ten1as un par de aspirinas al lado. Los arrays o matrices
n array es una me1a ariaDle compuesto de un conjunto de ariaDles simples del mismo tipo y uDicadas en posiciones conti1uas de la memoria. Con los arrays podemos acer todos lo Bue acíamos con las taDlas 'de DPsBueda) del ensamDlador y mucísimo mEs. n array completo tiene un nomDre y para acceder a cada uno de sus elementos se utilian índices entre corcetes ' ). "os índices pueden estar indicados por ariaDles o constantes. #n el si1uiente esBuema se e Bue el primer elemento de un array tiene índice 5 y el Pltimo, N34, siendo N la cantidad de elementos del array.
#structura de un array unidimensional de N elementos. Declaración de arrays
!ara declarar un array unidimensional se utilia la si1uiente sinta;is data0type identi
// letters es un array de 45 elementos de tipo car
lon1 _e;TaDle4Q6 // _e;TaDle es un array de 4Q elementos de tipo lon1 int address4556 // address es un array de 455 elementos de tipo int !ara el array letters el primer elemento es letters5 y el Pltimo, letters. Así, tenemos 45 elementos en total. +i BuisiJramos asi1nar a cada uno de los elementos de letters los caracteres desde la ba asta la bj, lo podríamos acer indiidualmente así
letters5 : kak6
// ABuí el índice es 5
letters4 : kDk6
// ABuí el índice es 4
letters : kck6
// ...
letters : kdk6
//
letters@ : kek6 letters : k=k6 lettersQ : k1k6 lettersU : kk6 lettersO : kik6 letters : kjk6
// ABuí el índice es
!ero así no tiene 1racia utiliar arrays. #n este caso lo mejor es utiliar un Ducle, así 'Nota los caracteres son, al
"os elementos de un array se pueden inicialiar junto con su declaraci8n. !ara ello se le asi1na una lista ordenada de alores encerrados por llaes y separados por comas. !or supuesto, los alores deDen ser compatiDles con el tipo de dato del array. #ste tipo de inicialiaci8n solo estE permitido en la declaraci8n del array. #jemplos unsi1ned car mas] : 2 5;F5, 5;5F, 5;C 76 // >] int a : 2 5, Q, OU, 3O, 555 76
// >]
car ocals : 2 kak, kek, kik, kok, kuk 76 // >] int c@ : 2 , Q, 5, 3, 5, @ 76 // #rror, demasiados inicialiadores TamDiJn es posiDle inicialiar un array sin especi
te;to, donde puede resultar muy inc8modo estar contando las letras de una cadena. !or ejemplo int a : 2 U5, 4, 4 76
// n array de elementos
car ocals : 2 kak, kek, kik, kok, kuk 76
// n array de elementos
car ms1 : #ste es un array de caracteres6 // n array o= 4 elementos L!or BuJ el Pltimo array tiene 4 elementos si solo se en 5 letrasM "o saDremos lue1o. Cadenas de te-to terminadas en nulo
+on arrays de tipo de dato car. _ay dos características Bue distin1uen a estas cadenas de los demEs arrays. !rimero su inicialiaci8n se ace empleando comillas doDles y se1undo, el Pltimo tJrmino del array es un carEcter N"" 'simplemente un 5;55). $e aí su nomDre. #jemplos car Greet45 : _ello6 car ms1 : _ello6
// n array de 45 elementos // n array de Q elementos
#l array Greet tiene espacio para 45 elementos, de los cuales solo los primeros an sido llenados con las letras de _ello, el resto se rellena con ceros. #l array ms1 tiene Q elementos porBue ademEs de las letras de _ello se le a aKadido unNull '5;55) al
#structura de una cadena de te;to.
Los punteros
"os punteros suelen ser el tema Bue mEs cuesta entender en pro1ramaci8n. !ero si ya lle1aste aBuí, es el momento menos indicado para detenerte. "os punteros son un tipo de ariaDles muy especial. +on ariaDles Bue almacenan las direcciones =ísicas de otras ariaDles. +i tenemos la direcci8n de una ariaDle, tenemos acceso a esa ariaDle de manera indirecta y podemos acer con ellas todo lo Bue Bueramos. Declaración de punteros
"os punteros pueden apuntar a todo tipo de ariaDles, pero no a todas al mismo tiempo. "a declaraci8n de un puntero es un tanto peculiar. #n realidad, se parece a la declaraci8n de una ariaDle ordinaria solo Bue se pone un asterisco de por medio. #n este punto deDes recordar las declaraciones de todo tipo de ariaDles Bue emos isto, incluyendo las inSuenciadas por los cali
// ip es un puntero a ariaDle de tipo int // cp es un puntero a ariaDle de tipo car
unsi1ned car * ucp6 const lon1 * clp6 Soat * p4, *p6
// !untero a ariaDle de tipo unsi1ned car
// !untero a constante de tipo lon1 // $eclara dos punteros a ariaDle de tipo Soat
*puntando a variables
$ecimos Bue una ariaDle puntero apunta a una ariaDle ; si contiene la direcci8n de dica ariaDle. !ara ello se utilia el operador &, el cual e;trae la direcci8n de la ariaDle a la Bue acompaKa. n puntero siempre deDería apuntar a una ariaDle cuyo tipo coincida con el tipo del puntero. #n los si1uientes ejemplos emos c8mo apuntar a ariaDles de tipo DEsico, como int, car o Soat. Es adelante eremos c8mo apuntar a arrays. oid main 'oid) 2 int ei1t, %idt6
car a, D, c6 Soat ma;6
int * ip6 car * cp6 Soat * =p6
// ip es un puntero a ariaDle tipo int // cp es un puntero a ariaDle tipo car // !untero a ariaDle tipo Soat
ip : &ei1t6
// Con esto ip tendrE la direcci8n de ei1t
ip : &%idt6
// Aora ip apunta a %idt
cp : &a6
// cp apunta a a
cp : &c6
// Aora cp apunta a c
cp : &a6
// Aora cp apunta a a otra e
=p : &ma;6
// =p apunta a ma;
=p : &ei1t6
// #rror^ ei1t no es una ariaDle Soat
//... 7
*signaciones indirectas mediante punteros
na e Bue un puntero apunte a una ariaDle cualBuiera, se puede acceder a dica ariaDle utiliando el nomDre del puntero precedido por un asterisco, de esta =orma oid main 'oid) 2 int ei1t, %idt, n6 // VariaDles ordinarias int * p, * B6
// p y B son punteros a ariaDles de tipo int
p : &ei1t6
// p apunta a ei1t
*p : 456
// #sto es como ei1t : 45
p : &%idt6
// p apunta a %idt
*p : 56
// #sto es como %idt : 5
ei1t : *p6
// #sto es como ei1t : %idt
B : &ei1t6
// B apunta a ei1t
n : '*p X *B)/6
// #sto es como n : 'ei1t X %idt)/
//... 7
"a e;presi8n *p se deDería leer la ariaDle apuntada por p. #so tamDiJn ayuda muco a comprender a los punteros. LY para esto se inentaron los punterosM Yo me pre1untaDa lo mismo en mis inicios. #l tema de los punteros se puede complicar casi asta el in
%unteros y arrays
LC8mo se declara un puntero a un arrayM n puntero a un array es simplemente un puntero al tipo de dato del array. Cuando se asi1na un puntero a un array, en realidad el puntero toma la direcci8n de su primer elemento, a menos Bue se especi
// $eclara p como puntero a int
int n6
// Al1una ariaDle
int mat : 2 UO, O, Q 76
p : &mat6
// Array de ariaDles int
// p apunta a mat 'a su primer elemento)
n : *p6
// #sto da n : UO
pXX6
// Incrementar p para apuntar a si1uiente elemento
n : *p6
// #sto da n : O
pXX6
// Incrementar p para apuntar a si1uiente elemento
n : *p6
// #sto da n : Q
*p : 456
// Con esto mat aldrE 45
p336
// $ecrementar p para apuntar a elemento anterior
*p : 4556
// Con esto mat aldrE 455
p : mat6
// p apunta a mat. #s lo mismo Bue p : &mat
p : N""6
// $esasi1nar p. "o mismo Bue p : 5;5555
// ... 7 #n el =ondo los arrays y los punteros traDajan de la misma =orma, por lo menos cuando re=erencian a ariaDles almacenadas en la RA del microcontrolador. "a Pnica di=erencia es Bue los arrays no pueden direccionar a datos di=erentes de su contenido6 por eso tamDiJn se les llama punteros estEticos. #n la prEctica esto si1ni
puede apreciar en el si1uiente c8di1o. '!or si las moscas,str4 es el array y str, el puntero.) oid main'oid) 2 car str4 : 2 kAk, krk, krk, kak, kyk 76 car * str : 2 k!k, kok, kik, knk, ktk, kek, krk 76
car a6
a : str456
// #sto da a : kAk
a : str46
// #sto da a : kak
a : str56
// #sto da a : k!k
a : str6
// #sto da a : knk
str4 X: 6
// #rror^ +tr4 es estEtico
str X: 6
// Correcto. Aora str apunta a kik
str4XX6
// #rror otra e^ +tr4 es estEtico
strXX6
// Correcto. Aora str apunta a knk
a : *str6
// #sto da a : knk
// ... 7 %aso de punteros y arrays a funciones
LRecuerdas el paso de ariaDles por alor y por re=erenciaM !ues aBuí amos de nueo. 9ien, recordemos una ariaDle pasada por alor a una =unci8n, en realidad le entre1a una copia suya6 por lo Bue la ariaDle ori1inal no tiene por BuJ ser a=ectada por el c8di1o de la =unci8n. Aora Dien, pasar una ariaDle por re=erencia si1ni
// !asar alor de ariaDle apuntada por p a...
// ariaDle apuntada por p4. *p : tmp6
// VariaDle apuntada por p aldrE tmp.
7 oid main 'oid) 2 int i, j6 /* _acer al1unas asi1naciones */ i : 456
j : 46
/* "lamar a =unci8n intercan1e pasando las direcciones de i y j */ intercan1e' &i, &j )6 // #n este punto i ale 4 y j ale 45 // ... 7 Al llamar a intercan1e le entre1amos &i y &j, es decir, las direcciones de i y j. !or otro lado, la =unci8n intercan1e reciDirE dicos alores en p4 y p, respectiamente. $e ese modo, p4 y pestarEn apuntando a i y j, y podremos modi
// +umar elemento pi a tmp.
return ' tmp/sie )6
// Retornar alor promediado.
7
oid main 'oid) 2
int array4@ : 2 4, 4@, Q, UO 76
// n array de @ elementos
int array : 2 3O, @, QQ, @U, 3U, O 76 // n array de Q elementos Soat ar16
// na ariaDle tipo Soat, para decimales
ar1 : prom 'array4, O)6 // Aora ar1 deDería aler '4 X 4@ X Q X UO )/O : @@.U
ar1 : prom 'array, Q)6 // Aora ar1 deDería aler '3O X @ X QQ X @U 3 U X O )/Q : 4O.
%ile' 4 )6
// 9ucle in
7 Finalmente, eamos un pro1rama donde se utilian las Cadenas de te;to terminadas en nulo. #ste pro1rama tiene dos =unciones au;iliares mayus conierte la cadena reciDida en mayPsculas, y lon calcula la lon1itud del te;to almacenado en el array reciDido. AmDas =unciones reciDen el array pasado en un puntero p dado Bue son compatiDles. oid mayus' car * p ) 2 %ile' *p ) // ientras carEcter apuntado sea di=erente de 5;55 2 i=' ' *p \: kak ) && ' *p [: kk ) ) // +i carEcter apuntado es // minPscula *p : *p 3 6 pXX6 7 7
// _acerlo mayPscula // Incrementar p para apuntar si1. carEcter
int lon' car * p) 2 int i : 56
// $eclarar ariaDle i e iniciarla a 5.
%ile' *p )
// ientras carEcter apuntado sea di=erente de 5;55
2 iXX6
// Incrementar contador.
pXX6
// Incrementar p para apuntar si1. carEcter
7 return i6
// Retornar i
7 oid main 'oid) 2 int "6 car son145 : $ar] 9lue6 car son15 : +tarin1 !roDlem6 car son15 : #;3Girl=riend6
/* >Dtener lon1itudes de los arrays de te;to */ " : lon'son14)6
// $eDería dar " :
" : lon'son1)6
// $eDería dar " : 4
" : lon'son1)6
// $eDería dar " : 4
/* Conertir cadenas en mayPsculas */
mayus'son14 )6
// #s lo mismo Bue mayus'&son14)6
// Aora son14 deDería aler $AR 9"#
mayus'son1 )6
// #s lo mismo Bue mayus'&son1)6
// Aora son1 deDería aler +TARING !R>9"#
mayus'son1 )6
// #s lo mismo Bue mayus'&son1)6
// Aora son1 deDería aler #`3GIR"FRI#N$
%ile'4)6
// 9ucle in
7 #n el pro1rama se crean tres arrays de te;to de 5 elementos 'son14, son1 y son1), pero el te;to almacenado en ellos termina en un carEcter 5;55. +e1Pn la taDla de caracteres A+CII, las letras mayPsculas estEn uDicadas posiciones por deDajo de las minPsculas. !or eso Dasta con sumarle o restarle ese alor a un carEcter A+CII para pasarlo a mayPscula o minPscula. #n amDas =unciones el puntero p nae1a por los elementos del array apuntado asta Bue encuentra el
*rrays constantes
No es Bue me aya atrasado con el tema, es solo Bue los arrays constantes son uno de los temas cuyo tratamiento aría muco entre los distintos compiladores. Veamos en BuJ. n array constante es uno cuyos elementos solo podrEn ser leídos pero no escritos6 tan simple como eso. #n principio, para Bue un array sea constante a su clEsica declaraci8n con inicialiaci8n de un array se le deDe anteponer el cali
// Array constante
const car ocals : 2 kak, kek, kik, kok, kuk 76 // Array constante
const car te;t : #ste es un array constante de caracteres6 $e este modo, los arrays a, ocals y te;t serEn de solo lectura, y sus elementos podrEn ser leídos, mas no escritos. #l compilador mostrarE mensajes de error si en lo Bue resta del pro1rama encuentra intentos de camDio, por ejemplo, como a@ : 4556
// #sto 1enerarE un error en tiempo de compilaci8n
ocals5 : kak6 // #rror^ no se puede escriDir por mas Bue sea el mismo dato Aora Dien, Bue los datos no camDien durante la ejecuci8n del pro1rama no necesariamente si1ni
!or otro lado, los compiladores de AVR o=recen mJtodos alternos para declarar arrays, o ariaDles en 1eneral, Bue puedan residir en la memoria F"A+_. Con eso no solo se destina la preciada RA a otras ariaDles sino Bue se pueden usar 1randes arrays constantes Bue simplemente no podrían caDer en la RA. Como todo esto a al mar1en de lo Bue di1a el AN+I C, cada compilador a estaDlecido su propia sinta;is para acerlo. #mpecemos por e;aminar el estilo de AVR GCC. !or ejemplo, si Bueremos Bue los tres primeros arrays de esta pE1ina se almacenen en la F"A+_ deDemos declararlas e inicialiarlas de esta =orma !R>G# const int a : 2 5, Q, OU, 3O, 555 76
// Array constante
!R>G# const car ocals : 2 kak, kek, kik, kok, kuk 76 // Array constante !R>G# const car te;t : #ste es un array constante de caracteres6 >Dsera Bue =ue tan simple como aKadirles al inicio la palaDra reserada !R>G#. #l cali
p1m0read0Dyte. "ee de un array residente en F"A+_ un entero compuesto por un Dyte de dato. #n el len1uaje C los Pnicos datos de este tamaKo son del tipo car y sus deriadossi1ned car y unsi1ned car. p1m0read0%ord. "ee de un array residente en F"A+_ un entero compuesto por Dytes. #n el C serían arrays de tipo 'si1ned) int, unsi1ned int, 'si1ned) sort y unsi1ned sort. p1m0read0d%ord. "ee de un array residente en F"A+_ un entero compuesto por @ Dytes. #n el C serían arrays de tipo 'si1ned) lon1 y unsi1ned lon1. p1m0read0Soat. "ee de un array residente en F"A+_ un nPmero de punto Sotante compuesto por @ Dytes. #n el len1uaje C serían arrays de tipo Soat y douDle operando en modo de Dits. #stas macros reciDen como ar1umento la direcci8n de un elemento del array en F"A+_. Como la direcci8n de una ariaDle cualBuiera en el C se oDtiene al aplicarle el operador &, las macros citadas traDajan de esta =orma. !R>G# const int a : 2 5, Q, OU, 3O, 555 76
// Array constante
!R>G# const car ocals : 2 kak, kek, kik, kok, kuk 76 // Array constante !R>G# const car te;t : #ste es un array constante de caracteres6
int ar6 car c6
ar : p1m0read0%ord'&a4)6
// Con esto ar aldrE Q
c : p1m0read0Dyte'&ocals)6 // Con esto c aldrE kok c : p1m0read0Dyte'&te;t44)6
// Con esto c aldrE kak
#l manual de AVR GCC nos presenta una =orma Bue puede resultar mEs =Ecil de asimilar el acceso a los elementos de estos arrays dice Bue primero asumamos acceder al elemento como si perteneciera a un array ordinario 'residente en RA), por ejemplo ar : a46 lue1o le aplicamos el operador & ar : &a46
y
// Con esto ar aldrE Q
!or supuesto Bue en nuestro pro1rama deDeremos poner solo la Pltima e;presi8n. #s muy importante recordar esto puesto Bue las e;presiones preias son tamDiJn Elidas para el compilador y no 1enerarE errores. +olo nos daremos con la sorpresa de er nuestro pro1rama =uncionando desastrosamente. e pasa con =recuencia porBue en mis c8di1os ten1o la costumDre de uDicar primero los arrays en la RA para lue1o de oDtener Duenos resultados mudarla a la memoria F"A+_. +i eres nueo te recomiendo se1uir la misma prEctica. TraDajar con datos en F"A+_ desde el inicio reBuiere de muca e;periencia. _ay otras macros y tipos de datos Bue deDemos saDer usar, y si no estamos se1uros de lo Bue acemos, repito, el compilador no nos ayudarE. "os parEmetros Bue reciDen como ar1umento las macros p1m0read0Dyte, p1m0read0%ord,p1m0read0d%ord y p1m0read0Soat so n direcciones de 4Q Dits. #sto Buiere decir Bue mediante ellas podemos acceder a los arrays cuyos elementos cuDren un espacio de 4Q : QQ Dytes de la memoria F"A+_. #n la 1ran mayoría de los casos es muco mEs de lo Bue se necesita, considerando Bue solo ay dos me1aAVR Bue superan esa memoria, los ATme1a4O y los ATme1aQ. !ero si se presentara la descomunal situaci8n donde ten1amos Bue traDajar con arrays de mEs de Q@ 9, la liDrería p1mspace. nos proee de otras macros ad oc. Retomamos este aspecto al
"as ariaDles !R>G# tienen un espacio asi1nado en la memoria Bue no camDia durante la ejecuci8n del pro1rama. !arece una pero1rullada pero los lectores perspicaces saDen Bue ese comportamiento es propio de dos tipos de ariaDles del C las ariaDles 1loDales y las ariaDles static locales. Todos los otros tipos de ariaDles tienen posiciones dinEmicas. Es Bue una coincidencia, lo dico arriDa es una condici8n necesaria para todas las ariaDles almacenadas en la F"A+_ para AVR IAR C y AVR GCC. #s decir, en estos compiladores las ariaDles !R>G# deDen o ser 1loDales o static locales. Todos los ejemplos mostrados arriDa =uncionan Dien asumiendo Bue estEn declaradas a niel 1loDal. +i los colocamos dentro de una =unci8n aDrE proDlemas. !or ejemplo, el si1uiente e;tracto de =unci8n no darE errores en AVR GCC pero el pro1rama =uncionarE de=ectuosamente, a pesar de Bue los arrays estEn declarados e inicialiados con=orme a lo estudiado preiamente.
/***************************************************************************** * Toca las notas del rin1tone apuntado por pRin1tone. ****************************************************************************/ oid Tune'!G0! pRin1tone) 2
// C C- $ $- # F F-
!R>G# const 2Q,UU,@,44,5,@,U576
unsi1ned
int
NoteFreBs
:
!R>G# const unsi1ned car >ctaes : 2Q,U,76 !R>G# const unsi1ned int 9pms
: 25,O4,@5Q,U5,5,4Q,476
!R>G# const unsi1ned car $urations : 2@,O,4,76
/* ... */
7 +ucede Bue los arrays estEn declarados como si =ueran locales ordinarias. +i los uDiJramos declarado 1loDalmente estaría Dien. !ero como son locales es necesario Bue sean ademEs de tipo static. Como saDemos, estas ariaDles en C se =orman aKadiJndoles la palaDra reseradastatic a su declaraci8n aDitual. Con esto aclarado, el c8di1o anterior traDajarE per=ectamente si lo escriDimos de esta =orma. /***************************************************************************** * Toca las notas del rin1tone apuntado por pRin1tone. ****************************************************************************/ oid Tune'!G0! pRin1tone) 2
// C C- $ $- # F F-
static !R>G# 2Q,UU,@,44,5,@,U576
const
unsi1ned
int
NoteFreBs
:
static !R>G# const unsi1ned car >ctaes : 2Q,U,76 static !R>G# const 25,O4,@5Q,U5,5,4Q,476
unsi1ned
int
9pms
:
static !R>G# const unsi1ned car $urations : 2@,O,4,76
/* ... */
7 #se troo de c8di1o pertenece al pro1rama de la prEctica reproductor de rin1tones !ICA`#. +i deseas comproDar lo e;puesto puedes descar1arlo y recompilarlo aciendo las modi
usto en el ejemplo anterior aparece el tipo de dato !G0! en una de sus =unciones Bue es permitir el paso de ariaDles a =unciones. #se tema lo pro=undiaremos lue1o. #l tipo de dato !G0! es un puntero a una ariaDle residente en la memoria F"A+_. +u deG# car * pero el arcio p1mspace. de AVR IAR C lo deG# como 00Sas con lo cual las dos e;presiones de arriDa serían idJnticas asumiendo Bue en AVR GCC const !R>G# careBuiale a const car !R>G# y tamDiJn a !R>G# const car, siendo esta Pltima presentaci8n la =orma en Bue emos enido traDajando. $eDido a ello en mucas ocasiones podremos prescindir de !G0!, pero sur1irEn al1unos casos en Bue AVR IAR C muestre su discon=ormidad por ese reacomodo de tJrminos. !G0! no solo termina de arre1lar estos desajustes sino Bue =acilita notaDlemente la escritura del c8di1o ante la aparici8n de construcciones mEs complejas como las Bue eremos despuJs. +i !G0! de
necesario porBue a ctaes un array de enteros de O Dits, amDos residentes en la F"A+_. -include ar0compiler.
!R>G# const unsi1ned int Notes : 2Q, UU, @, 44, @@76 !R>G# const unsi1ned car >ctaes : 2Q, U, 76
int main'oid) 2 !G0! p6
// $eclarar el puntero p
unsi1ned car c6 unsi1ned int n6
p : '!G0!)>ctaes6 c : p1m0read0Dyte'p X 4)6
p : '!G0!)Notes6
// Apuntar al array >ctaes // >Dtener el elemento >ctaes4
// Apuntar al array Notes
n : p1m0read0%ord''!R>G# int*)p X )6 // >Dtener Notes
%ile'4)6 7 Como los arrays pueden ser entendidos como punteros tamDiJn, en principio se podrían acer las asi1naciones a p directamente como p : Notes, pero para eitar protestas del compilador se deDen usar conersiones de tipo, poniendo
al lado iBuierdo y entre parJntesis el tipo de la ariaDle Bue reciDe el alor, en este caso !G0! porBue p es de ese tipo. $e ese modo p podrE apuntar a arrays de cualBuier tipo. !or otro lado, para leer los elementos del array >ctaes usamos la macro p1m0read0DyteporBue es un array de Dytes y para Notes usamos p1m0read0%ord porBue es un array de enteros de Dytes. A p1m0read0Dyte se le enía el puntero p mEs el índice del elemento accedido. Recordemos Bue estas macros reciDen direcciones y como los punteros contienen direcciones, no es necesario sacar direcciones mediante el operador &. #ste caso =ue sencillo porBue el tipo de >ctae se acoplaDa =Ecilmente a !G0!. p1m0read0%ord tamDiJn espera reciDir una direcci8n pero no se le puede eniar a pdirectamente como en el caso preio. #s preciso acer una conersi8n de tipo para Bue el alor de p sea entendido como una direcci8n de ariaDles de Dytes. !or eso colocamos al lado iBuierdo de p la e;presi8n '!R>G# int *) Bue se adapta al tipo del array Notes. TamDiJn se pudo aDer puesto '!R>G# const unsi1ned int *) para una mejor claridad en la correspondencia. "o Bue cuenta es Bue impliBue un tipo de Dytes. #l eco de usar el tipo !G0! ace presuponer Bue solo se traDajarE con ariaDles de Dytes Bue son accedidas mediante la macro p1m0read0Dyte. $e eco es así en la 1ran mayoría de los casos y todo Bueda Dien. "a le1iDilidad se pierde en pro1ramas como el ejemplo preio donde el mismo puntero se usa tamDiJn para acceder a un array de enteros de Dytes. +i de todos modos amos a estar aciendo conersiones de tipos lo mEs recomendaDle sería usar un puntero neutro lo cual deja por sentado Bue traDajarE soDre ariaDles de distintos tipos. #se tipo de puntero e;iste y se llama !G0V>I$0!. #s aceptado así en los compiladores AVR IAR C y AVR GCC. #s un puntero a oid deG# * y en AVR IAR C como const oid 00Sas *. "o importante es Bue su empleo es similar al puntero !G0!, así Bue lo asimilaremos de inmediato. #l pro1rama anterior por ejemplo se puede reescriDir de la si1uiente =orma. '#l c8di1o Bued8 con mejor acaDado y con una linda simetría.) -include ar0compiler.
!R>G# const unsi1ned int Notes : 2Q, UU, @, 44, @@76 !R>G# const unsi1ned car >ctaes : 2Q, U, 76
int main'oid) 2 !G0V>I$0! p6
// $eclarar el puntero p
unsi1ned car c6 unsi1ned int n6
p : '!G0V>I$0!)>ctaes6
// Apuntar al array >ctaes
c : p1m0read0Dyte''!R>G# car*)p X 4)6 // >Dtener el elemento >ctaes4
p : '!G0V>I$0!)Notes6
// Apuntar al array Notes
n : p1m0read0%ord''!R>G# int*)p X )6 // >Dtener Notes
%ile'4)6 7 "os punteros !G0! y !G0V>I$0! tamDiJn pueden actuar soDre ariaDles de tipo complejo. #stamos aDlando por ejemplo de estructuras deI$0! para acceder a los descriptores de +9 Bue por su tamaKo residen en la F"A+_. #sa liDrería +9 se ale de un arcio llamado compiler. para 1uardar la compatiDilidad de c8di1os entre los compiladores AVR IAR C y AVR GCC para los Bue estE escrita. Contiene arias imprecisiones Bue, ima1ino, se deDen a los de=ectos Bue AVR GCC presentaDa anti1uamente, cuando se escriDi8 la liDrería. I1ual ale la pena reisarla.
Variables %.#/0E0 como argumentos de funciones
#n primer lu1ar recordemos Bue los ar1umentos de las =unciones deDen ser del mismo tipo Bue las ariaDles Bue se le enían. +i las ariaDles son residentes en la F"A+_, lo cual deja suponer Bue son arrays o estructuras complejas, el mJtodo a usar son los punteros, no solo por el tamaKo de esas ariaDles sino por la capacidad de adaptaci8n de los punteros Bue estudiamos en la secci8n anterior. Allí se descriDi8 la operaci8n de los punteros !G0! y !G0V>I$0! y se e;plic8 lo imprescindiDles Bue serían. No es recomendaDle Bue los ar1umentos de las =unciones sean punteros con tipos di=erentes de !G0! o !G0V>I$0!. +olo ellos 1arantian Bue nuestros pro1ramas =uncionarEn Dien en los dos compiladores AVR IAR C y AVR GCC. $ico eso, podemos pasar al ejemplo. #n el si1uiente pro1rama la =unci8n print imprime un mensaje por el puerto serie, similar a puts de la liDrería stdio. del compilador. "a =unci8n puts solo traDaja con mensajes en la RA a di=erencia de print Bue reciDe arrays residentes en la F"A+_. "os dos compiladores Bue usamos tamDiJn o=recen =unciones de F"A+_ y a eso pretendemos lle1ar a su uso. -include ar0compiler. -include usart.
!R>G# const car rt54 : r $ec] te alls6 !R>G# const car rt5 : r in1le Dells6 !R>G# const car rt5 : r (e %is you a merry cristmas6 !R>G# const car rt5@ : r +ilent ni1t6
/***************************************************************************** * #nía por el +ART el te;to pasado en p ****************************************************************************/ oid print'!G0! p) 2 car c6 %ile' 'c : p1m0read0Dyte'pXX)) ^: 5;55 )
putcar'c)6
7
/****************************************************************************** * ain =unction *****************************************************************************/ int main'oid) 2 usart0init')6
// Inicialiar +ART
print'rt54)6
// Imprimir mensaje de rt54
print'rt5)6
// ...
print'rt5)6
// ...
print'rt5@)6
// ...
%ile '4)6 7 Creo Bue el c8di1o estE Dastante claro. Como los arrays son de te;to 'de caracteres de 4 Dyte), se opt8 por el puntero !G0! y por la macro p1m0read0Dyte para la Bue no =ue necesaria una conersi8n de tipo. "a conersi8n de tipo para p es opcional, por ejemplo, tamDiJn se pudo escriDir print''!G0!)rt54). Y aora la pre1unta Bue nos trae aBuí L+e puede eniar a una =unci8n una ariaDle en Sas directamenteM #s decir, BuJ pasa si en e de declarar los arrays por separado, los escriDimos directamente en el ar1umento de la si1uiente =orma. print'r $ec] te alls)6 print'r in1le Dells)6
// Imprimir este mensaje // ...
print'r (e %is you a merry cristmas)6 // ...
print'r +ilent ni1t)6
// ...
#l compilador AVR GCC todaía acepta las sentencias y construye el pro1rama limpiamente, sin presentar errores, ni siBuiera adertencias. !ero el resultado es un pro1rama mostrando mamarracos en e de los illancicos esperados. #l compilador AVR IAR C, por su parte, simplemente no admite el c8di1o =uente. LZuJ pas8M Como ariaDles locales ordinarias Bue son, los compiladores tratan de implementar las cadenas pasadas en la memoria RA. AVR IAR C nota la incompatiDilidad de tipos y recaa el c8di1o de plano, en tanto Bue AVR GCC sí cumple el cometido pasando por alto la dier1encia de tipos porBue, recordemos, este compilador ace la di=erencia en el momento de acceder a las ariaDles usando sus macros como p1m0read0Dyte. #sa macro reciDe en el pro1rama una direcci8n RA 'tamDiJn de 4Q Dits) y la usa para leer de la memoria F"A+_ como si las cadenas de te;to estuieran allí. "ee cualBuier cosa menos las cadenas. Al1uien mEs aeado podría decir Bue eso se puede arre1lar con conersiones de tipos por ejemplo reescriDiendo las sentencias así print''!G0!)'r $ec] te alls))6 print''!G0!)'r in1le Dells))6
// Imprimir este mensaje // ...
print''!G0!)'r (e %is you a merry cristmas))6 // ... print''!G0!)'r +ilent ni1t))6
// ...
#l c8di1o uele a compilarse limpiamente. _asta AVR IAR C es en1aKado. !ero cuando emos el pro1rama en acci8n descuDrimos Bue solo nos emos en1aKado a nosotros mismos. #n este pro1rama los 1araDatos Bue se isualian en el terminal serial nos Buitaron la enda de los ojos rEpidamente, =elimente. #n otras circunstancias detectar el error uDiera costado mEs. "as cadenas si1uen siendo colocadas en la RA. Recordemos Bue para Bue las ariaDles residan en la F"A+_ deDen o ser 1loDales o static locales. "o primero es oDiamente un imposiDle6 y lo se1undo, Bue sean static, solo es posiDle en el compilador AVR GCC 1racias a una macro llamada!+TR Bue inicialia el array como static y toma su direcci8n automEticamente. "a si1uiente construcci8n entonces =uncionarE como se desea pero solo en este compilador. print'!+TR'r $ec] te alls))6 print'!+TR'r in1le Dells))6
// Imprimir este mensaje // ...
print'!+TR'r (e %is you a merry cristmas))6 // ... print'!+TR'r +ilent ni1t))6
// ...
+olo por curiosidad, la macro !+TR tiene la si1uiente deG# : 's)6 &00c567))
*rrays de cadenas %.#/0E0
#ste es un tema recurrente en pro1ramaci8n. !ara crear un array de cadenas en F"A+_ primero se declaran e inicialian las cadenas de la =orma ya conocida y lue1o se construye el array con los nomDres de las cadenas. #sta re1la es Pnica, inSe;iDle, limitante e i1ualmente Elida para los dos compiladores Bue usamos, AVR IAR Cy AVR GCC. Con un ejemplo lo amos a entender mejor. #l oDjeto del si1uiente pro1rama es idJntico al ejemplo de la secci8n anterior el pro1rama deDe mostrar los mismos mensajes almacenados en la F"A+_ solo Bue esta e se les desea acceder mediante un índice, por eso los mensajes estEn a1rupados en un array. -include ar0compiler. -include usart.
!R>G# const car rin1t54 : r $ec] te alls6 !R>G# const car rin1t5 : r in1le Dells6 !R>G# const car rin1t5 : r (e %is you a merry cristmas6 !R>G# const car rin1t5@ : r +ilent ni1t6
!G0! rin1tones : 2 rin1t54, rin1t5, rin1t5,
rin1t5@ 76
/****************************************************************************** * ain =unction *****************************************************************************/ int main'oid) 2 usart0init')6
// Inicialiar +ART
puts0!'rin1tones5)6
// Imprimir $ec] te alls
puts0!'rin1tones4)6
// Imprimir in1le Dells
puts0!'rin1tones)6
// Imprimir (e %is you a merry cristmas
puts0!'rin1tones)6
// Imprimir +ilent ni1t
%ile '4)6 7 "a =unci8n puts0! es proeída por los compiladores. #s similar a la =unci8n puts pero las cadenas Bue reciDe deDen uDicarse en la F"A+_. #n otras palaDras, puts0! es similar a la =unci8n printBue creamos en el ejemplo preio. +e nota Bue el array rin1tones a sido declarado para uDicarse en la RA, por eso accedemos a sus elementos de =orma re1ular y no empleando macros. +e io así porBue cada elemento es un puntero de Dytes y como solo son @ punteros, no ocupan muco espacio. +i uDiera mucos mEs elementos en el array rin1tones, la situaci8n camDiaría y sería mejor Bue tamDiJn residiera en la F"A+_. #so lo eremos al
es =actiDle en otros compiladores como CodeVisionAVR o +$CC. !or lo Bue dicen sus manuales, en los compiladores AVR IAR C y AVR GCC en el mejor de los casos esto solo uDicarE los elementos en la RA. #n AVR GCC ni siBuiera la macro !+TR, Bue sire para inicialiar en línea datos residentes en F"A+_, podrE ayudarnos esta e. Y, lo olidaDa, no intentes =orar el destino del array o de sus elementos utiliando conersiones de tipos. +olo eadirEs los errores y adertencias, pero los datos se1uirEn yendo a la RA y el pro1rama =uncionarE incorrectamente. '_a clic aBuí si Buieres er la ersi8n CodeVisionAVR de este pro1rama.) !G0! rin1tones : 2 r $ec] te alls, r in1le Dells, r (e %is you a merry cristmas, r +ilent ni1t 76 #sa presentaci8n coincide con la =orma en Bue emos estado traDajando antes primero!R>G#, lue1o const y al
!R>G# const car rin1t54 : r $ec] te alls6 !R>G# const car rin1t5 : r in1le Dells6 !R>G# const car rin1t5 : r (e %is you a merry cristmas6
!R>G# const car rin1t5@ : r +ilent ni1t6
!R>G# !G0! const rin1tones : 2 rin1t54, rin1t5, rin1t5, rin1t5@ 76
/****************************************************************************** * ain =unction *****************************************************************************/ int main'oid) 2 usart0init')6
// Inicialiar +ART
puts0!''!G0!)p1m0read0%ord'&rin1tones5))6 // Imprimir k$ec] te allsk puts0!''!G0!)p1m0read0%ord'&rin1tones4))6 // Imprimir kin1le Dellsk puts0!''!G0!)p1m0read0%ord'&rin1tones))6 // Imprimir k(e %is you a ... puts0!''!G0!)p1m0read0%ord'&rin1tones))6 // Imprimir k+ilent ni1tk
%ile '4)6 7 "a conersi8n de tipo con '!G0!) no es necesaria para AVR IAR C y para AVR GCC sire para eitar %arnin1s aunBue el pro1rama =unciona i1ual.
CamDiando de tema, en AVR GCC el pro1rama se compila en O Dytes de memoria F"A+_ y 5 Dytes de RA. #n CodeVisionAVR aDía tomado @5 Dytes de F"A+_ y solo O Dytes de RA. #s uno de los inusuales casos donde 1ana CodeVisionAVR, normalmente ni se le acerca. !ero AVR IAR C lo io en U Dytes de F"A+_ y U5 Dytes de RA. !arece Bue AVR IAR C uDiera puesto los datos en la RA, pero no. #s el estilo de este compilador tomar un poco mEs de RA para aorrar mEs F"A+_. #n los tres casos la compilaci8n se reali8 con la optimiaci8n a mE;imo niel. *rrays m's que grandes
"os parEmetros Bue reciDen como ar1umento las macros p1m0read0Dyte, p1m0read0%ord,p1m0read0d%ord y p1m0read0Soat so n direcciones de 4Q Dits. #sto Buiere decir Bue mediante ellas podemos acceder a los arrays cuyos elementos cuDren un espacio de 4Q : QQ Dytes de la memoria F"A+_. #n la 1ran mayoría de los casos es muco mEs de lo Bue se necesita, considerando Bue solo ay dos me1aAVR Bue superan esa memoria, los ATme1a4O y los ATme1aQ. !ero si se presentara la descomunal situaci8n donde ten1amos Bue traDajar con arrays de mEs de Q@ 9, la liDrería p1mspace. nos proee de otras macros ad oc. p1m0read0Dyte0=ar. Accede a arrays de enteros de 4 Dyte. p1m0read0%ord0=ar. Accede a arrays de enteros de Dytes. p1m0read0d%ord0=ar. Accede a arrays de enteros de @ Dytes. p1m0read0Soat0=ar. Accede a arrays de decimales @ Dytes. +in ser muy oDseradores notamos Bue sus nomDres proienen de las macros anteriores. Aora llean el suG#. !R>G# const int a : 2 5, Q, OU, 3O, 555 76
// Array constante
!R>G# const car ocals : 2 kak, kek, kik, kok, kuk 76 // Array constante !R>G# const car te;t : #ste es un array constante de caracteres6
int ar6