Tuesday 18 July 2017

PCF8563 interface with nRF51822


File Name : main.c
#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_uart.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "PCF8563.h"
#include "nrf_delay.h"

/* UART buffer size */
#define UART_TX_BUF_SIZE 256
#define UART_RX_BUF_SIZE 1

#warning "!**** ARE YOU ABSOLUTELY SURE YOU HAVE CHOSEN THE CORRECT SCL AND SDA PINS? ****!"

#define DEVICE_SCL_PIN 5
#define DEVICE_SDA_PIN 6

nrf_drv_twi_t twi_instance = NRF_DRV_TWI_INSTANCE(0);

uint8_t device_address = 0; // Address used to temporarily store the current address being checked
bool device_found = false;


/**
 * @brief UART events handler.
 */
static void uart_events_handler(app_uart_evt_t * p_event)
{
    switch (p_event->evt_type)
    {
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}


/**
 * @brief UART initialization.
 */
static void uart_config(void)
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud115200
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_events_handler,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

/**
 * @brief TWI events handler.
 */
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{  
    switch(p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            // If EVT_DONE (event done) is received a device is found and responding on that particular address
            //printf("\r\n!****************************!\r\nDevice found at 7-bit address: %#x!\r\n!****************************!\r\n\r\n", device_address);
            //device_found = true;
                                                   
            break;
        case NRF_DRV_TWI_EVT_ADDRESS_NACK:
            printf("No address ACK on address: %#x!\r\n", device_address);
            break;
        case NRF_DRV_TWI_EVT_DATA_NACK:
            printf("No data ACK on address: %#x!\r\n", device_address);
            break;
        default:
            break;       
    }  
}

/**
 * @brief UART initialization.
 */
void twi_init (void)
{
    ret_code_t err_code;
   
    const nrf_drv_twi_config_t twi_config = {
       .scl                = DEVICE_SCL_PIN,
       .sda                = DEVICE_SDA_PIN,
       .frequency          = NRF_TWI_FREQ_400K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH
    };
    err_code = nrf_drv_twi_init(&twi_instance, &twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);   
    nrf_drv_twi_enable(&twi_instance);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    date_time_t dt;
    nrf_gpio_cfg_output(LED_1);
    nrf_gpio_pin_set(LED_1);
    uart_config();
    printf("PCF8563 RTC Test...........\r\n");
    twi_init();
             Initialize_PCF8563();
                  nrf_delay_ms(1000);    // nrf_delay_ms(1000);
                 dt.month   = 7;    // December
      dt.day     = 18;    // 31
      dt.year    = 17;    // 2006
      dt.hours   = 11;    // 23 hours (11pm in 24-hour time)
      dt.minutes = 49;    // 59 minutes 
      dt.seconds = 45;    // 50 seconds
      dt.weekday = 0;     // 0 = Sunday, 1 = Monday, etc.

      PCF8563_set_datetime(&dt);  

    while(1){
      nrf_delay_ms(1000);
                                       PCF8563_read_datetime(&dt);
                                       printf("Time: %d:%d:%d\r\n", dt.hours,dt.minutes,dt.seconds);
                                       printf("Date: %d:%d:%d\r\n", dt.day,dt.month,dt.year);
                                      
    }
}

/** @} */
File Name : PCF8563.c
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "string.h"
#include "PCF8563.h" 

nrf_drv_twi_t twi_dist_pcf8563 = NRF_DRV_TWI_INSTANCE(0);

uint8_t _rm_bcd(uint8_t data);
uint8_t _get_bcd(uint8_t data);

//======================================================================================
uint8_t bin2bcd(uint8_t binary_value)
{
  uint8_t temp;
  uint8_t retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }

  return(retval);
}
//====================================================================================================

// Input range - 00 to 99.
uint8_t bcd2bin(uint8_t bcd_value)
{
  uint8_t temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
            

/*
   temp=bcd_value;
   bcd_value=(temp>>4)*10;
   bcd_value=bcd_value+(temp&0x0F);
             return bcd_value;
             */
}
//======================================================================================

