Mostrando entradas con la etiqueta Microcontroladores. Mostrar todas las entradas
Mostrando entradas con la etiqueta Microcontroladores. Mostrar todas las entradas

USB Micros II

USB GoogleDocs
USB Mediafire

Complementario Final

GoogleDocs
RTCC
UART
SPI
I2C
Mediafire
RTCC
UART
SPI
I2C

Micros II

Material complementario
Descargar
Descargar Cuadratura
Descargar PWM

Notas Micros I

Subidas al sistema revisen

Asignaciones Laboratorio 3

Laboratorio 3 Grupos T1




Grupo 1
Rondon P
Lugo M
Elias
Castro E.

Grupo 2
García H.
Rosales C
Diaz Y.
Molina A.

Grupo 3
Martines L
Rivas T
Diaz A
Caraballo J

Grupo 4
Sanchez L
Hernandez F.
Brito G.
Manuel.

Grupo 5
Rojas N
Tarache A
Sequea A.
Vivas L.
Nain F.

Grupo 6
Rodriguez L.
Olveros L.

Laboratorio 3 Grupos M2
Grupo 1
Baldassare
Castillo
Herrera
Velásquez  R

Grupo 2
Suarez N.
Coronado
Aguilar
Padilla

Grupo 3
 Diaz I
Aponte F
Farrera A

Grupo 4
Campos C
Marcano H
Gonzalez O

Grupo 5
Vacante  Contactar al profesor

Grupo 6
Rendon R
Velasquez D
Rondon O
Lino R

Fechas

M2
05-09-14 Laboratorio 2
11-09-14 Examen 3 
19-09-14 Laboratorio 3

T1
05-09-14 Laboratorio 2
12-09-14 Examen 3 
19-09-14 Laboratorio 3


Laboratorio 3

Las reglas del Laboratorio se darán en clases y el sorteo se hará en clases también, será este lunes 1 /8 /14 en cada salón correspondiente
                      indica el uso de un modo de comunicación modulo inalámbrico de 433Mhz,
                      indica el uso de un modo de comunicación modulo inalámbrico de 2.4Ghz,
                      indica el uso de un modo cableado 

Las propuestas de laboratorio está en los links siguientes
Mediafire
GoogleDocs 
cada grupo deberá comunicarse con el que posea el mismo modo de comunicación (sensor)

Laboratorio 2

Escoja uno de los 6 laboratorios (no deberán haber laboratorios repetidos, solo un grupo en la tarde lo podrá hacer, este deberá ser el laboratorio 6)
Fecha de entrega 5 de septiembre
GoogleDocs
Mediafire

T1
Laboratorio 1 Grupo
24 559 768 / 20 374 432 / 20 805 689
Laboratorio 2 Grupo
20806000 / 23502733 / 22586361 / 20804946
Laboratorio 3 Grupo
06-18886610 / 11-21250174 / 09-20556571 / 09-20299976
Laboratorio 4 Grupo
16.395.187 / 17.523.155 / 16.025.982 / 19297141
Laboratorio 5 Grupo
23503975 / 18 886 905 / 19301771/ 18515354

M2

Laboratorio 1: Grupo 
19303263, 19157504, 20934394, 21794231
Laboratorio 3 Grupo
15632304 / 20126180
Laboratorio 4 Grupo
22921572 / 19094788 / 18515850 / 18337438
Laboratorio 6 grupo
20506402 /  24847543 / 20286560 / 23500652
20.654.421 / 20.298.085
Laboratorio 5 Grupo
20035852 / 24227137 / 20994954 / 21176449 / 21008004

Utilizar el visualizador LCD gráfico

Utilizar el visualizador LCD gráfico

Un LCD gráfico (GLCD) proporciona un método avanzado para visualizar mensajes. Mientras que un LCD de caracteres puede visualizar sólo caracteres alfanuméricos, el LCD gráfico puede visualizar los mensajes en forma de dibujos y mapas de bits. El LCD gráfico utilizado con más frecuencia tiene una resolución de pantalla de 128x64 píxeles. El contraste de un GLCD se puede ajustar por medio del potenciómetro P1.
EJEMPLO 14
En este ejemplo el GLCD visualiza una secuencia de imágenes, de las que un mapa de bits representa un camión almacenado en otro archivo denominado truck_bmp.c. Para habilitar que este programa funcione apropiadamente, usted debe añadir este archivo como archivo fuente a su proyecto.
Las directivas del preprocesador incluidas en este ejemplo le permiten elegir si quiere visualizar toda la secuencia de imágenes o sólo una secuencia corta. Por defecto se visualizará toda la secuencia de imágenes. Sin embargo, al añadir un comentario delante de la directiva#define COMPLETE_EXAMPLE se deshabilita visualizar algunas imágenes de la secuencia. Si se comenta (o si se borra) esta directiva, las sentencias entre las directivas #ifdef COMPLETE_EXAMPLE y #endif no serán compiladas, así que no se ejecutarán.
/*Cabecera******************************************************/

//Declaraciones-----------------------------------------------------------------
const code char truck_bmp[1024]; // Declarar la constante definida en truck_bmp.c
// para utilizarla en este archivo
//--------------------------------------------------------final-de-declaraciones

// Conexiones del módulo Glcd
char GLCD_DataPort at PORTD;
sbit GLCD_CS1 at RB0_bit;
sbit GLCD_CS2 at RB1_bit;
sbit GLCD_RS at RB2_bit;
sbit GLCD_RW at RB3_bit;
sbit GLCD_EN at RB4_bit;
sbit GLCD_RST at RB5_bit;
sbit GLCD_CS1_Direction at TRISB0_bit;
sbit GLCD_CS2_Direction at TRISB1_bit;
sbit GLCD_RS_Direction at TRISB2_bit;
sbit GLCD_RW_Direction at TRISB3_bit;
sbit GLCD_EN_Direction at TRISB4_bit;
sbit GLCD_RST_Direction at TRISB5_bit;
// Final de conexiones del módulo Glcd

