Ayuda con pic 16f877 y ccs

Hola amigos del foro, estoy comenzando un proyecto de la uni, y el primer paso es conseguir que presionando cualquier entrada del puerto b se active una salida por el puerto d, lo estuve realizando en ccs, use la sentencia case, el programa lo compila, pero en el proteus no funciona, no se cual es mi error, tengo dudas con la sentencia case, se pueden ingresar datos de esta forma como lo he hecho en binario? y lo otro estoy leyendo directamente el portb, no es necesario guardarlo en otra variable?,estee s el codigo :

#include <16F877A.h> /// libreria para el manejo del pic16f877a
#use delay(clock=4000000) /// declara la frecuencia del cristal

#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT

#byte portb = 0x06 // se definen las direcciones de memoria
#byte portd = 0x08


void main(void){

set_tris_b(0xff); // se configura el puerto b como entrada
set_tris_d(0x00); // puerto d como salida para el speaker
output_d(0x00); //limpiamos los pines del puerto d

switch(portb){

case 0b00000001:
output_high(PIN_D0);
output_high(PIN_D3);
delay_ms(500);
break;

case 0b00000010:
output_high(PIN_D0);
break;

case 0b00000100:
output_high(PIN_D0);
break;

case 0b00001000:
output_high(PIN_D0);
break;

case 0b00010000:
output_high(PIN_D0);
break;

case 0b00100000:
output_high(PIN_D0);
break;

case 0b01000000:
output_high(PIN_D0);
break;

case 0b10000000:
output_high(PIN_D0);
break;

}while(true);

}
 
El error lo tenes en que el While que usas para un bucle infinito no hace nada, es decir esta mal ubicado debería empezar sobre las sentencia switch y terminar al final. Te lo dejo modificado por si no te das cuenta. Ademas la sentencia WHILE no se escribe WHILE(true); sino WHILE(true){}

Código:
#include <16F877A.h> /// libreria para el manejo del pic16f877a
#use delay(clock=4000000) /// declara la frecuencia del cristal

#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT

#byte portb = 0x06 // se definen las direcciones de memoria
#byte portd = 0x08


void main(void){

set_tris_b(0xff); // se configura el puerto b como entrada 
set_tris_d(0x00); // puerto d como salida para el speaker
output_d(0x00); //limpiamos los pines del puerto d

             while(true){

switch(portb){

case 0b00000001:
output_high(PIN_D0); 
output_high(PIN_D3);
delay_ms(500); 
break;

case 0b00000010:
output_high(PIN_D0); 
break;

case 0b00000100:
output_high(PIN_D0); 
break;

case 0b00001000:
output_high(PIN_D0); 
break;

case 0b00010000:
output_high(PIN_D0); 
break; 

case 0b00100000:
output_high(PIN_D0); 
break;

case 0b01000000:
output_high(PIN_D0); 
break;

case 0b10000000:
output_high(PIN_D0); 
break;

}
}

}
 
Pues gracias , no me percate de este detalle, lo logre simular, pero al simular: si yo ingreso un dato al puerto b efectivamemnte se enciende el RD0, pero no se apaga queda constantemente prendido, asi haya dejado de pulsar una entrada en el puertob, o es que debo agregar una instruccion mas para apagar el RD0.

Se que parecen cosas faciles, pero recien estoy empezando en esto del ccs,

gracias
 
No hay problema, siempre se empieza así :). Efectivamente deberías realizar una rutina que testee si todo el puerto B es 0 que apague las salidas que se encendieron.

Saludos
 
eso de la rutina de testeo no es el switch?, estoy usando esta sentencia para evaluar constantemente el puerto b , si hay un cambio en una entrada se enciende el pin 0 del puerto D. y si no se mantiene apagado, bueno eso lo pense asi enm un primer momento, no pense que hay que hacer otra rutina de testeo.

pues consegui lo que buscaba, faltaba una sentencia mas denbtro del bucle switch, y era lo del dafault, si no es ningun valor de los indicados, pongo que el rd0 se apague.
gracias por los aportes ahora ya complete esta parte, se va avanzando poco a poco
 
Última edición:
lo que hace tu programa es poner a 1 D0 cada vez que se ponga a 1 cualquier pin del puerto b, pero nunca pones un caso o una condicion para apagar, depende como quieras apagar es la nstruccion que deberas poner
 
