Migrar Librerias de Arduino a PIC.

no son micros raros ni patrañas y menos artimañas

son otros micros de otros fabricantes y CCS no es un compilador fiable, almenos para mi no es del todo confiable y no es estandar.

si el AVR studio si es mas fiable y confiable que CCS, cada quien es libre de usar un compilador C , a menos que sea arduino ahi le dire no inventes !!!.
 
Estoy controlando un modulo generador de señales via spi con un pic, especificamente el ad9833.
Funciona perfectamente, pero solo puedo generar ciertas frecuencias debido a que se usan palabras de 28bits; encontre un ejemplo basado en arduino que me puede servir pero no entiendo muy bien las operaciones que realiza.

El codigo en cuestión:

Código:
 //Once we\'ve got that, we split it up into separate bytes.
 MSB = (int)((calculated_freq_word & 0xFFFC000)>>14); //14 bits
 LSB = (int)(calculated_freq_word & 0x3FFF);


No se si esta realizando operaciones "and" o se refiere a otra operación.

En las hojas de datos del ad9833 muestra un ejemplo pero solo utiliza 14 bits, segui los pasos y solo puedo generar frecuencias de 0Hz a 1500Hz, si quisiera frecuencias mas grandes requiero de 28 bits y lamentablemente no se como formar la palabra.

Gracias de antemano. ...
 
Espero que tengas bien el código y no como aparece ahi XD
Son operaciones lógicas simples, (int) es conversion explicita, & es un operador de AND a nivel de bits, con 0xFFFC000 crea una mascara de bits, prácticamente ignora los bits en ceros, que serian los primeros, el símbolo >> indica un desplazamiento de bits hacia la derecha indicado que son 14.
En el segundo se indica simplemente mascara con los 0x3FFF (los primeros 14) y así es que separa las variables en 2.

Por si acaso, así es como debería verse el código:
Código:
 //Once we\'ve got that, we split it up into separate bytes.
 MSB = (int)((calculated_freq_word & 0xFFFC000)>>14); //14 bits
 LSB = (int)(calculated_freq_word & 0x3FFF);

Las operaciones a nivel de bits y desplazamiento de bits son generales en todos los procesadores, así que puedes usar la función como está, solo recuerda declarar las variables apropiadamente.
 
Hola:

Este es el código de Arduino que quiero pasar a C del CCS.
Código:
int pinLed =  13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  pinMode(pinLed, OUTPUT);  // Inicializa el pin del Led 1 como salida.
  /* Voy leyendo carácter a carácter lo que se recibe por el canal
   *  serie (mientras llegue algún dato allí), y los voy concatenando
   *  uno tras otro en una cadena. En la práctica, si usamos el
   *  "Serial monitor" el bucle while acabará cuando pulsemos Enter.
   *  El delay es conveniente para no saturar el canal serie y que la
   *  concatenación se haga de forma ordenada.
   */
  while (Serial.available() > 0)
  {
    caracter= Serial.read();
    comando.concat(caracter);
    delay(10);
  }

  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
   * que la placa Arduino reaccione según sea este. Aquí podríamos
   * hacer lo que quiesiéramos: si el comando es "tal", enciende
   * un Led, si es cual, mueve un motor... y así.
   */
  if (comando.equals("s1000") == true)  // Led_ON
  {
        digitalWrite(pinLed, HIGH); // Enciende el Led.
        Serial.println("EQUA");
  }
        
  if (comando.equals("s0000") == true) // Led_OFF
  {
        digitalWrite(pinLed, LOW); // Apaga el Led.
        Serial.println("EQUA");
  } 
  
  // Limpiamos la cadena para volver a recibir el siguiente comando. 
  comando="";
}
Hice algo que poco tiene que ver. Por eso los que sepan, intentar hacer lo más parecido a Arduino, con estilo, no lo que hice en C para el PIC.

Código:
#include <16F876A.h> 
#fuses HS,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay (clock=4000000)         //Fosc=4Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)   //manejo del RS232
#use fast_io (B)
#use fast_io (C)
/*******************************
Declaramos variables a usar
*/////////////////////////