void delay2S(){    // Función de tiempo de retardo de 2 segundos
  Delay_ms(2000);
}

void main() {
  unsigned short ii;
  char *someText;
  
  /* Esta directiva define un macro denominado COMPLETE_EXAMPLE. Más tarde en el
  programa, la directiva ifdef prueba si este macro está definido. Si se borra esta
  línea o si se transforma en un comentario, las secciones del código entre las
  directivas ifdef y endif no serán compiladas. */
  
  #define COMPLETE_EXAMPLE // Poner esta línea como un comentario si quiere  
  // visualizar la versión corta de la secuencia
  
  ANSEL = 0;       // Configurar los pines AN como digitales
  ANSELH = 0;
  C1ON_bit = 0;    // Deshabilitar comparadores
  C2ON_bit = 0;
  Glcd_Init();     // Inicializar el GLCD
  Glcd_Fill(0x00); // Borrar el GLCD
  
  while(1) {                    // bucle infinito, la secuencia se repite
  
  /* Dibujar la primera imagen */
  #ifdef COMPLETE_EXAMPLE
  Glcd_Image(truck_bmp);        // Dibujar la imagen
  delay2S(); delay2S();
  #endif  
  Glcd_Fill(0x00);              // Borrar el GLCD
  
  /* Dibujar la segunda imagen */
  Glcd_Box(62,40,124,56,1);     // Dibujar la caja
  Glcd_Rectangle(5,5,84,35,1);  // Dibujar el rectángulo
  Glcd_Line(0, 0, 127, 63, 1);  // Dibujar la línea
  
  delay2S();
  
  for(ii = 5; ii < 60; ii+=5 ){ // Dibujar líneas horizontales y verticales
    Delay_ms(250);
    Glcd_V_Line(2, 54, ii, 1);
    Glcd_H_Line(2, 120, ii, 1);
  }
  
  delay2S();
  Glcd_Fill(0x00); // Borrar el GLCD
  
  /* Dibujar la tercera imagen */
  
  #ifdef COMPLETE_EXAMPLE
    Glcd_Set_Font(Character8x7, 8, 7, 32);   // Seleccionar la fuente, ver
    // __Lib_GLCDFonts.c en la carpeta Uses
  #endif
  
  Glcd_Write_Text("mikroE", 1, 7, 2);        // Escribir la cadena
  for (ii = 1; ii <= 10; ii++)               // Dibujar los círculos
    Glcd_Circle(63,32, 3*ii, 1); 
  delay2S();
  
  Glcd_Box(12,20, 70,57, 2);                 // Dibujar la caja
  delay2S();
  
  /* Dibujar la cuarta imagen */
  #ifdef COMPLETE_EXAMPLE
  Glcd_Fill(0xFF); // Llenar el GLCD
  Glcd_Set_Font(Character8x7, 8, 7, 32);     // Cambiar de la fuente
  someText = "8x7 Font";
  Glcd_Write_Text(someText, 5, 0, 2);        // Escribir la cadena
  delay2S();
  Glcd_Set_Font(System3x5, 3, 5, 32);        // Cambiar de la fuente
  someText = "3X5 CAPITALS ONLY";
  Glcd_Write_Text(someText, 60, 2, 2);       // Escribir la cadena
  delay2S();
  Glcd_Set_Font(font5x7, 5, 7, 32);          // Cambiar de la fuente
  someText = "5x7 Font";
  Glcd_Write_Text(someText, 5, 4, 2);        // Escribir la cadena
  delay2S();
  Glcd_Set_Font(FontSystem5x7_v2, 5, 7, 32); // Cambiar de la fuente
  someText = "5x7 Font (v2)";
  Glcd_Write_Text(someText, 5, 6, 2);        // Escribir la cadena
  delay2S();
  #endif
  }
}
truck_bmp.c:
/*Cabecera*****************************************************/

unsigned char const truck_bmp[1024] = {
   0,  0,  0,  0,  0,248,  8,  8,  8,  8,  8,  8, 12, 12, 12, 12,
  12, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  9,  9,
   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,137,137,137,137,137,137,
 137,137,137,137,137,137,137,  9,  9,  9,  9,  9,  9,  9,  9,  9,
   9,  9, 13,253, 13,195,  6,252,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,255,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 240,240,240,240,240,224,224,240,240,240,240,240,224,192,192,224,
 240,240,240,240,240,224,192,  0,  0,  0,255,255,255,255,255,195,
 195,195,195,195,195,195,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,255,240, 79,224,255, 96, 96, 96, 32, 32, 32, 32, 32,
  32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64,128,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,255,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 255,255,255,255,255,  0,  0,  0,  0,255,255,255,255,255,  0,  0,
   0,  0,255,255,255,255,255,  0,  0,  0,255,255,255,255,255,129,
 129,129,129,129,129,129,128,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,255,  1,248,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
   8,  8,  8,  8, 16,224, 24, 36,196, 70,130,130,133,217,102,112,
 160,192, 96, 96, 32, 32,160,160,224,224,192, 64, 64,128,128,192,
  64,128,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0, 63, 96, 96, 96,224, 96, 96, 96, 96, 96, 96,
  99, 99, 99, 99, 99, 96, 96, 96, 96, 99, 99, 99, 99, 99, 96, 96,
  96, 96, 99, 99, 99, 99, 99, 96, 96, 96, 99, 99, 99, 99, 99, 99,
  99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 64, 64,
  64,224,224,255,246,  1, 14,  6,  6,  2,  2,  2,  2,  2,  2,  2,
   2,  2,  2,  2,130, 67,114, 62, 35, 16, 16,  0,  7,  3,  3,  2,
   4,  4,  4,  4,  4,  4,  4, 28, 16, 16, 16, 17, 17,  9,  9, 41,
 112, 32, 67,  5,240,126,174,128, 56,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
   1,  1,127,127,127,127,255,255,247,251,123,191, 95, 93,125,189,
 189, 63, 93, 89,177,115,243,229,207, 27, 63,119,255,207,191,255,
 255,255,255,255,255,255,255,127,127,127,127,127,127,127,127,255,
 255,255,127,127,125,120,120,120,120,120,248,120,120,120,120,120,
 120,248,248,232,143,  0,  0,  0,  0,  0,  0,  0,  0,128,240,248,
 120,188,220, 92,252, 28, 28, 60, 92, 92, 60,120,248,248, 96,192,
 143,168,216,136, 49, 68, 72, 50,160, 96,  0,  0,  0,  0,  0,  0,
   0,  0,  0,128,192,248,248,248,248,252,254,254,254,254,254,254,
 254,254,254,254,254,255,255,255,255,255,246,239,208,246,174,173,
 169,128,209,208,224,247,249,255,255,252,220,240,127,255,223,255,
 255,255,255,255,255,254,254,255,255,255,255,255,255,255,254,255,
 255,255,255,255,255,255,254,254,254,254,254,254,254,254,254,254,
 254,254,254,254,255,255,255,255,255,255,254,255,190,255,255,253,
 240,239,221,223,254,168,136,170,196,208,228,230,248,127,126,156,
 223,226,242,242,242,242,242,177, 32,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  1,  1,  1,  1,  3,  3,  3,  7,  7,  7,  7,  7, 15,
  15, 15,  7, 15, 15, 15,  7,  7, 15, 14, 15, 13, 15, 47, 43, 43,
  43, 43, 43, 47,111,239,255,253,253,255,254,255,255,255,255,255,
 191,191,239,239,239,191,255,191,255,255,255,255,255,255,255,255,
 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 255,255,255,255,127,127,127,127,255,255,191,191,191,191,255,254,
 255,253,255,255,255,251,255,255,255,127,125, 63, 31, 31, 31, 31,
  31, 31, 63, 15, 15,  7,  7,  3,  3,  3,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,
   1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
   1,  1,  1,  1,  3,  3,  3, 11, 11, 11, 11,  7,  3, 14,  6,  6,
   6,  2, 18, 19, 19,  3, 23, 21, 21, 17,  1, 19, 19,  3,  6,  6,
  14, 15, 15,  7, 15, 15, 15, 11,  2,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};