gracias sammaael y dragondgold, ya se hizo esta parte ahora miren lo que se tiene que hacer es que cada vez que se ponga a 1 cualquier pin del portb se escuche un sonido por esta salida rd0, lo que hize antes solo era una prueba, osea ya consegui que se encienda un led, pero ahora ahi debe haber un speaker que emita el sonido cada vez que se presione una entrada del puerto b.

Es como si fuera un piano, imaginense que cada entrada del puerto b seria una tecla del piano y corresponderia a una nota, se que tengo que usar la libreria tones.c pero lo que no se es como definirla, por que hay varias opciones de esocger una nota do (X) x hay con 1,2,3,4

Saludos
 
bueno esa libreria se adjunta cuando instala s el ccs, pero si no la tienes aqui te la adjunto, ojo que se ha cambiado la extension para poder subirlo, esta en txt, para que funcione dentro del entorno ccs, debe estar con extensionv .c a ver si puedes descubrir como se define la funcion para que me ayudes

Saludos
 

Adjuntos

  • TONES.txt
    3.4 KB · Visitas: 84
Hola a todos, tengo un libro nuevo de ccs, y he copiado un programa tal como esta escrito y aunque me produjo algunos errores, no se como solucionar 3 errores que no me permiten ensamblar el programa y la parte especifica es en el lcd.c pienso yo.

Es simplemente para el manejo de un lcd de 2x16 y unos pulsadores, aqui lo pongo:

#include <16F876.h>
#fuses xt,nowdt
#use delay(clock = 4000000)
#include <lcd.c>
#use standard_io(C)
#use standard_io(A)


enum funciones {med,cal,ini}; //Asigna un valor a cada elemento
//med = 0, cal = 1 e ini = 2

void medir(void){ //Funcion medir
//Algoritmo correspondiente
output_toggle(pin_C0);
}

void calibrar(void){ //Funcion calibrar
//Algoritmo correspondiente
output_toggle(pin_C1);
}

void inicializar(void){ //Funcion inicializar
//Algoritmo correspondiente
output_toggle(pin_C2);
}

void run_func(int numfunc){ //Asignacion de la funcion a realizar
//viene dada por la variable "item"

switch(numfunc){
case med:
medir();
break;
case cal:
calibrar();
break;
case ini:
inicializar();
break;
}
}

void main(){
char item; //Variables de las funciones
char n_menus = 3; //Numero de Funciones

//bit_set(trisa,0);
lcd_init();

while (1){
if (input(pin_A0) == 1){ //detecta boton de seleccion
item++; //Si pulsa aumenta la variable
delay_ms(300); //Para evitar rebotes
lcd_putc('\f');}

if (item > (n_menus-1)){ //Si la variable supera el numero de...
item = 0;} //funciones la inicializa

switch (item) {

case 0:
lcd_gotoxy(1,1);
printf(lcd_putc,"Medir");
lcd_gotoxy(1,1);
break;

case 1:
printf(lcd_putc,"Calibrar");
lcd_gotoxy(1,1);
break;

case 2:
printf(lcd_putc,"Inicializar");
lcd_gotoxy(1,1);
break;
}
if (input(pin_a1) == 1) //Si pulsa boton de seleccion...
{delay_ms(200);
run_func(item);} //Se llama a la funcion correspondiente
}
}

y los errores que me salen son:

Error12"C:/David PCS CCS/PICC/Drivers/lcd.c"Line 91{29,30}: Undefined identifier ''set_tris_d
Error12"C:/David PCS CCS/PICC/Drivers/lcd.c"Line 103{30,31}: Undefined identifier ''set_tris_d
Error12"C:/David PCS CCS/PICC/Drivers/lcd.c"Line 133{28,29}: Undefined identifier ''set_tris_d

El programa que estoy usando es PCW y despues le puse la instruccion #define use_portb_lcd TRUE, pero igual me sale los mismos errores y cuando clikeo para visualizar la linea fallida, esta me lleva a la libreria del lcd (lcd.c) y me senala las siguientes lineas de esa libreria:

set_tris_lcd(LCD_READ);
set_tris_lcd(LCD_WRITE);
set_tris_lcd(LCD_WRITE);
 
