Introduction:
Recently, I stumbled upon a scenario where I had to write Nano130’s SPI driver code for ADE7753 while I already had written this with NUC200. You can go through my previous blog to compare this blog with previous one and you will find out how stuffs change when microcontrollers change.

Note:
As we know Nano130 works on 3.3 volt and ADE7753 works on 5 volt so need a signal voltage translator. Follow this link to know how to use a voltage level translator between two SPI devices.

Pins connection:
See diagram for the pin connections

Nano_spi

Source Code:-
Include some header file which is given below

#include <stdio.h>
#include "nano1xx.h"
#include "nano1xx_sys.h"

Now need to declare some variables

double ADE7753_output_data;
uint32_t delay=0;

Need to declare a function to write in the register of ADE7753. Three parameters are needed to call this function.

  1. Address of the register in which you want to write
  2. Data which you want to write to that register
  3. Total no. of bytes in data

See the function

void write_to_ADE7753(int ADE7753_address, long write_buffer, int bytes_to_write)
    {
    uint8_t bit_length=0;
    // Add write command to data
    ADE7753_address = ADE7753_address|0x80;
    // select slave	 
    SPI0->SSR = 1;				
    //total bit length				
    bit_length= 8+bytes_to_write*8;
    if(bit_length == 32)
       {
        bit_length = 0;
       }
     // set bit length
    SPI0->CTL = (SPI0->CTL & ~SPI_CTL_TX_BIT_LEN_MASK) | (bit_length << 3);
    //Store data into TX buffer 
    SPI0->TX0= ((ADE7753_address)<<(bytes_to_write*8)) | write_buffer; 
    // start transmitting                               
    SPI0->CTL |= SPI_CTL_GO_BUSY;
    // wait until the transmission is not completed
    while(SPI0->CTL & SPI_CTL_GO_BUSY);
    // Deselect Slave
    SPI0->SSR = 0;  									
}

After that make another function to read a register of ADE7753. Two parameters will be needed to call this function

  1. Address of the register to which you want to read
  2. total bytes which you want to read

See the function

uint32_t read_ADE7753(int ADE7753_address, int bytes_to_read)
   {
    int i;
    uint8_t data2=0;
    uint32_t data = 0;
    SPI0->SSR = 1; //select slave
     //set bit length
    SPI0->CTL = (SPI0->CTL & ~SPI_CTL_TX_BIT_LEN_MASK) | (8 << 3); 
    // write data to TX buffer
    SPI0->TX0=ADE7753_address;
    // start transmission
    SPI0->CTL |= SPI_CTL_GO_BUSY;
    while(SPI0->CTL & SPI_CTL_GO_BUSY);
    //wait until the transmission is not finished 	
    /* now receive data*/ 
    for ( i = 1; i <= bytes_to_read; i++)
        {
        SPI0->TX0 = 0xFF; //get data byte
        SPI0->CTL |= SPI_CTL_GO_BUSY;
        while(SPI0->CTL & SPI_CTL_GO_BUSY);
        data2=SPI0->RX0&0xFF;
        data = data|data2;
        if (i< bytes_to_read) {
        data = data<<8; // bit operation
        }
    }
    SPI0->SSR = 0;										
    return data;
}

Now Time to write main function. In this function we will initialize the system clock, SPI clock and setting of SPI port0.

int main(void)
   {
    GCR->IPRST_CTL2 |= GCR_IPRSTCTL2_SPI0;
    GCR->IPRST_CTL2 &= ~GCR_IPRSTCTL2_SPI0;	
    CLK->APBCLK |= CLK_APBCLK_SPI0_EN;		
    GCR->PC_L_MFP = (GCR->PC_L_MFP & ~(PC0_MFP_MASK|PC1_MFP_MASK|PC2_MFP_MASK|PC3_MFP_MASK));
    GCR->PC_L_MFP |= (PC0_MFP_SPI0_SS0 | PC1_MFP_SPI0_SCLK | PC2_MFP_SPI0_MISO0 | PC3_MFP_SPI0_MOSI0);
    //select SPI0, SPI1 clock source are both from PLL
    CLK->CLKSEL2 = (CLK->CLKSEL2 & CLK_CLKSEL2_SPI0_MASK) | CLK_CLKSEL2_SPI0_PLL;
    SPI0->CLKDIV= (SPI0->CLKDIV & ~SPI_CLKDIV_DIVIDER1_MASK) | 0x10;
    //SPI_MODE_MASTER
    SPI0->CTL = (SPI0->CTL & ~0x40000); 
    //Set MSB first
    SPI0->CTL=(SPI0->CTL &= ~0x0400)|0; 
    // SPI_TYPE1
    SPI0->CTL = (SPI0->CTL & ~0x806) |0x002;  
    //disable auto slave select
    SPI0->SSR &= ~SPI_SSR_AUTOSS;	 
     // Select low as slave select
    SPI0->SSR &= ~SPI_SSR_SS_LVL;

Initialize UART port 0 to see the output on serial monitor. Always remember that Baud rate of serial monitor and microcontroller should be same.


    GCR->PA_H_MFP = (GCR->PA_H_MFP &~(PA15_MFP_MASK|PA14_MFP_MASK)) |            (PA15_MFP_UART0_TX|PA14_MFP_UART0_RX);
    /* Enable UART0 clock */
    CLK->APBCLK |= CLK_APBCLK_UART0_EN;    
    CLK->CLKDIV0 &= ~CLK_CLKDIV0_UART_MASK;
    /* Select 12 Mhz XTAL */
    CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_MASK) | CLK_CLKSEL1_UART_HXT;  
    //UART_CLK_DIVIDER(x)
    /* Set UART to 115200,n,8,1,none */
    /* Baud Rate:115200 for 12MHz */
    UART0->BAUD = 0x67;  
    UART0->TLCTL = 0x03;     
    printf("nn");
    printf("+-------------------------------------------------+n");
    printf("|    Nano130 SPI Driver Sample Code for ADE7753   |n");	
    printf("+-------------------------------------------------+n");

Write a while(1) loop which is a infinite loop and will write and read registers continue with delay of some seconds.

while(1)
  {
   for(delay=0; delay< 620000; delay++);
    //write to mode register
   write_to_ADE7753(0x09,0x2c,2);
   for(delay=0; delay< 620000; delay++);
   for(delay=0; delay< 620000; delay++);
   // read from temperature register
   ADE7753_output_data= read_ADE7753(0x26,1); 
   // print temp. value
   printf("Temp %f   ",ADE7753_output_data); 
   //read from IRMS register
   ADE7753_output_data = read_ADE7753(0x16,3);
   // print IRMS. value
   printf("IRMS %f",ADE7753_output_data);
    //read from VRMS register 
   ADE7753_output_data = read_ADE7753(0x17,3); 
   // print VRMS. value
   printf("  VRMS  %f",ADE7753_output_data);
  }
}

Note:-

  1. You will receive zero if AC input is not connected to ADE7753 IC so first connect AC input then do testing.
  2. This board comes with the LCD which conflicts with the SPI0 port so it is highly recommended to remove LCD from Nuvoton Nano130 board.

If still you are facing any problem please leave comment.