Para que este ejemplo funcione apropiadamente, es necesario marcar la librería GLCD en la ventana Library Manager antes de compilar el programa. Asimismo, es necesario incluir el documento truck_bmp.c en el proyecto.

Generación de sonido, librería de sonido...

Generación de sonido, librería de sonido...

Las señales de audio se utilizan con frecuencia cuando se necesita llamar la atención de usuario, confirmar que alguno de los botones se ha pulsado, avisar que se ha llegado hasta los valores mínimos o máximos etc. Pueden ser una simple señal de pitido así como melodías de una duración más larga o más corta. En este ejemplo se muestra la generación de sonido por medio de funciones que pertenecen a la librería Sound.
EJEMPLO 13
Además de estas funciones, la función Button que pertenece a la misma librería se utiliza para probar los botones de presión.
/*Cabecera******************************************************/

void Tone1() {
  Sound_Play(659, 250); // Frecuencia = 659Hz, duración = 250ms
}

void Tone2() {
  Sound_Play(698, 250); // Frecuencia = 698Hz, duración = 250ms
}

void Tone3() {
  Sound_Play(784, 250); // Frecuencia = 784Hz, duración = 250ms
}

void Melody1() { // Componer una melodía divertida 1
  Tone1(); Tone2(); Tone3(); Tone3();
  Tone1(); Tone2(); Tone3(); Tone3();
  Tone1(); Tone2(); Tone3();
  Tone1(); Tone2(); Tone3(); Tone3();
  Tone1(); Tone2(); Tone3();
  Tone3(); Tone3(); Tone2(); Tone2(); Tone1();
}

void ToneA() { // Tono A
  Sound_Play( 880, 50);
}

void ToneC() { // Tono C
  Sound_Play(1046, 50);
}

void ToneE() { // Tono E
  Sound_Play(1318, 50);
}

void Melody2() { // Componer una melodía divertida 2
  unsigned short i;
  
  for (i = 9; i > 0; i--) {
    ToneA(); ToneC(); ToneE();
  }
}

void main() {
  ANSEL = 0;                   // Todos los pines de E/S son digitales
  ANSELH = 0;
  TRISB = 0xF0;                // Pines RB7-RB4 se configuran como entradas
  
  // RB3 se configura como salida
  Sound_Init(&PORTB, 3);
  Sound_Play(1000, 500);
  
  while (1) {
    if (Button(&PORTB,7,1,1)) // RB7 genera Tono1
    Tone1();
    while (PORTB & 0x80) ;    // Esperar que se suelte el botón
    if (Button(&PORTB,6,1,1)) // RB6 genera Tono2
    Tone2();
    while (PORTB & 0x40) ;    // Esperar que se suelte el botón
    if (Button(&PORTB,5,1,1)) // RB5 genera melodía 2
    Melody2();
    while (PORTB & 0x20) ;    // Esperar que se suelte el botón
    if (Button(&PORTB,4,1,1)) // RB4 genera melodía 1
    Melody1();
    while (PORTB & 0x10) ;    // Esperar que se suelte el botón
  }
}
Para que este ejemplo funcione apropiadamente, es necesario marcar las siguientes librerías en la ventana Library Manager antes de compilar el programa:
  • Button
  • Sound

Medición de temperatura por medio del sensor DS1820. Uso del protocolo ‘1-wire’...

Medición de temperatura por medio del sensor DS1820. Uso del protocolo ‘1-wire’...

La medición de temperatura es una de las tareas más frecuentes realizadas por el microcontrolador. En este ejemplo, se utiliza un sensor DS1820 para medir. Es capaz de medir en el rango de 55 °C a 125 °C con exactitud de 0.5 °C. Para transmitir los datos al microcontrolador se utiliza un tipo especial de la comunicación serial denominado 1-wire. Debido al hecho de que estos sensores son simples de utilizar y de grandes capacidades, los comandos utilizados para hacerlos funcionar y controlarlos tienen la forma de funciones almacenadas en la librería One_Wire. En total son las siguientes tres funciones:
  • Ow_Reset se utiliza para reiniciar el sensor;
  • Ow_Read se utiliza para recibir los datos del sensor; y
  • Ow_Write se utiliza para enviar los comandos al sensor
