Estoy intentando leer la hora desde un RTC con mi Microcontrolador PIC32 a través de SPI. Ya he logrado leer el tiempo con un Arduino del RTC.
PIC32 : enlace (Documentación, Hoja de datos)
RTC : enlace (Documentación, Hoja de datos)
Arduino : Arduino Pro Mini
Problema : de alguna manera, los valores que lee el PIC32 del RTC no son correctos. Tal vez los valores no se lean o almacenen correctamente con el PIC32. Por ejemplo, el valor de los segundos leídos del RTC solo está por debajo de 30 cuando el RTC realmente está entre los segundos 50 y 59. (El segundo valor% 2 sigue siendo = 0 cada dos segundos). No sé por qué obtengo esos valores extraños de la RTC.
Códigos : he incluido ambos ejemplos de código: la versión de trabajo de Arduino y la versión de PIC32 que no funciona.
Versión de trabajo de Arduino:
#include <SPI.h>
const int cs=10; //chip select
int TimeDate[7]; //second,minute,hour,null,day,month,year
void setup() {
Serial.begin(9600);
pinMode(cs,OUTPUT); // chip select
pinMode(8,OUTPUT); // LED light
// start the SPI library:
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work
//set control register
digitalWrite(cs, LOW);
SPI.transfer(0x8E);
SPI.transfer(0x60); //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
digitalWrite(cs, HIGH);
delay(10);
}
void loop() {
ReadTimeDate();
// (TimeDate[0] contains the seconds read from the rtc)
if(TimeDate[0]<30) digitalWrite(8, HIGH); // works perfectly, is on from 0 t0 30
else digitalWrite(8, LOW);
delay(50);
}
void ReadTimeDate(){
for(int i=0; i<=6;i++){
if(i==3) i++;
digitalWrite(cs, LOW);
SPI.transfer(i+0x00);
unsigned int n = SPI.transfer(0x00);
digitalWrite(cs, HIGH);
int a=n & B00001111;
if(i==2){
int b=(n & B00110000)>>4; //24 hour mode
if(b==B00000010) b=20;
else if(b==B00000001) b=10;
TimeDate[i]=a+b;
}else if(i==4){
int b=(n & B00110000)>>4;
TimeDate[i]=a+b*10;
}else if(i==5){
int b=(n & B00010000)>>4;
TimeDate[i]=a+b*10;
}else if(i==6){
int b=(n & B11110000)>>4;
TimeDate[i]=a+b*10;
}else{
int b=(n & B01110000)>>4;
TimeDate[i]=a+b*10;
}
}
}
Versión de PIC32 que no funciona:
#include <p32xxxx.h>
#include <plib.h>
// configure bit settings
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = XT, FNOSC = PRIPLL, FPBDIV = DIV_1, CP = OFF, BWP = OFF
// I/O Definitions
#define CS _RG9 // chip select
#define TCS _TRISG9 // tris control for CS pin
#define SYS_FREQ (80000000L)
int TimeDate[7]; //second,minute,hour,null,day,month,year
// send one byte of data and receive one back at the same time
char writeSPI2( char i ) {
SPI2BUF = i; // write to buffer for TX
while( !SPI2STATbits.SPIRBF ); // wait for TX complete
return SPI2BUF; // read the received values
}
// delay in microseconds function
void delay_us( delay ) {
// note that 1 core tick = 2 SYS cycles (this is fixed)
int us_ticks=( SYS_FREQ / 1000000 ) / 2;
WriteCoreTimer( 0 );
while( ReadCoreTimer() < delay*us_ticks );
}
main() {
SYSTEMConfig( SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE );
mOSCSetPBDIV( OSC_PB_DIV_2 ); // added
// Open core timer for delay function
OpenCoreTimer( 0xFFFFFFFF );
// SPI config
// CKP (clock polarity control) = 0
// CKE (clock edge control) = 1
// 8-bit, Master Mode
// Baud = 4MHz (Fpb/20 = 80/20 MHz)
SpiChnOpen( 2, SPICON_MSTEN | SPICON_CKE | SPICON_ON, 20 );
// initialize the SPI peripheral
TCS = 0; // make CS pin output
CS = 1; // release chip
// 2. RTC settings
delay_us( 1000000 ); // wait 1s
CS = 0;
delay_us( 40000 ); // delay 40ms
writeSPI2(0x8E);
writeSPI2(0x60); // 60 = disable Osciallator and Battery SQ wave @1hz,
// temp compensation, Alarms disabled
CS = 1;
delay_us( 10000 );
// 3. Pin settings (to visualize feedback)
DDPCONbits.JTAGEN = 0; // disable JTAGport, free up PORTA
TRISA = 0b0000000000000000; // all PORTA as output (0 = 0 utput , 1 = 1 nput)
// main loop
while(1) {
ReadTimeDate();
if( TimeDate[0] < 30 ) PORTA = 0b1111111111111111; // does not work at all, the LED is on from 50 to 59 (why??????)
else PORTA = 0b0000000000000000;
delay_us( 5000 );
}
}
ReadTimeDate() {
int i; // change TODO: changed to char
for (i = 0; i <= 6; i++) {
if (i == 3)
i++;
CS = 0;
writeSPI2(i + 0x00);
unsigned int n = writeSPI2(0x00);
CS = 1;
int a = n & 0b00001111;
if (i == 2) {
int b = (n & 0b00110000) >> 4; //24 hour mode
if (b == 0b00000010) b = 20;
else if (b == 0b00000001) b = 10;
TimeDate[i] = a + b;
} else if (i == 4) {
int b = (n & 0b00110000) >> 4;
TimeDate[i] = a + b * 10;
} else if (i == 5) {
int b = (n & 0b00010000) >> 4;
TimeDate[i] = a + b * 10;
} else if (i == 6) {
int b = (n & 0b11110000) >> 4;
TimeDate[i] = a + b * 10;
} else {
int b = (n & 0b01110000) >> 4;
TimeDate[i] = a + b * 10;
}
}
}
Posibles errores:
- No sé si es necesario configurar BITOrder en MSBFirst en el PIC32. (como en la versión Arduino) (y no sé cómo)
- Es posible que BaudRate no esté configurado correctamente. (aunque lo obtuve de un gran tutorial)
- Las conversiones de tipo y valor y las operaciones de bit en la función ReadTime () no se pueden manejar de la misma manera que en el Arduino, lo que podría causar la lectura de valores extraños en el RTC
Versión de PIC32 RTCC no funciona:
Aquí hay un fragmento de código que he hecho para usar para el módulo RTCC en el UBW32.
No funciona, ya que los minutos aparecen impares todo el tiempo en la prueba.
No sé si necesito más definiciones de pines, o si debo unir un cristal.
Aquí está el esquema. A mi me parece que se incluye un cristal: enlace
// Master header file for all peripheral library includes
#include <plib.h>
// configuration settings
#pragma config FNOSC = PRIPLL, POSCMOD = HS, FPLLMUL = MUL_18, FPLLIDIV = DIV_2, FPBDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FWDTEN = OFF
int main(void) {
rtccTime tm; // time structure
rtccDate dt; // date structure
// Configure the device for maximum performance.
// This macro sets flash wait states, PBCLK divider and DRM wait states based on the specified
// clock frequency. It also turns on the cache mode if avaialble.
// Based on the current frequency, the PBCLK divider will be set at 1:2. This knoweldge
// is required to correctly set UART baud rate, timer reload value and other time sensitive
// setting.
SYSTEMConfigPerformance(72000000L);
RtccInit(); // init the RTCC
while(RtccGetClkStat()!=RTCC_CLK_ON); // wait for the SOSC to be actually running and RTCC to have its clock source
// could wait here at most 32ms
RtccOpen(0x10073000, 0x07011602, 0); // set time and date (- actually i don't know what time is set, but for the moment it doesn't matter.)
// time is MSb: hour, min, sec, rsvd. date is MSb: year, mon, mday, wday.
// please note that the rsvd field has to be 0 in the time field!
RtccGetTimeDate(&tm, &dt); // get current time
DDPCONbits.JTAGEN = 0; // disable JTAGport, free up PORTA
TRISA = 0b0000000000000000;
TRISB = 0b0000000000000000;
while(1){
RtccGetTimeDate(&tm, &dt);
// test: minutes odd or even
int minutes = tm.min%2;
switch(minutes){
case 0:
PORTA = 0b0000000000000000;
PORTB = 0b1111111111111111;
break;
case 1:
PORTA = 0b1111111111111111;
PORTB = 0b0000000000000000;
break;
}
}
}
¿Alguien tiene una idea de cómo puedo obtener los valores correctos con el PIC32?