antes me pasaba lo mismo te recomiendo uses esta libreria que no me da problemas

PHP:
///////////////////////////////////////////////////////////////////////////
////                             LCD.C                                ////
////                 Driver for common LCD modules                     ////
////                                                                   ////
////  lcd_init()   Must be called before any other function.           ////
////                                                                   ////
////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
////                     The following have special meaning:           ////
////                      \f  Clear display                            ////
////                      \n  Go to start of second line               ////
////                      \b  Move back one position                   ////
////                                                                   ////
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
////                                                                   ////
////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2003 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS C  ////
//// compiler.  This source code may only be distributed to other      ////
//// licensed users of the CCS C compiler.  No other use, reproduction ////
//// or distribution is permitted without written permission.          ////
//// Derivative programs created using this software in object code    ////
//// form are not restricted in any way.                               ////
///////////////////////////////////////////////////////////////////////////
//
// As defined in the following structure the pin connection is as follows:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.
//
// Un-comment the following define to use port B
 #define use_portb_lcd TRUE
//
//
struct lcd_pin_map {                 // This structure is overlayed
           BOOLEAN enable;           // on to an I/O port to gain
           BOOLEAN rs;               // access to the LCD pins.
           BOOLEAN rw;               // The bits are allocated from
           BOOLEAN unused;           // low order up.  ENABLE will
           int     data : 4;         // be pin B0.
        } lcd;
//
#if defined(__PCH__)
#if defined use_portb_lcd
   #byte lcd = 0xF81                   // This puts the entire structure
#else
   #byte lcd = 0xF83                   // This puts the entire structure
#endif
#else
#if defined use_portb_lcd
   #byte lcd = 6                  // on to port B (at address 6)
#else
   #byte lcd = 8                 // on to port D (at address 8)
#endif
#endif
//
#if defined use_portb_lcd
   #define set_tris_lcd(x) set_tris_b(x)
#else
   #define set_tris_lcd(x) set_tris_d(x)
#endif
//
#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line
//
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.
//
                             // The following are used for setting
                             // the I/O port direction register.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
//
BYTE lcd_read_byte() {
      BYTE low,high;
      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}
//
void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}
//
void lcd_send_byte( BYTE address, BYTE n ) {
      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}
//
void lcd_init() {
    BYTE i;
    set_tris_lcd(LCD_WRITE);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}
//
void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;   
  if(y!=1)
    address=lcd_line_two;
  else
    address=0;
  address+=x-1;
  lcd_send_byte(0,0x80|address);
}
//
void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}
//
char lcd_getc( BYTE x, BYTE y) {
   char value;
    lcd_gotoxy(x,y);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd.rs=1;
    value = lcd_read_byte();
    lcd.rs=0;
    return(value);
}
 
Hola sammael, gracias por tu ayuda, he seguido leyendo el libro pero aun no he intentado copilar los siguientes ejemplos, mi pregunta es si conoces alguna pagina donde se puedan encontrar librerias confiables que se puedan usar??

Gracias por todo
 
hola amigos del foro, bueno me ausente un tiempo por un motivo personal, y el trabajo quedo a medias, ll drl piano estuve checando mi avance, y aun me falta mucho para conseguirlo.
Lo que estuve ya consegui generar un sonido con el pic usando la libreriatones.c del ccs, tengo que adicionar un selector de octavas, lo estuve haciendo por el puerto a son tres pulsadores que cada vez que sensen un 1 el programa cambie la generacion de sonido por otra octava, lo esty haciendo con un switch, osea sensando cada una de estas enmtradas, y como va ver tyres casos diferentes, se active una octava diferente, lo que sucede es que mi programa no detecta el cambio de las entradas del puertoa , se queda estancado en una sola octava asi yo cambie de posicion la entrada a, pienso que se esta quedando dentro de ese bucle, alguien me podria ayudar creo que al correr el programa sensa la octava que seleccione, y se queda ahi.

este es el programa lo he planteado con dos sentencias switch, uno detecta en que octava esta, y el otro detecta que tecla se presiono, no se si estara bn.