EJEMPLO 12
Este ejemplo muestra la ventaja de utilizar librerías con las funciones listas para ser utilizadas. Concretamente, no tiene que examinar la documentación proporcionada por el fabricante para utilizar el sensor. Basta con copiar alguna de estas funciones en el programa. Si le interesa saber cómo se declaran, basta con pulsar sobre alguna de ellas y seleccione la opción Help.
/*Cabecera******************************************************/

// Conexiones del módulo LCD
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// Final de conexiones del módulo LCD

const unsigned short TEMP_RESOLUTION = 9;
char *text = "000.0000";
unsigned temp;

void Display_Temperature(unsigned int temp2write) {
  const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
  char temp_whole;  
  unsigned int temp_fraction;
  
  // comprobar si la temperatura es negativa
  if (temp2write & 0x8000) {
  text[0] = '-';
  temp2write = ~temp2write + 1;
  }
  
  // extraer temp_whole
  temp_whole = temp2write >> RES_SHIFT ;
  
  // convertir temp_whole en caracteres
  if (temp_whole/100)
     text[0] = temp_whole/100 + 48;
  else
    text[0] = '0';
 
  text[1] = (temp_whole/10)%10 + 48;     // Extraer dígito de decenas
  text[2] = temp_whole%10 + 48;          // Extraer dígito de unidades
  
  // extraer temp_fraction y convertirlo en unsigned int
  temp_fraction = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;
  
  // convertir temp_fraction en caracteres
  text[4] = temp_fraction/1000 + 48;     // Extraer dígito de miles
  text[5] = (temp_fraction/100)%10 + 48; // Extraer dígito de centenas
  text[6] = (temp_fraction/10)%10 + 48;  // Extraer dígito de decenas
  text[7] = temp_fraction%10 + 48;       // Extraer dígito de unidades
  
  // Visualizar temperatura en el LCD
  Lcd_Out(2, 5, text);
}

void main() {
  ANSEL = 0;                // Configurar los pines AN como digitales
  ANSELH = 0;
  C1ON_bit = 0;             // Deshabilitar los comparadores
  C2ON_bit = 0;
  
  Lcd_Init();               // Inicializar el LCD
  Lcd_Cmd(_LCD_CLEAR);      // Borrar el LCD
  Lcd_Cmd(_LCD_CURSOR_OFF); // Apagar el cursor
  Lcd_Out(1, 1, " Temperatura: ");
  
  // Visualizar el carácter de grado, 'C' para centígrados
  Lcd_Chr(2,13,223); // distintos visualizadores LCD tienen diferentes códigos
  
  // de caracteres para el grado
  // si ve la letra griega Alfa, intente introducir 178 en vez de 223
  Lcd_Chr(2,14,'C');
  
  //--- bucle principal
  do {
    //--- realizar lectura de temperatura
    Ow_Reset(&PORTE, 2);       // Señal de reinicio de Onewire
    Ow_Write(&PORTE, 2, 0xCC); // Ejecutar el comando SKIP_ROM
    Ow_Write(&PORTE, 2, 0x44); // Ejecutar el comando CONVERT_T
    Delay_us(120);
    Ow_Reset(&PORTE, 2);
    Ow_Write(&PORTE, 2, 0xCC); // Ejecutar el comando SKIP_ROM
    Ow_Write(&PORTE, 2, 0xBE); // Ejecutar el comando READ_SCRATCHPAD
    temp = Ow_Read(&PORTE, 2);
    temp = (Ow_Read(&PORTE, 2) << 8) + temp;
 
    //--- Formatear y visualizar el resultado en el LCD
    Display_Temperature(temp);
    Delay_ms(500);
  } while (1);
}
Para que este ejemplo funcione apropiadamente, es necesario marcar las siguientes librerías en la ventana Library Manager antes de compilar el programa:
  • One_Wire
  • LCD

Comunicación serial RS-232

Comunicación serial RS-232

Este ejemplo muestra cómo utilizar el módulo EUSART del microcontrolador. La conexión a una PC se habilita por medio del estándar de comunicación RS-232. El programa funciona de la siguiente manera. Cada byte recibido por medio de la comunicación serial se visualiza al utilizar los LEDs conectados al puerto PORTB y después se devuelve automáticamente al transmisor. Si ocurre un error en recepción, se lo indicará al encender el diodo LED. La manera más fácil es comprobar el funcionamiento del dispositivo en la práctica al utilizar un programa estándar de Windows denominado Hyper Terminal.
EJEMPLO 11
/*Cabecera******************************************************/

unsigned short i;

void main() {
  UART1_Init(19200); // Inicializar el módulo USART
  // (8 bits, tasa de baudios 19200, no hay bit
  // de paridad...)
  
  while (1) {
    if (UART1_Data_Ready()) { // si se ha recibido un dato
      i = UART1_Read(); // leerlo
      UART1_Write(i); // enviarlo atrás
    }
  }
}
Para que este ejemplo funcione apropiadamente, es necesario marcar la librería UART en la ventana Library Manager antes de compilar el programa:
  • UART

Utilizar el visualizador LCD

Utilizar el visualizador LCD

Este ejemplo muestra cómo utilizar un visualizador LCD alfanumérico. Las librerías de funciones simplifican este programa, lo que significa que al final el esfuerzo para crear el software vale la pena.
Un mensaje escrito en dos líneas aparece en el visualizador:
mikroElektronika
LCD example
Dos segundos más tarde, el mensaje en la segunda línea cambia, y se visualiza el voltaje presente en la entrada del convertidor A/D (el pin RA2). Por ejemplo:
mikroElektronika
voltage:3.141V
En un dispositivo real se puede visualizar temperatura actual o algún otro valor medido en vez de voltaje.
EJEMPLO 10
Para que este ejemplo funcione apropiadamente, es necesario marcar las siguientes librerías en la ventana Library Manager antes de compilar el programa:
  • ADC
  • LCD
