Índice de ejercicios:
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned int a = 50;
unsigned int * a_ptr;
a_ptr = &a;
printf("Imprimo el valor de 'a': %d\n\n", a);
printf("Imprimo la direccion de 'a': 0x%p\n", (void *) &a); // Casteo a (void*) para evitar warning al compilar
printf("El %%p imprime en hexadecimal\n\n");
printf("Imprimo el puntero 'a_ptr' : 0x%p\n\n", (void *)a_ptr); // Casteo a (void*) para evitar warning al compilar
printf("Imprimo el valor al que apunta 'a_ptr': %d\n", *a_ptr);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned int v = 50;
unsigned int * puntero;
puntero = &v;
printf("La variable 'v' vale %u\n", *puntero);
*puntero = 89;
printf("La variable 'v' vale %u\n", *puntero);
v = 97;
printf("La variable 'v' vale %u\n", *puntero);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
/*
Función que calcula el promedio del vector 'valores' y lo guarda en el lugar de memoria apuntado por 'prom_ptr'
*/
void calcularPromedio(float * prom_ptr, float * valores, unsigned int cantidad);
int main()
{
float vector_valores[] = { 2.5, 5, 7, 9 };
float promedio;
calcularPromedio(&promedio, vector_valores, 4);
printf("El promedio es %f\n", promedio);
return 0;
}
void calcularPromedio(float * prom_ptr, float * valores, unsigned int cantidad)
{
float suma = 0;
unsigned int i;
for(i = 0; i < cantidad; ++i)
{
suma += *(valores+i);
/*
Hacer *(valores+i) es lo mismo que valores[i]
*/
}
*prom_ptr = suma / (float) i;
}
#include "derivative.h" /* include peripheral declarations */
/*
* En este ejemplo haremos titilar el led azul de la placa de desarrollo (PTD1)
*/
// Deben agregar la declaración de la función Init_MCU()
// Por temas de tamaño en el ejemplo no la agregue, ver la pestaña de 'Recursos KL25Z' del site
void Init_MCU(void);
int main(void)
{
Init_MCU();
SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; // Habilito el clock del puerto D
PORTD_PCR1 = PORT_PCR_MUX(1); // Selecciono la alternativa 1 del multiplexor para el pin PTD1 para que funcione como GPIO
GPIOD_PDDR |= 1 << 1; // Configuro el PTD1 como una salida
for(;;) { // For infinito, nunca debemos salir
for(unsigned long i = 0; i < 1000000; i++){} // Delay casero
GPIOD_PTOR |= 1 << 1; // Registro de toggle, cambia el estado de la salida del pin PTD1
}
return 0;
}
#include "derivative.h" /* include peripheral declarations */
/*
* En este ejemplo leeremos una entrada digital que hará que el led rojo (PTB18) de la placa se apague o prenda
*/
// Deben agregar la declaración de la función Init_MCU()
// Por temas de tamaño en el ejemplo no la agregue, ver la pestaña de 'Recursos KL25Z' del site
void Init_MCU(void);
int main(void)
{
Init_MCU();
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; // Habilito el clock del puerto B
SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; // Habilito el clock del puerto C
PORTB_PCR18 = PORT_PCR_MUX(1); // Selecciono la alternativa 1 del multiplexor para el pin PTB18 para que funcione como GPIO
PORTC_PCR4 = PORT_PCR_MUX(1); // Selecciono la alternativa 1 del multiplexor para el pin PTC4 para que funcione como GPIO
GPIOB_PDDR |= 1 << 18; // Configuro el PTD1 como una salida
GPIOC_PDDR &= ~(1 << 4); // Configuro el PTC4 como una entrada
for(;;) { // For infinito, nunca debemos salir
if(((GPIOC_PDIR >> 4) & 0x1) == 1) // Si leo un 1 en la salida
{
GPIOB_PSOR |= 1 << 18; // Seteo en 1 la salida (se apaga el led, ya que el led rgb de la placa prende por 0
}
else
{
GPIOB_PCOR |= 1 << 18; // Seteo en 0 la salida (se prende el led, ya que el led rgb de la placa prende por 0
}
}
return 0;
}
#include "derivative.h"
/*
* En este ejemplo configuraremos la KBI (keyboard interrupt) de un pin para que cambie el estado del led verde (PTB19) de la placa.
* Cada vez que se detecte un flanco ascendente en el PTD5 se ejecutará el handler de interrupciones del puerto D
*/
void Init_PTD5_IRQ();
void Init_PTB19_Salida();
// Deben agregar la declaración de la función Init_MCU()
// Por temas de tamaño en el ejemplo no la agregue, ver la pestaña de 'Recursos KL25Z' del site
void Init_MCU(void);
int main(void)
{
Init_MCU(); // Desactivo WATCHDOG y configuro clock a 48MHz
Init_PTD5_IRQ(); // Inicializo la interrupcion en el PTD5
Init_PTB19_Salida(); // Inicializo el PTB19
for(;;) { // For infinito, nunca debemos salir
}
return 0;
}
void Init_PTB19_Salida()
{
// Habilito el clock del puerto B
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
// Configuro el pin PTB19 como GPIO
PORTB_PCR19 = PORT_PCR_MUX(1);
// Lo configuro como salida
GPIOB_PDDR |= 1 << 19;
}
void Init_PTD5_IRQ()
{
// Habilito el clock del puerto D
SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
PORTD_PCR5 = PORT_PCR_MUX(0b1);
PORTD_PCR5 |= PORT_PCR_IRQC(0b1001);
// Habilito las interrupciones del puerto D en el NVIC
NVIC_ICPR |= 1 << 31;
NVIC_ISER |= 1 << 31;
}
void PORTD_IRQHandler(void)
{
// En todos los periféricos (salvo el SysTick) debo avisarle al microcontrolador que ya pude atender la interrupción.
// En este caso para limpiarla debo poner un 1 en el bit ISF del registro PORT_PCR del pin que haya sido interrumpido
PORTD_PCR5 |= PORT_PCR_ISF_MASK;// Limpio la interrupcion del PTD5
GPIOB_PTOR |= 1 << 19; // Cambio de estado el led verde de la placa
}
#include "derivative.h" /* include peripheral declarations */
uint16_t tiempo = 0;
uint8_t bandera = 0;
uint16_t val, falling_edge_val;
void SysTick_Config(void);
void TPM1_CH0_Timer_Capture_Init(void);
void pulso (void);
int main(void) {
Init_MCU();
SysTick_Config();
TPM1_CH0_Timer_Capture_Init();
SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK;
PORTD_PCR1 = PORT_PCR_MUX(1);
PORTD_PCR0 = PORT_PCR_MUX(1);
PORTC_PCR13 = PORT_PCR_MUX(1);
GPIOD_PDDR |= 1 << 1; // PTD1 como salida
GPIOD_PDDR &= ~(1 << 0); //PTD0 como entrada
GPIOC_PDDR |= 1 << 13; // PTC13 como salida
TPM1_SC |= TPM_SC_CMOD(1); /* Inicio el timer */
tiempo = 1000;
for (;;) {
pulso();
}
return 0;
}
void pulso (void){
if (tiempo > 999)
{
GPIOC_PSOR |= 1 << 13;
}
else
{
GPIOC_PCOR |= 1 << 13;
}
if(tiempo==0)
{
tiempo=1000;
}
}
void SysTick_Config(void) {
SYST_RVR = 479;
SYST_CVR = 0;
SYST_CSR = 0x00000007;
}
void TPM1_CH0_Timer_Capture_Init(void) {
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; /* Enable clock to PORTA */
PORTA_PCR12 = PORT_PCR_MUX(3); /* Set Port A for TPM1CH0 input PTA12*/
SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK; /* Enable clock to TPM1 */
SIM_SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); /* Configuro la fuente del clock */
SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1);
TPM1_CONF = 0x00; /* Blow away the control registers to ensure that the counter is not running */
TPM1_SC = TPM_SC_PS(4); /* Seteo prescaler DIV 4 */
TPM1_CNT = 0;
TPM1_MOD = 0xFFFF; /* Set max modulo */
/* Input Capture mode rising edge interrupt first, ELSB:ELSA = 01, MSB:MSA = 00 */
TPM1_C0SC = (1* TPM_CnSC_CHIE_MASK) | (1*TPM_CnSC_ELSA_MASK) | (0 * TPM_CnSC_ELSB_MASK) | (0*TPM_CnSC_MSA_MASK) | (0*TPM_CnSC_MSB_MASK);
NVIC_ICPR |= 1 << ((INT_TPM1 - 16)) % 32;
NVIC_ISER |= 1 << ((INT_TPM1 - 16)) % 32;
}
void FTM1_IRQHandler(void)
{
TPM1_C0SC |= TPM_CnSC_CHF_MASK; //clear channel interrupt flag
TPM1_SC &= TPM_SC_CMOD_MASK;//paro el timer
if(bandera==0) //es flanco ascendente
{
/* Input Capture mode falling edge interrupt first, ELSB:ELSA = 10, MSB:MSA = 00 */
TPM1_C0SC = 0;
TPM1_C0SC = (1* TPM_CnSC_CHIE_MASK) | (0*TPM_CnSC_ELSA_MASK) | (1 * TPM_CnSC_ELSB_MASK) | (0*TPM_CnSC_MSA_MASK) | (0*TPM_CnSC_MSB_MASK);
TPM1_CNT = 0; //reseteo el contador
TPM1_SC |= TPM_SC_CMOD(1); //inicio el timer
falling_edge_val=0;
bandera=1;
}
else //es flanco descendente
{
falling_edge_val=TPM1_C0V; // Guardo el contador en la variable falling_edge_val
/* Input Capture mode rising edge interrupt first, ELSB:ELSA = 01, MSB:MSA = 00 */
TPM1_C0SC = 0;
TPM1_C0SC = (1* TPM_CnSC_CHIE_MASK) | (1*TPM_CnSC_ELSA_MASK) | (0 * TPM_CnSC_ELSB_MASK) | (0*TPM_CnSC_MSA_MASK) | (0*TPM_CnSC_MSB_MASK);
TPM1_SC |= TPM_SC_CMOD(1); //inicio el timer
val = ((falling_edge_val*60)/1000);
bandera = 0;
}
}
void SysTick_Handler(void) { //entra cada 1ms
tiempo--;
}
void Init_MCU(void) {
SIM_COPC=0; // Desactivo el Watchdog
//PLL
SIM_CLKDIV1 = (SIM_CLKDIV1_OUTDIV1(0x01) | SIM_CLKDIV1_OUTDIV4(0x01)); //Actualizo los prescalers del core
SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //Selecciona al PLL como fuente de reloj para varios periféricos
SIM_SOPT1 &= ~SIM_SOPT1_OSC32KSEL(0x03); //System oscillator drives 32 kHz clock for various peripherals
//Cambio a modo FBE
MCG_C2 = (MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK);
OSC0_CR = OSC_CR_ERCLKEN_MASK;
MCG_C1 = (MCG_C1_CLKS(2) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(3)));
MCG_C5 = MCG_C5_PRDIV0(1);
MCG_C6 = MCG_C6_VDIV0(0);
while ((MCG_S & MCG_S_IREFST_MASK) != 0) { //Espero hasta que el clock de referencia del FLL sea el clock externo
}
while ((MCG_S & 0x0CU) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
//Cambio a modo PBE
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0));
while ((MCG_S & 0x0C) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
while ((MCG_S & MCG_S_LOCK0_MASK) == 0x00) { //Espero hasta que se fije la frecuencia
}
//Cambio a modo PEE
MCG_C1 = (MCG_C1_CLKS(0) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
while ((MCG_S & 0x0C) != 0x0C) { //Espero hasta que se seleccione la salida del PLL
}
}
#include "derivative.h" /* include peripheral declarations */
// Prototipos de las funciones usadas
void init_adc();
void Init_MCU();
// Variables globales
unsigned int estado = 0;
unsigned int valor;
int main(void) {
Init_MCU(); // Inicializo el clock, desactivo el watchdog
init_adc(); // Inicializo el adc (ver funcion abajo)
// Inicializo el led rojo y verde (como salidas
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTD_MASK;
PORTB_PCR18 = PORT_PCR_MUX(1);
PORTB_PCR19 = PORT_PCR_MUX(1);
GPIOB_PDDR |= 1 << 18 | 1 << 19;
GPIOB_PDOR |= 1 << 18 | 1 << 19;
for (;;) {
switch (estado) {
case 0:
// Pregunto si la conversión esta lista
if ((ADC0_SC1A & ADC_SC1_COCO_MASK)!=0)
{
// Guardo el valor de la conversión en la variable valor
valor = ADC0_RA;
estado = 1;
}
break;
case 1:
// Dependiendo del valor leído del ADC prendo o apago los leds
if (valor<=85)
{
GPIOB_PSOR |= 1 << 18;
GPIOB_PCOR |= 1 << 19;
}
if (valor>85&&valor<=170)
{
GPIOB_PCOR |= 1 << 18;
GPIOB_PSOR |= 1 << 19;
}
if (valor>170)
{
GPIOB_PCOR |= 1 << 18;
GPIOB_PCOR |= 1 << 19;
}
estado=0;
break;
}
}
return 0;
}
void init_adc() {
//Activo el modulo del ADC
SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK;
//Registros del ADC
//ADC0_CFG1 = 0b11110000; //Low power, fBus / 8, long sample, ADC de 8 bits, bus clock (la fmax del ADC son 6 MHz aprox en este caso)
ADC0_CFG1 = ADC_CFG1_ADLPC_MASK | (0b11 << ADC_CFG1_ADIV_SHIFT)
| ADC_CFG1_ADLSMP_MASK | (0b00 << ADC_CFG1_MODE_SHIFT)
| (0 * ADC_CFG1_ADICLK_MASK);
//ADC0_CFG2 = 0b00000; //Canales A por usar el canal 0, asynchronous clock disabled, normal speed, longest sample
ADC0_CFG2 = (0 * ADC_CFG2_MUXSEL_MASK) | (0 * ADC_CFG2_ADACKEN_MASK)
| (0 * ADC_CFG2_ADHSC_MASK) | (0 * ADC_CFG2_ADLSTS_MASK);
//ADC0_SC2 = 0b000000000; //Compare function disabled,DMA is disabled
ADC0_SC2 = 0;
//ADC0_SC3 = 0b000001000; //conversion continua, promedio deshabilitado.
ADC0_SC3 = (1 * ADC_SC3_ADCO_MASK) | (0 * ADC_SC3_AVGE_MASK);
//Configuro el canal a medir
//ADC0_SC1A = 0b00000000; //sin interrupciones,no dierencial, canal 0 PTE20 (codigo binario de los ultimos 5 bits)
ADC0_SC1A = (0*ADC_SC1_AIEN_MASK) | (0*ADC_SC1_DIFF_MASK) | ADC_SC1_ADCH(0);
}
void Init_MCU(void) {
SIM_COPC = 0; // Desactivo el Watchdog
//PLL
SIM_CLKDIV1 = (SIM_CLKDIV1_OUTDIV1(0x01) | SIM_CLKDIV1_OUTDIV4(0x01)); //Actualizo los prescalers del core
SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //Selecciona al PLL como fuente de reloj para varios periféricos
SIM_SOPT1 &= ~SIM_SOPT1_OSC32KSEL(0x03); //System oscillator drives 32 kHz clock for various peripherals
//Cambio a modo FBE
MCG_C2 = (MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK);
OSC0_CR = OSC_CR_ERCLKEN_MASK;
MCG_C1 = (MCG_C1_CLKS(2) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
MCG_C4 &= (uint8_t) ~(uint8_t) ((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(3)));
MCG_C5 = MCG_C5_PRDIV0(1);
MCG_C6 = MCG_C6_VDIV0(0);
while ((MCG_S & MCG_S_IREFST_MASK) != 0) { //Espero hasta que el clock de referencia del FLL sea el clock externo
}
while ((MCG_S & 0x0CU) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
//Cambio a modo PBE
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0));
while ((MCG_S & 0x0C) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
while ((MCG_S & MCG_S_LOCK0_MASK) == 0x00) { //Espero hasta que se fije la frecuencia
}
//Cambio a modo PEE
MCG_C1 = (MCG_C1_CLKS(0) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
while ((MCG_S & 0x0C) != 0x0C) { //Espero hasta que se seleccione la salida del PLL
}
}
/*
* main implementation: use this 'C' sample to create your own application
*
*/
#include "derivative.h" /* include peripheral declarations */
// Canal B, promedio, conversión simple, interrupciones
// Prototipos de las funciones usadas
void init_adc();
void Init_MCU();
// Variables globales
unsigned int estado = 0;
unsigned int valor;
int main(void) {
Init_MCU(); // Inicializo el clock, desactivo el watchdog
init_adc(); // Inicializo el adc (ver funcion abajo)
// Inicializo el led rojo y verde (como salidas)
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTD_MASK;
PORTB_PCR18 = PORT_PCR_MUX(1);
PORTB_PCR19 = PORT_PCR_MUX(1);
GPIOB_PDDR |= 1 << 18 | 1 << 19;
GPIOB_PDOR |= 1 << 18 | 1 << 19;
for (;;) {
//Dependiendo el valor leído prendo o apago los leds
if (valor <= 85) {
GPIOB_PSOR |= 1 << 18;
GPIOB_PCOR |= 1 << 19;
}
if (valor > 85 && valor <= 170) {
GPIOB_PCOR |= 1 << 18;
GPIOB_PSOR |= 1 << 19;
}
if (valor > 170) {
GPIOB_PCOR |= 1 << 18;
GPIOB_PCOR |= 1 << 19;
}
}
return 0;
}
void ADC0_IRQHandler() {
// Leyendo el registro ADC0_RA se limpia automáticamente la interrupción
// Tambien leyendo ese registro se limpia automáticamente el COCO
valor = ADC0_RA ;
// Tengo que volver a disparar el ADC porque está en conversión simple
ADC0_SC1A = (1 * ADC_SC1_AIEN_MASK) | (0 * ADC_SC1_DIFF_MASK) | ADC_SC1_ADCH(4);
}
void init_adc() {
//Activo el modulo del ADC
SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK;
//Registros del ADC
//ADC0_CFG1 = 0b11110000; //Low power, fBus / 8, long sample, ADC de 8 bits, bus clock (la fmax del ADC son 6 MHz aprox en este caso)
ADC0_CFG1 = ADC_CFG1_ADLPC_MASK | (0b11 << ADC_CFG1_ADIV_SHIFT)
| ADC_CFG1_ADLSMP_MASK | (0b00 << ADC_CFG1_MODE_SHIFT)
| (0 * ADC_CFG1_ADICLK_MASK);
//ADC0_CFG2 = 0b00000; //Canales A por usar el canal 0, asynchronous clock disabled, normal speed, longest sample
// ACA SELECCIONO EL CANAL B!!!! (Mux en 1)
ADC0_CFG2 = (1 * ADC_CFG2_MUXSEL_MASK) | (0 * ADC_CFG2_ADACKEN_MASK)
| (0 * ADC_CFG2_ADHSC_MASK) | (0 * ADC_CFG2_ADLSTS_MASK);
//ADC0_SC2 = 0b000000000; //Compare function disabled,DMA is disabled
ADC0_SC2 = 0;
//ADC0_SC3 = 0b000001000; //conversion simple (ADCO en 0), promedio habilitado (AVGE en 1).
ADC0_SC3 = (0 * ADC_SC3_ADCO_MASK) | (1 * ADC_SC3_AVGE_MASK);
//Configuro el canal a medir
//ADC0_SC1A = 0b00000000; //con interrupciones (AIEN en 1) ,no dierencial, canal 4b PTE29 (codigo binario de los ultimos 5 bits)
ADC0_SC1A = (1 * ADC_SC1_AIEN_MASK) | (0 * ADC_SC1_DIFF_MASK) | ADC_SC1_ADCH(4);
// Habilito la interrupcion del ADC en el NVIC
NVIC_ICPR |= 1 << 15; // Limpia las interrupciones pendientes
NVIC_ISER |= 1 << 15; // Habilita la interrupcion 15 del NVIC (la del ADC)
}
void Init_MCU(void) {
SIM_COPC = 0; // Desactivo el Watchdog
//PLL
SIM_CLKDIV1 = (SIM_CLKDIV1_OUTDIV1(0x01) | SIM_CLKDIV1_OUTDIV4(0x01)); //Actualizo los prescalers del core
SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //Selecciona al PLL como fuente de reloj para varios periféricos
SIM_SOPT1 &= ~SIM_SOPT1_OSC32KSEL(0x03); //System oscillator drives 32 kHz clock for various peripherals
//Cambio a modo FBE
MCG_C2 = (MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK);
OSC0_CR = OSC_CR_ERCLKEN_MASK;
MCG_C1 = (MCG_C1_CLKS(2) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
MCG_C4 &= (uint8_t) ~(uint8_t) ((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(3)));
MCG_C5 = MCG_C5_PRDIV0(1);
MCG_C6 = MCG_C6_VDIV0(0);
while ((MCG_S & MCG_S_IREFST_MASK) != 0) { //Espero hasta que el clock de referencia del FLL sea el clock externo
}
while ((MCG_S & 0x0CU) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
//Cambio a modo PBE
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV0(0));
while ((MCG_S & 0x0C) != 0x08) { //Espero hasta que el clock externo sea la referencia del módulo MCG
}
while ((MCG_S & MCG_S_LOCK0_MASK) == 0x00) { //Espero hasta que se fije la frecuencia
}
//Cambio a modo PEE
MCG_C1 = (MCG_C1_CLKS(0) | MCG_C1_FRDIV(3) | MCG_C1_IRCLKEN_MASK);
while ((MCG_S & 0x0C) != 0x0C) { //Espero hasta que se seleccione la salida del PLL
}
}