void main(void){

int x;
int y;
set_tris_b(0xff); // se configura el puerto b como entrada ,0 es salida y 1 es entrada
set_tris_d(0x00); // puerto d como salida para el speaker
set_tris_a(0xff); // puerto a como entrada para la seleccion de octavas
set_tris_c(0x00); // puerto c como salida es para visualizar en que octava estas
output_d(0x00); //limpiamos los pines del puerto d
output_c(0x00); //limpiamos los pines del puerto c
x=input_b();
y=input_a();

while(true){ //bucle infinito

switch(y){

case 1:
output_c(0x01);
switch(portb){

case 1:
generate_tone(C_NOTE[0], fusa); //nota do
break;

case 2:
generate_tone(D_NOTE[0], fusa); //nota re
break;

case 4:
generate_tone(E_NOTE[0], fusa); //nota mi
break;

case 8:
generate_tone(F_NOTE[0], fusa); //nota fa
break;

case 16:
generate_tone(G_NOTE[0], fusa); //nota sol
break;

case 32:
generate_tone(A_NOTE[0], fusa); //nota la
break;

case 64:
generate_tone(B_NOTE[0], fusa); //nota si
break;

case 128:
generate_tone(C_NOTE[0], fusa); //otra vez la nota do
break;
//default :
//output_low(PIN_D0);
}
break;

case 2:

output_c(0x02);
switch(portb){

case 1:
generate_tone(C_NOTE[1], negra); //nota do
break;

case 2:
generate_tone(D_NOTE[1], negra); //nota re
break;

case 4:
generate_tone(E_NOTE[1], negra); //nota mi
break;

case 8:
generate_tone(F_NOTE[0], negra); //nota fa
break;

case 16:
generate_tone(G_NOTE[1], negra); //nota sol
break;

case 32:
generate_tone(A_NOTE[1], negra); //nota la
break;

case 64:
generate_tone(B_NOTE[1], negra); //nota si
break;

case 128:
generate_tone(C_NOTE[1], negra); //otra vez la nota do
break;
//default :
//output_low(PIN_D0);
}
break;

case 4:

output_c(0x04);
switch(portb){

case 1:
generate_tone(C_NOTE[2], blanca); //nota do
break;

case 2:
generate_tone(D_NOTE[2], blanca); //nota re
break;

case 4:
generate_tone(E_NOTE[2], blanca); //nota mi
break;

case 8:
generate_tone(F_NOTE[2], blanca); //nota fa
break;

case 16:
generate_tone(G_NOTE[2], blanca); //nota sol
break;

case 32:
generate_tone(A_NOTE[2], blanca); //nota la
break;

case 64:
generate_tone(B_NOTE[2], blanca); //nota si
break;

case 128:
generate_tone(C_NOTE[2], blanca); //otra vez la nota do
break;
//default :
//output_low(PIN_D0);
}
break;

// default:
// output_c(0x01);
// y=1;
}

}
} //

el ccs si lo compila, lo que sucede es que al probarlo con el proteus no funciona.
 
amigos del foro nuevamebnte recurro a ustedes para que me ayuden, este prog, es del piano que lo sigo realizando, tengo una duda estoy haciendo una funcion que detecta el puerto a si se ha presionado una tecla que es up o down, que representa el selector de octavas, luego esta funcion devuelve un valor entero y este valor lo comparo con un comando switch para ver que octava a sido deleccionada, enm la depuracion no sale errores, pèro en la simulacion no funciona, mi duda es saber si esta bn declarado y llamado la funcion que cree: int sele_octava(void). pongo el codigo para que lo vean :

// DECLARACION DE VARIABLES GLOBALES

int S_corchea=125,corchea=250,fusa=62;
long negra=500,blanca=1000,redonda=2000;

int octava;

// DECLARACION DE PROTOTIPOS DE FUNCIONES

int sele_octava(void); //no espera un argumento y devuelve un numero entero