/*Cabecera*****************************************************/

// Conexiones del módulo LCD
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// Final de las conexiones del módulo LCD

// Declarar variables
unsigned char ch; 
unsigned int adc_rd; 
char *text; 
long tlong; 

void main() {
  INTCON = 0;                    // Todas las interrupciones deshabilitadas
  ANSEL = 0x04;                  // Pin RA2 se configura como una entrada analógica
  TRISA = 0x04;
  ANSELH = 0;                    // Los demás pines se configuran como digitales
  
  Lcd_Init();                    // Inicialización del visualizador LCD
  Lcd_Cmd(_LCD_CURSOR_OFF);      // Comando LCD (apagar el cursor)
  Lcd_Cmd(_LCD_CLEAR);           // Comando LCD (borrar el LCD)
  
  text = "mikroElektronika";     // Definir el primer mensaje
  Lcd_Out(1,1,text);             // Escribir el primer mensaje en la primera línea
  
  text = "LCD example";          // Definir el segundo mensaje
  Lcd_Out(2,1,text);             // Definir el primer mensaje
  
  ADCON1 = 0x82;                 // Voltaje de referencia para la conversión A/D es VCC
  TRISA = 0xFF;                  // Todos los pines del puerto PORTA se configuran como entradas
  Delay_ms(2000);
  
  text = "voltage:";             // Definir el tercer mensaje
  
  while (1) {
    adc_rd = ADC_Read(2);        // Conversión A/D. Pin RA2 es una entrada.
    Lcd_Out(2,1,text);           // Escribir el resultado en la segunda línea
    tlong = (long)adc_rd * 5000; // Convertir el resultado en milivoltios    
    tlong = tlong / 1023;        // 0..1023 -> 0-5000mV
    ch = tlong / 1000;           // Extraer voltios (miles de milivoltios)
                              
    // del resultado             
    Lcd_Chr(2,9,48+ch);          // Escribir resultado en formato ASCII
    Lcd_Chr_CP('.');             
    ch = (tlong / 100) % 10;     // Extraer centenas de milivoltios
    Lcd_Chr_CP(48+ch);           // Escribir resultado en formato ASCII
    ch = (tlong / 10) % 10;      // Extraer decenas de milivoltios
    Lcd_Chr_CP(48+ch);           // Escribir resultado en formato ASCII
    ch = tlong % 10;             // Extraer unidades de milivoltios
    Lcd_Chr_CP(48+ch);           // Escribir resultado en formato ASCII
    Lcd_Chr_CP('V');
    Delay_ms(1);
  }
}

Contador de dos dígitos LED, multiplexión

Contador de dos dígitos LED, multiplexión

En este ejemplo el microcontrolador funciona como un contador de dos dígitos. La variable i se incrementa (suficiente lentamente para ser visible) y su valor se visualiza en un visualizador de dos dígitos LED (99-0). El punto es habilitar una conversión de un número binario en un decimal y partirlo en dos dígitos (en decenas y unidades). Como los segmentos del visualizador LED se conectan en paralelo, es necesario asegurar que alternen rápidamente para tener una impresión de que emiten la luz simultáneamente (multiplexión por división en tiempo).
En este ejemplo, el temporizador TMR0 está encargado de la multiplexión por división en tiempo, mientras que la función mask convierte un número binario a formato decimal.
Ejemplo 9
/*Cabecera******************************************************/

unsigned short mask(unsigned short num);
unsigned short digit_no, digit10, digit1, digit, i;

void interrupt() {
  if (digit_no == 0) {
    PORTA = 0;       // Apagar ambos visualizadores
    PORTD = digit1;  // Colocar máscara para visualizar unidades en el
 
    // puerto PORTD
    PORTA = 1;       // Encender el visualizador para las unidades (LSD)
    digit_no = 1;
  }else{
    PORTA = 0;       // Apagar ambos visualizadores
    PORTD = digit10; // Colocar máscara para visualizar decenas en el
 
    // puerto PORTD
    PORTA = 2;       // Encender el visualizador para las decenas (MSD)
    digit_no = 0;
  }
  
  TMR0 = 0;          // Reiniciar el contador TMRO
  INTCON = 0x20;     // Bit T0IF=0, T0IE=1
}

void main() {
  OPTION_REG = 0x80; // Ajustar el temporizador TMR0
  TMR0 = 0;
  INTCON = 0xA0;     // Deshabilitar las interrupciones PEIE,INTE,RBIE,T0IE
  PORTA = 0;         // Apagar ambos visualizadores
  TRISA = 0;         // Todos los pines del puerto PORTA se configuran
  
  // como salidas
  PORTD = 0;         // Apagar todos los segmentos del visualizador
  TRISD = 0;         // Todos los pines del puerto PORTD se configuran
  
  // como salidas
  do {
    for (i = 0; i<=99; i++) { // Contar de 0 a 99
      digit = i % 10u;
      digit1 = mask(digit);   // Preparar la máscara para visualizar unidades
      digit = (char)(i / 10u) % 10u;
      digit10 = mask(digit);  // Preparar la máscara para visualizar decenas
      Delay_ms(1000);
    }
  } while (1);                // Bucle infinito
}
mask.c
/*Cabecera******************************************************/

unsigned short mask(unsigned short num) {
  switch (num) {
    case 0 : return 0x3F;
    case 1 : return 0x06;
    case 2 : return 0x5B;
    case 3 : return 0x4F;
    case 4 : return 0x66;
    case 5 : return 0x6D;
    case 6 : return 0x7D;
    case 7 : return 0x07;
    case 8 : return 0x7F;
    case 9 : return 0x6F;
  }
}
Para que este ejemplo funcione apropiadamente, es necesario incluir el archivo mask.c en el proyecto (aparte del archivo example9.c) en la ventana Project Manager antes de compilar el programa:
Example9.mcppi - Sources - Add File To Project
  • mask.c
  • example9.c