void PCF8563_writeReg(uint8_t W_reg, uint8_t value)
{
   ret_code_t ret;
    do
    {
        uint8_t buffer[2]; /* Addr + data */
        buffer[0] = W_reg;
        buffer[1] = value;
        ret = nrf_drv_twi_tx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR , buffer, 2, false);
    }while (0);
   nrf_delay_ms(5);
}
//======================================================================================
uint8_t PCF8563_readReg(uint8_t W_reg)
{
  ret_code_t ret;
  uint8_t W_data;
    do
    {
       ret = nrf_drv_twi_tx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR, &W_reg, 1, true);
       if (NRF_SUCCESS != ret)
       {
                                                     printf("Error 1\r\n");
          return 0;
       }
                                        nrf_delay_ms(5);
       ret = nrf_drv_twi_rx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR, &W_data, 1);
       if (NRF_SUCCESS != ret)
       {
                                                     printf("Error 2\r\n");
          return 0;
       }
    }while (0);
                          nrf_delay_ms(5);
      return W_data;
}
//======================================================================================
void PCF8563_writeMulti(uint8_t W_reg, uint8_t const * src, uint8_t count)
{
      ret_code_t ret;

   do{
      uint8_t buffer[1 + count]; /* index + data */
      buffer[0] = (uint8_t)W_reg;
      memcpy(buffer + 1, src, count);
      ret = nrf_drv_twi_tx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR, buffer, count + 1, false);
   } while (0);
              nrf_delay_ms(5);
 }
//======================================================================================
 void PCF8563_readMulti(uint8_t W_reg, uint8_t * dst, uint8_t count)
{
  
       ret_code_t ret; 

    do
    {
       ret = nrf_drv_twi_tx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR, &W_reg, 1, true);
       if (NRF_SUCCESS != ret)
       {
                                                      //printf("Return with Error \r\n");
          break;
       }
                                       nrf_delay_ms(5);
       ret = nrf_drv_twi_rx(&twi_dist_pcf8563, I2C_PCF8563_SLAVE_ADDR, dst, count);
                                         if (NRF_SUCCESS != ret)
       {
                                                      printf("Return with Error \r\n");
          break;
       }
    }while (0);
   nrf_delay_ms(5);
}
//======================================================================================
void Initialize_PCF8563(void){
             PCF8563_writeReg(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);
             //PCF8563_writeReg(0x0D,0x83);
}
//======================================================================================
void PCF8563_set_datetime(date_time_t *dt) {

  PCF8563_writeReg(PCF8563_SECONDS_REG,bin2bcd(dt->seconds));  
             PCF8563_writeReg(PCF8563_MINUTES_REG,bin2bcd(dt->minutes)); 
             PCF8563_writeReg(PCF8563_HOURS_REG,bin2bcd(dt->hours));
             PCF8563_writeReg(PCF8563_DAY_REG,bin2bcd(dt->day));
             PCF8563_writeReg(PCF8563_WEEK_REG,dt->weekday);
             PCF8563_writeReg(PCF8563_MONTH_REG,bin2bcd(dt->month));
             PCF8563_writeReg(PCF8563_WEEK_REG,bin2bcd(dt->year));
}
//======================================================================================
void PCF8563_read_datetime(date_time_t *dt)
{
             unsigned char LCu_Array[7]={0};
             PCF8563_readMulti(PCF8563_SECONDS_REG,LCu_Array,7);
             dt->seconds = bcd2bin(LCu_Array[0]&0x7F);
             dt->minutes = bcd2bin(LCu_Array[1]&0x7F);     
             dt->hours   = bcd2bin(LCu_Array[2] & 0x3F);
             dt->day     = bcd2bin(LCu_Array[3] & 0x3F);
             dt->month   = bcd2bin(LCu_Array[5] & 0x1F);
             dt->weekday =    LCu_Array[4] & 0x07;
             dt->year    = bcd2bin(LCu_Array[6]); 
}
//======================================================================================

File Name : PCF8563.h
#ifndef PCF8563_H__
#define PCF8563_H__
 
#include "nordic_common.h"
#include "nrf_drv_config.h"
#include "app_error.h"

typedef struct
{
uint8_t seconds;    // 0 to 59
uint8_t minutes;    // 0 to 59
uint8_t hours;      // 0 to 23  (24-hour time)
uint8_t day;        // 1 to 31
uint8_t weekday;    // 0 = Sunday, 1 = Monday, etc.
uint8_t month;      // 1 to 12
uint8_t year;       // 00 to 99
}date_time_t;

             #define I2C_PCF8563_SLAVE_ADDR                       0x51