// PROGRAMA PRINCIPAL
void main(void){

set_tris_b(0xff); // se configura el puerto b como entrada ,0 es salida y 1 es entrada
set_tris_d(0x00); // puerto d como salida para el speaker
set_tris_a(0xff); // puerto a como entrada para la seleccion de octavas
set_tris_c(0x00); // puerto c como salida es para visualizar en que octava estas
output_d(0x00); //limpiamos los pines del puerto d
output_c(0x00); //limpiamos los pines del puerto c

while(true){ //bucle infinito

sele_octava();
switch(octava){

case 1:
output_c(octava);
switch(portb){
case 1:
generate_tone(C_NOTE[0], fusa); break; //nota do
case 2:
generate_tone(D_NOTE[0], fusa); break; //nota re
case 4:
generate_tone(E_NOTE[0], fusa); break; //nota mi
case 8:
generate_tone(F_NOTE[0], fusa); break; //nota fa
case 16:
generate_tone(G_NOTE[0], fusa); break; //nota sol
case 32:
generate_tone(A_NOTE[0], fusa); break; //nota la
case 64:
generate_tone(B_NOTE[0], fusa); break; //nota si
case 128:
generate_tone(C_NOTE[0], fusa); break; //otra vez la nota do
default:break;
}
break;

case 2:
output_c(octava);
switch(portb){
case 1:
generate_tone(C_NOTE[1], negra); break; //nota do
case 2:
generate_tone(D_NOTE[1], negra); break; //nota re
case 4:
generate_tone(E_NOTE[1], negra); break; //nota mi
case 8:
generate_tone(F_NOTE[0], negra); break; //nota fa
case 16:
generate_tone(G_NOTE[1], negra); break; //nota sol
case 32:
generate_tone(A_NOTE[1], negra); break; //nota la
case 64:
generate_tone(B_NOTE[1], negra); break; //nota si
case 128:
generate_tone(C_NOTE[1], negra); break; //otra vez la nota do
default:break;
}
break;

case 4:
output_c(octava);
switch(portb){
case 1:
generate_tone(C_NOTE[2], blanca); break; //nota do
case 2:
generate_tone(D_NOTE[2], blanca); break; //nota re
case 4:
generate_tone(E_NOTE[2], blanca); break; //nota mi
case 8:
generate_tone(F_NOTE[2], blanca); break; //nota fa
case 16:
generate_tone(G_NOTE[2], blanca); break; //nota sol
case 32:
generate_tone(A_NOTE[2], blanca); break; //nota la
case 64:
generate_tone(B_NOTE[2], blanca); break; //nota si
case 128:
generate_tone(C_NOTE[2], blanca); break; //otra vez la nota do
default:break;
}
break;
default:break;
}
}
} // fin de programa



// DEFINICION DE LAS FUNCIONES


int sele_octava (void){

signed char i=0; //contador para tabla
int tabla[3]={0b001,0b010,0b100,}; //octava 1 2 3

octava = tabla[ i ]; //inicializa octava 1 xq i=0
//output_c(octava); //enciende los leds en el puerto c indicando la octava seleccionada

if(input(PIN_A0)==1) //¿se ha pulsado el boton up?
{
delay_ms(250); //SI -> retardo para evitar los rebotes
i++; //incremento contador
if(i>2) //¿se ha mostrado digito 2?
i=0; //SI -> restaura valor indice(para mostrar digito 0)
}
if(input(PIN_A1)==1) //¿se ha pulsado el boton down?
{
delay_ms(250); //SI -> retardo para evitar los rebotes
i--; //decremento contador
if(i<0) //¿se ha mostrado digito 0?
i=2; //SI -> restaura valor indice(para mostrar octava 3)
}
octava = tabla[ i ];
//output_c(octava); //muestra por portc en que octava esta

//output_c(octava); //inicializa octava 1 xq i=0
return octava;

}
 
Hola a todos!
Soy Totalmente nuevo en el uso de pics, así como en su programación.
Alguien podría decirme, ¿cómo puedo meter una canción al PIC? Más que eso, cómo programarla...
No les pido que me ahorren el trabajo, sino que me guíen para poder hacerlo, ya que no tengo ni la más mínima idea de cómo introducirla, peor que eso, cómo sacarla después a una bocina.
Saludos!
 
Podes grabar las diferentes frecuencias que tenes que reproducir para formar la cancion en un EEPROM o mejor aun RAM externa o MMC y luego tomar el valor binario que representa la frecuencia y sacarla por un pin del PIC al altavoz.
Lo complicado sería obtener un programa que pase la cancion a esos datos binarios. Averigua como trabaja el formato .WAV.

Saludos
 
Atrás
Arriba