Utilizar memoria EEPROM

Utilizar memoria EEPROM

Este ejemplo muestra cómo escribir y leer la memoria EEPROM incorporada. El programa funciona de la siguiente manera. El bucle principal lee constantemente el contenido de localidad de la memoria EEPROM en la dirección 5 (decimal). Luego el programa entra en el bucle infinito en el que el puerto PORTB se incrementa y se comprueba el estado de entradas del puerto PORTA.2. En el momento de presionar el botón denominado MEMO, un número almacenado en el puerto PORTB será guardado en la memoria EEPROM, directamente leído y visualizado en el puerto PORTD en forma binaria.
Ejemplo 8
/*Cabecera******************************************************/

void main() {{
  ANSEL = 0;                 // Todos los pines de E/S se configuran como digitales
  ANSELH = 0;
  PORTB = 0;                 // Valor inicial del puerto PORTB
  TRISB = 0;                 // Todos los pines del puerto PORTB se configuran
  
  // como salidas
  PORTD = 0;                 // Valor inicial del puerto PORTB  
  TRISD = 0;                 // Todos los pines del puerto PORTD se configuran
  
  // como salidas
  TRISA = 0xFF;              // Todos los pines del puerto PORTA se configuran
  
  // como entradas
  PORTD = EEPROM_Read(5);    // Leer la memoria EEPROM en la dirección 5
  
  do {
    PORTB = PORTB++;         // Incrementar el puerto PORTB en 1
    Delay_ms(100);           // Tiempo de retardo de 100mS
 
    if (PORTA.F2)
      EEPROM_Write(5,PORTB); // Si se pulsa el botón MEMO, guardar el puerto PORTB
   
    PORTD = EEPROM_Read(5);  // Leer el dato escrito
 
    do {
      while (PORTA.F2);      // Quedarse en este bucle hasta que el botón esté pulsado
    }
  }
  while(1);                  // Bucle infinito
}
Para comprobar el funcionamiento de este circuito, basta con pulsar el botón MEMO y apagar el dispositivo. Después de reiniciar el dispositivo, el programa visualizará el valor guardado en el puerto PORTD. Acuérdese de que en el momento de escribir, el valor fue visualizado en el puerto PORTB.
Para que este ejemplo funcione apropiadamente, es necesario marcar la librería EEPROM en la ventana Library Manager antes de compilar el programa:
  • EEPROM

Utilizar el convertidor A/D

Utilizar el convertidor A/D

El convertidor A/D del microcontrolador PIC16F887 se utiliza en este ejemplo. ¿Hace falta decir que todo es pan comido? Una señal analógica variable se aplica al pin AN2, mientras que el resultado de la conversión de 10 bits se muestra en los puertos POTRB y PORTD (8 bits menos significativos en el puerto PORTD y 2 bits más significativos en el puerto PORTB). La Tierra (GND) se utiliza como voltaje de referencia bajo Vref-, mientras que el voltaje de referencia alto se aplica al pin AN3. Esto habilita que la escala de medición se estire y encoja.
IEn otras palabras, el convertidor A/D siempre genera un resultado binario de 10 bits, lo que significa que reconoce 1024 niveles de voltaje en total (210=1024). La diferencia entre dos niveles de voltaje no es siempre la misma. Cuánto menor sea la diferencia entre Vref+ y Vref-, tanto menor será la diferencia entre dos de 1024 niveles. Como hemos visto, el convertidor A/D es capaz de detectar pequeños cambios de voltaje.
Ejemplo 7
/*Cabecera******************************************************/

unsigned int temp_res;

void main() {
  ANSEL = 0x0C;             // Pines AN2 y AN3 se configuran como analógicos
  TRISA = 0xFF;             // Todos los pines del puerto PORTA se configuran
  
  // como entradas
  ANSELH = 0;               // Los demás pines se configuran como digitales
  TRISB = 0x3F;             // Pines del puerto PORTB, RB7 y RB6 se configuran
  
  // como salidas
  TRISD = 0;                // Todos los pines del PORTD se configuran como salidas
  ADCON1.F4 = 1 ;           // Voltaje de referencia es llevado al pin RA3.
  
  do {
    temp_res = ADC_Read(2); // Resultado de la conversión A/D es copiado a temp_res
    PORTD = temp_res;       // 8 bits menos significativos se mueven al puerto PORTD
    PORTB = temp_res >> 2;  // 2 bits más significativos se mueven a los bits RB6 y RB7
  } while(1);               // Bucle infinito
}
Para que este ejemplo funcione apropiadamente, es necesario marcar la librería ADC en la ventana Library Manager antes de compilar el programa:
  • ADC

Módulo CCP1 como generador de señal PWM

Módulo CCP1 como generador de señal PWM

Este ejemplo muestra el uso del módulo CCP1 en modo PWM. Para hacer las cosas más interesantes, la duración de los pulsos en la salida P1A (PORTC,2) se puede cambiar por medio de los botones de presión simbólicamente denominados ‘OSCURO’ y ‘CLARO’. La duración ajustada se visualiza como una combinación binaria en el puerto PORTB. El funcionamiento de este módulo está bajo el control de las funciones pertenecientes a la librería especializada PWM. Aquí se utilizan las tres de ellas:
  1. PWM1_init tiene el prototipo: void Pwm1_Init(long freq);
    El parámetro freq ajusta la frecuencia de la señal PWM expresada en hercios. En este ejemplo equivale a 5kHz.
  2. PWM1_Start tiene el prototipo: void Pwm1_Start(void);
  3. PWM1_Set_Duty tiene el prototipo: void Pwm1_Set_Duty(unsigned short duty_ratio);
    El parámetro duty_ratio ajusta la duración de pulsos en una secuencia de pulsos.
La librería PWM también contiene la función PWM_Stop utilizada para deshabilitar este modo. Su prototipo es: void Pwm1_Stop(void);
Ejemplo 6
/*Cabecera******************************************************/

// Definir las variables ciclo_de_trabajo_actual, 
// ciclo_de trabajo_anterior

unsigned short ciclo_de_trabajo_actual;
unsigned short ciclo_de trabajo_anterior; 

void initMain() {
  ANSEL = 0;       // Todos los pines de E/S se configuran como digitales
  ANSELH = 0;
  PORTA = 255;     // Estado inicial del puerto PORTA
  TRISA = 255;     // Todos los pines del puerto PORTA se configuran como entradas
  PORTB = 0;       // Estado inicial del puerto PORTB
  TRISB = 0;       // Todos los pines del puerto PORTB se configuran como salidas
  PORTC = 0;       // Estado inicial del puerto PORTC
  TRISC = 0;       // Todos los pines del puerto PORTC se configuran
  
  // como salidas
  PWM1_Init(5000); // Inicialización del módulo PWM (5KHz)
}

void main() {
  initMain();
  ciclo_de_trabajo_actual = 16;    // Valor inicial de la variable ciclo_de_trabajo_actual
  ciclo_de trabajo_anterior = 0;   // Reiniciar la variable ciclo_de trabajo_anterior
  PWM1_Start();                    // Iniciar el módulo PWM1
  
  while (1) {                      // Bucle infinito
    if (Button(&PORTA, 0,1,1))     // Si se presiona el botón conectado al RA0
    ciclo_de_trabajo_actual++ ;    // incrementar el valor de la variable current_duty
    if (Button(&PORTA, 1,1,1))     // Si se presiona el botón conectado al RA1
    ciclo_de_trabajo_actual-- ;    // decrementar el valor de la variable current_duty
 
    if (old_duty != ciclo_de_trabajo_actual) {             // Si ciclo_de_trabajo_actual y
      // ciclo_de trabajo_anterior no son iguales
      PWM1_Set_Duty(ciclo_de_trabajo_actual);              // ajustar un nuevo valor a PWM,
      ciclo_de trabajo_anterior = ciclo_de_trabajo_actual; // Guardar el nuevo valor
      PORTB = ciclo_de trabajo_anterior;                   // y visualizarlo en el puerto PORTB
    }
    Delay_ms(200); // Tiempo de retardo de 200mS
  }
}
Para que este ejemplo funcione apropiadamente, es necesario marcar las siguientes librerías en la ventana Library Manager antes de compilar el programa:
  • PWM
  • Button

Utilizar el temporizador perro - guardián

Utilizar el temporizador perro - guardián

Este ejemplo muestra cómo NO se debe utilizar el temporizador perro-guardián. Un comando utilizado para reiniciar este temporizador se omite a propósito en el bucle del programa principal, lo que habilita al temporizador perro guardián “ganar la batalla del tiempo” y reiniciar al microcontrolador. Por consiguiente, el microcontrolador se va a reiniciar sin parar, lo que indicará el parpadeo de los LEDs del puerto PORTB.
Ejemplo 5
/*Cabecera******************************************************/

void main() {
  OPTION_REG = 0x0E; // Pre-escalador se le asigna al temporizador WDT (1:64)
  asm CLRWDT;        // Comando en ensamblador para reiniciar el temporizador WDT
  PORTB = 0x0F;      // Valor inicial del registro PORTB
  TRISB = 0;         // Todos los pines del puerto PORTB se configuran como salidas
  Delay_ms(300);     // Tiempo de retardo de 30mS
  PORTB = 0xF0;      // Valor del puerto PORTB diferente del inicial
                     
  while (1);         // Bucle infinito. El programa se queda aquí hasta que el
                     // temporizador WDT reinicie al microcontrolador
}
Para que este ejemplo funcione apropiadamente, es necesario habilitar al temporizador perro-guardián al seleccionar la opción Tools/mE Programmer/Watchdog Timer - Enabled.
Ejemplo 5 Ejecución

Utilizar los temporizadores Timer0, Timer1 y Timer2

Utilizar los temporizadores Timer0, Timer1 y Timer2. Utilizar interrupciones, declarar nuevas funciones...

Al analizar los ejemplos anteriores, es probable que se haya fijado en la desventaja de proporcionar tiempo de retardo por medio de la función Delay. En estos casos, el microcontrolador se queda ‘estático’ y no hace nada. Simplemente espera que transcurra una cierta cantidad de tiempo. Tal pérdida de tiempo es un lujo inaceptable, por lo que se deberá aplicar otro método.
¿Se acuerda usted del capítulo de los temporizadores? ¿Se acuerda de lo de interrupciones? Este ejemplo los conecta de una manera práctica. El esquema se queda inalterada, y el desafío sigue siendo presente. Es necesario proporcionar un tiempo de retardo suficiente largo para darse cuenta de los cambios en el puerto. Para este propósito se utiliza el temporizador Timer0 con el pre-escalador asignado. Siempre que se genere una interrupción con cada desbordamiento en el registro del temporizador, la variable cnt se aumenta automáticamente en 1 al ejecutarse cada rutina de interrupción. Cuando la variable llega al valor 400, el puerto PORTB se incrementa en 1. Todo el procedimiento se lleva a cabo “entre bastidores”, lo que habilita al microcontrolador hacer otra tarea.
Ejemplo 4
/*Cabecera******************************************************/

unsigned cnt;          // Definir la variable cnt

void interrupt() {
  cnt++;               // Con una interrupción la cnt se incrementa en 1
  TMR0 = 96;           // El valor inicial se devuelve en el temporizador TMR0
  INTCON = 0x20;       // Bit T0IE se pone a 1, el bit T0IF se pone a 0
}

void main(){
  OPTION_REG = 0x84;   // Pre-escalador se le asigna al temporizador TMR0
  ANSEL = 0;           // Todos los pines de E/S se configuran como digitales
  ANSELH = 0;
  TRISB = 0;           // Todos los pines de puerto PORTB se configuran
  
                       // como salidas
  PORTB = 0x0;         // Reiniciar el puerto PORTB
  TMR0 = 96;           // Temporizador T0 cuenta de 96 a 255
  INTCON = 0xA0;       // Habilitada interrupción TMR0
  cnt = 0;             // A la variable cnt se le asigna un 0
  
  do {                 // Bucle infinito
    if (cnt == 400) {  // Incrementar el puerto PORTB después 400 interrupciones
      PORTB = PORTB++; // Incrementar número en el puerto PORTB en 1
      cnt = 0;         // Reiniciar la variable cnt
    }
  } while(1);
  
}
Ejemplo 4 con TMR0
Siempre que se produzca un desbordamiento en el registro del temporizador TRM0, ocurre una interrupción.
/*Cabecera******************************************************/

unsigned short cnt;   // Definir la variable cnt

void interrupt() {
  cnt++ ;             // Con una interrupción la cnt se incrementa en 1
  PIR1.TMR1IF = 0;    // Reiniciar el bit TMR1IF
  TMR1H = 0x80;       // El valor inicial se devuelve en los registros
  TMR1L = 0x00;       // del temporizador TMR1H y TMR1L
}

void main() {
  ANSEL = 0;          // Todos los pines de E/S se configuran como digitales
  ANSELH = 0;
  PORTB = 0xF0;       // Valor inicial de los bits del puerto PORTB
  TRISB = 0;          // Pines del puerto PORTB se configuran como salidas
  T1CON = 1;          // Configurar el temporizador TMR1
  PIR1.TMR1IF = 0;    // Reiniciar el bit TMR1IF
  TMR1H = 0x80;       // Ajustar el valor inicial del temporizador TMR1
  TMR1L = 0x00;
  PIE1.TMR1IE = 1;    // Habilitar la interrupción al producirse un desbordamiento
  cnt = 0;            // Reiniciar la variable cnt
  INTCON = 0xC0;      // Interrupción habilitada (bits GIE y PEIE)
  
  do {                // Bucle infinito
    if (cnt == 76) {  // Cambiar el estado del puerto PORTB después de 76 interrupciones
      PORTB = ~PORTB; // Número en el puerto PORTB está invertido
      cnt = 0;        // Reiniciar la variable cnt
    }
  } while (1);
}
Ejemplo 4 con TMR1
En este caso, una interrupción se habilita después de que se produzca un desbordamiento en el registro del temporizador TMR1 (TMR1H, TMR1L). Además, la combinación de los bits que varía en el puerto POTRB difiere de la en el ejemplo anterior.
/*Cabecera******************************************************/

unsigned short cnt;   // Definir la variable cnt

void Reemplazar() {
  PORTB = ~PORTB;     // Definir nueva función ‘Reemplazar’
}                     // Función invierte el estado del puerto

void interrupt() {
  if (PIR1.TMR2IF) {  // Si el bit TMR2IF = 1,
    cnt++ ;           // Incrementar variable la cnt en 1
    PIR1.TMR2IF = 0;  // Reiniciar el bit y
    TMR2 = 0;         // Reiniciar el registro TMR2
  }
}

// main
void main() {
  cnt = 0;            // Reiniciar la variable cnt
  ANSEL = 0;          // Todos los pines de E/S se configuran como digitales
  ANSELH = 0;
  PORTB = 0b10101010; // Estado lógico en los pines del puerto PORTB
  TRISB = 0;          // Todos los pines del puerto PORTB se configuran como salidas
  T2CON = 0xFF;       // Configurar el temporizador T2
  TMR2 = 0;           // Valor inicial del registro del temporizador TMR2
  PIE1.TMR2IE = 1;    // Interrupción habilitada
  INTCON = 0xC0;      // Bits GIE y PEIE se ponen a 1
  
  while (1) {         // Bucle infinito
    if (cnt > 30) {   // Cambiar el estado del puerto PORTB después de
                      // más de 30 interrupciones
      Reemplazar();   // Función Reemplazar invierte el estado del puerto PORTB
      cnt = 0;        // Reiniciar la variable cnt
    }
  }
}
Example 4 using TMR2
En este ejemplo, una interrupción ocurre después de que se produce un desbordamiento en el registro del temporizador TMR2. Para invertir el estado lógico de los pines del puerto se utiliza la función Reemplazar, que normalmente no pertenece al lenguaje C estándar

Primer Programa en MikroC

Escribir cabecera, configurar pines de E/S, utilizar la función Delay y el operador Switch

El único propósito de este programa es de encender varios diodos LED en el puerto B. Utilice este ejemplo para examinar cómo es un programa real. La siguiente figura muestra el esquema de conexión, mientras que el programa se encuentra en la siguiente página.
Configuración de pines I/O
Al encender la fuente de alimentación, cada segundo, el diodo LED en el puerto B emite luz, lo que indica que el microcontrolador está conectado correctamente y que funciona normalmente.
En este ejemplo se muestra cómo escribir una cabecera correctamente. Lo mismo se aplica a todos los programas descritos en este libro. Para no repetir, en los siguientes ejemplos no vamos a escribir la cabecera. Se considera estar en el principio de cada programa, marcada como "Cabecera".
Ejemplo de cabecera
Para hacer este ejemplo más interesante, vamos a habilitar que los LEDs conectados al puerto PORTB parpadeen. Hay varios modos de hacerlo:
  1. Tan pronto como se encienda el microcontrolador, todos los LEDs emitirán la luz por un segundo. La función Delay se encarga de eso en el programa. Sólo se necesita ajustar la duración del tiempo de retardo en milisegundos.
  2. Después de un segundo, el programa entra en el bucle for, y se queda allí hasta que la variable k sea menor que 20. La variable se incrementa en 1 después de cada iteración. Dentro del bucle for, el operador switch monitorea el estado lógico en el puerto PORTB. Si PORTB=0xFF, su estado se invierte en 0x00 y viceversa. Cualquier cambio de estos estados lógicos hace todos los LEDs parpadear. El ciclo de trabajo es 5:1 (500mS:100mS).
  3. Al salir del bucle for, el estado lógico del puerto POTRB cambia (0xb 01010101) y el programa entra en el bucle infinito while y se queda allí hasta que 1=1. El estado lógico del puerto PORTB se invierte cada 200mS.
Program Example