// registers //
#define PCF8563_CONTROL1   0x00     //control/status 1
#define PCF8563_CONTROL2   0x01     //control/status 2
#define PCF8563_CLKOUT     0x0D     //CLKOUT control
#define PCF8563_TCONTROL   0x0E     //timer control
#define PCF8563_TIMER      0x0F     //timer countdown value

#define PCF8563_SECONDS    0x02     //0..59 BCD (bit7 is VL)
#define PCF8563_MINUTES    0x03     //0..59 BCD
#define PCF8563_HOURS      0x04     //0..23 bcd
#define PCF8563_DAYS       0x05     //1..31 bcd
#define PCF8563_WEEKDAY    0x06     //0..6
#define PCF8563_MONTHS     0x07     //0..12 (bit7 is Century, leave clear for 20xx)
#define PCF8563_YEARS      0x08     //0..99 bcd

#define PCF8563_MINUTE_ALARM  0x09  //0..59 BCD
#define PCF8563_HOUR_ALARM    0x0A  //0..23 BCD
#define PCF8563_DAY_ALARM     0x0B  //0..31 BCD
#define PCF8563_WEEKDAY_ALARM 0x0C  //0..6
            
            
// Register addresses
#define PCF8563_CTRL_STATUS_REG1   0x00
#define PCF8563_CTRL_STATUS_REG2   0x01
#define PCF8563_SECONDS_REG        0x02
#define PCF8563_MINUTES_REG        0x03
#define PCF8563_HOURS_REG          0x04
#define PCF8563_DAY_REG            0x05
#define PCF8563_WEEK_REG           0x06
#define PCF8563_MONTH_REG          0x07
#define PCF8563_YEAR_REG           0x08
#define PCF8563_ALARM_MINS_REG     0x09
#define PCF8563_ALARM_HOURS_REG    0x0A
#define PCF8563_ALARM_DAY_REG      0x0B
#define PCF8563_ALARM_WEEKDAY_REG  0x0C
#define PCF8563_CTRL_CLKOUT_REG    0x0D
#define PCF8563_CTRL_TIMER_REG     0x0E
#define PCF8563_TIMER_REG          0x0F

// Commands for the Control/Status register.
#define PCF8563_START_COUNTING     0x08
#define PCF8563_STOP_COUNTING      0x28


//*************************************  for Set_Alarm()
#define PCF8563_Alarm_off          0x00
#define PCF8563_M_Mode             0x01
#define PCF8563_MH_Mode            0x04
#define PCF8563_MHW_Mode           0x07
#define PCF8563_MHD_Mode           0x0B 

//*************************************  for config_CLKOUT()
#define PCF8563_CLKOUT_off         0x00
#define PCF8563_CLKOUT_32KHz       0x80
#define PCF8563_CLKOUT_1KHz        0x81
#define PCF8563_CLKOUT_32Hz        0x82
#define PCF8563_CLKOUT_1Hz         0x83

//*************************************  for config_PCF8563_Timer()
#define PCF8563_Timer_off          0x00
#define PCF8563_Timer_4KHz         0x80
#define PCF8563_Timer_64Hz         0x81
#define PCF8563_Timer_1Hz          0x82
#define PCF8563_Timer_1_60Hz       0x83

//*************************************  for config_PCF8563_Interrupt()
#define Alarm_Interrupt_Enable     0x01
#define Timer_Interrupt_Enable     0x02
#define A_T_Interrupt_Enable       0x03
#define Timer_INT_Pulse_on         0x10
#define Timer_INT_Pulse_off        0x00

uint8_t bin2bcd(uint8_t binary_value) ;
uint8_t bcd2bin(uint8_t bcd_value) ;
void PCF8563_writeReg(uint8_t W_reg, uint8_t value);
uint8_t PCF8563_readReg(uint8_t W_reg);
void PCF8563_writeMulti(uint8_t W_reg, uint8_t const * src, uint8_t count);
void PCF8563_readMulti(uint8_t W_reg, uint8_t * dst, uint8_t count);
void Initialize_PCF8563(void);
void PCF8563_set_datetime(date_time_t *dt);
void PCF8563_read_datetime(date_time_t *dt) ;


#endif /* PCF8563_H_ */

No comments:

Post a Comment

ESP8266 Multiple Timer

ESP8266 Maximum upto 7 OS_Timer Source code : #include <Arduino.h> extern "C" { #include "user_interface.h"...