#byte RCSTA=0X018
#define usart_off bit_clear(RCSTA,7)
#define usart_on bit_set(RCSTA,7)
//int xbe_buffer [6];
int dat,dat0,dat1,dat2,dat3;
int1 flag=false;



void main (void)
{
setup_adc_ports(no_analogs);
set_tris_c(0b11111000);
set_tris_a(0b000000);
set_tris_b(0b00000000);
output_a(0b000000);
output_b(0b00000000);
output_c(0b00000000);



while(1)
{

int conta=0;
usart_on;
//delay_ms(100);
while(getc() !=0x73);
{flag=true;
for(conta=0;conta<4;conta++)
{dat=getc();
// ([conta]=getc());
switch(conta)
{
case 0: dat0=dat;
break;
case 1: dat1=dat;
break;
case 2: dat2=dat;
break;
case 3: dat3=dat;
break;
default:
break;
}
//putc(getc());
}
}
if(flag==true)
{
if((dat0=='1') && (dat1=='0') && (dat2=='0') && (dat3=='0'))
{output_high(pin_b5);
output_high(pin_b4);
output_high(pin_c2);
putc ('E');
putc ('Q');
putc ('U');
putc ('A');
flag=false;
}
if(dat0=='0' && dat1=='0' && dat2=='0' && dat3=='0')
{ output_low(pin_a5);
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_b2);
output_low(pin_b1);
output_low(pin_b0);
output_low(pin_b5);
output_low(pin_c1);
output_low(pin_c2);
output_low(pin_b4);
putc ('E');
putc ('Q');
putc ('U');
putc ('A');
flag=false;
}
}
Saludos.
 
En C tenés librerías ansi que pueden ayudarte:

- comando.equals("s1000") => strcmp(cadena1, cadena2)
- comando.concat(caracter) => strcat(cadena1, cadena2)

Esas funciones se encuentran en la librería "string.h". Fijate si tenés espacio de código suficiente en el uC, de lo contrario vas a tener que hacer algo más a la medida.

Luego la impresión por medio del puerto serie deberás encargarte vos de hacer una rutina para enviar/recibir un string por el puerto serie (supongo que serán las funciones getc y putc). Lo mismo que el manejo de los puertos.

Lo que hiciste para comparar los string no es tan loco, solo que está mal implementado, deberías usar vectores o punteros, que es lo mismo que hacés en assembler cuando apuntás en memoria usando un registro como dirección.
 
Hola:

Actualicé el código del PIC arriba.

Aquí abajo, encontré un código ejemplo que no se si estará mejor sin gastar tanta RAM.
Código:
/* El módulo EUSART. Control remoto y monitorización

Este ejemplo recibe una serie de comandos ('0'-'7') que permiten cambiar de estado las salidas
RB7:RB0. Constantemente se transmite, previa conversión a ASCII, el estado actual de esas salidas 
a modo de monitorización */

#include <16f886.h>

/* Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades */

#fuses     NOLVP,PUT,NOWDT,EC_IO,NOFCMEN,NOBROWNOUT    //Palabra 1 de configuración
#fuses    NOWRT,BORV40                                //Palabra 2 de configuración

/* Con estas directivas las funciones "input" y "output_bit" no reprograman
el pin de la puerta cada vez que son utilizadas. Si no se indica el
modo fast_io se asume por defecto standard_io el cual reprograma el pin
siempre antes de ser utilizadas estas funciones. */

#use fast_io (B)
#use fast_io (C)
#use delay(clock=4000000)            //Frecuencia de trabajo

//Habilita las funciones RS232, velocidad a 9600 baudios

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#byte PORTB =0x06                    //Dirección de la puerta B

/*Programa de tratamiento de la interrupción que se produce al recibir un carácter. Analiza el
comando recibido ('0' -'7') y actua sobre la salida apropiada haciéndola cambiar de estado */

#int_rda            //Vector de interrupción al recibir por el UART
tratamiento()
{    switch(getc())        //Lee el carácter recibido
    {
        case '0': output_toggle(pin_b0);break;    //Si es el comando '0' , RB0 cambia de estado
        case '1': output_toggle(pin_b1);break;    //Si es el comando '1' , RB1 cambia de estado
        case '2': output_toggle(pin_b2);break;    //Si es el comando '2' , RB2 cambia de estado
        case '3': output_toggle(pin_b3);break;    //Si es el comando '3' , RB3 cambia de estado
        case '4': output_toggle(pin_b4);break;    //Si es el comando '4' , RB4 cambia de estado
        case '5': output_toggle(pin_b5);break;    //Si es el comando '5' , RB5 cambia de estado
        case '6': output_toggle(pin_b6);break;    //Si es el comando '6' , RB6 cambia de estado
        case '7': output_toggle(pin_b7);break;    //Si es el comando '7' , RB7 cambia de estado
    }    
}

main()
{  
    signed int Contador;

    SETUP_ADC_PORTS(NO_ANALOGS);    //Puerta A y B Digitales
    output_b(0x00);                    //Borra las salidas
    set_tris_b(0b00000000);            //Puerta B salida
    set_tris_c(0b10111111);            //RC6/TxD salida de datos y RC7/RxD entrada del EUSART    
    putc('\r');                        //Transmite CR
    putc('\n');                        //Transmite avance de línea

    enable_interrupts(INT_RDA);        //Activa interrupción en la recepción
    enable_interrupts(global);        //Habilita interrupciones

    while(1)
    {
        for (Contador=7;Contador>=0;Contador--)    //Contador con Nº de bits a chequear
            printf ("%c",bit_test(PORTB,Contador)+'0');    //Transmite los bits convertidos a ASCII
            putc('\r');                //Transmite CR
    }
}
 
Dejando de lado ciertas funciones que parecen propias del CCS (no las conozco), pareciera que si funcionaría.

Lo que te recomendaría, es utilizar una trama aunque sea bien sencilla, para descartar mensajes equivocados. La trama por ej. la podés hacer con 3 bytes:

Byte cabecera (tipo código) - Byte con el datos a leer - Byte de checksum (la suma de los dos bytes anteriores)

Si bien estás transmitiendo el triple de información, hacés más robusta la comunicación y a futuro te permite expandirla a enviar algo más complejo que un solo byte de datos, pensá que te permitiría tomar decisiones diferentes según el byte de código que envías, haciendo por ejemplo que el byte de datos se pueda convertir en un array de datos según ese código.

Otra alternativa sencilla para este caso, es agregar el bit de paridad.
 
Buenas estimados colegas, lo que sucede es lo siguiente, he decido usar el DS3231 para hacer un reloj usando el pin SQW, ese pin genera una señal de 1hz onda cuadrada, para mi es más fácil hacer que esa señal de 1hz incremente una variable llamada "segundo" ya que 1hz significa = 1 segundo, he visto tutoriales en youtube y leído artículos y la mayoría hace el reloj con hora y fecha con un código largo y es algo dificil de modificar, pero usando el pin SQW lo noto más sencillo de hacerlo, ya que con el incremento de 1 segundo, puedo incrementar los minutos y horas yo tendría que hacer el resto del código, lo bueno es que pude hacerlo con arduino, ya que encontre una librería que me permite usar el SQW del ds3231, pero MI PROBLEMA esta en que no he podido encontrar una librería para usarlo con un pic 16f877A con el CCS, alguien podría darme una mano como puedo hacer que el DS3231 genere 1hz para pic 16f877A?

He intentado usar la librería de arduino en el CCS, pero tiene esa opción de "wire.h" y eso no hay en CCS .


P.D.: en arduino como ejemplo para incrementar una variable "seconds" (segundos) con el DS3231 es así:


Código:
#include <Wire.h>       //I2C library
#include <RtcDS3231.h> //RTC library
 
RtcDS3231 <TwoWire> rtcObject(Wire);

const byte interruptPin = 3;
volatile int16_t seconds = 0;


void setup() {
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
  rtcObject.Begin(); //Starts I2C
  rtcObject.SetSquareWavePin(DS3231SquareWavePin_ModeClock); //Sets pin mode
  rtcObject.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz); //Sets frequency
}

void handleInterrupt() {
  seconds++;
}

void loop() {
  // put your main code here, to run repeatedly:

} ...
Claro que detrás de ese código de ejemplo está la librería ya instalada en el arduino IDE
 
Atrás
Arriba