Newbie: Problem using MC13192 on AVR AT90CAN128

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Newbie: Problem using MC13192 on AVR AT90CAN128

3,594 Views
Ravs
Contributor I
Hi,
 
I am new to this forum and new to the embedded world. My sincere apologies if this is not the right place for posting my query .
 
I have one AVR AT90CAN128 MCU which drives an MC13192 radio. I want to port one application which was written for freescale HCS08 MCU using SMAC onto my AVR MCU. The following code is developed using AVR Studio 4 and WinAVR.
 
Here in this code, i am trying to reset the transceiver and then calling one Init_MC13192() function. I have tried to port the MC13192Init(), the one mentioned in MC13192_hw_config.c.
After doing that i am trying to send one register address with read access to read the contents of that register like

  SPI_DATA_REGISTER = reg_address;   /* place register address on MOSI*/
  while(!(SPSR &(1<<SPIF));          /* Wait for transmission to complete */
  receive_data = SPI_DATA_REGISTER;  /* Read the SPI data register to obtain received data*/

I have to call the above routine three times to obtain the contents of the corresponding register. Am i missing something? I am not able to receive anything from transceiver side.
 
Thanks.
 
#include<avr/io.h>
#include<inttypes.h>
#define F_CPU 16000000L   /* MCU Clock Speed */
#define SPI_PORT PORTB    /* Define SPI port */
#define SS PB0            /* The SPI Slave Select Bit */
unsigned char Rx_SPI[2];
uint16_t delay_count;
uint8_t temp;
void delay(uint8_t ms)
{
   uint16_t cnt;
   asm volatile (
   "\n"
   "L_dl1%=:" "\n\t"
   "mov %A0, %A2" "\n\t"
   "mov %B0, %B2" "\n"
   "L_dl2%=:" "\n\t"
   "sbiw %A0, 1" "\n\t"
   "brne L_dl2%=" "\n\t"
   "dec %1" "\n\t"
   "brne L_dl1%=" "\n\t"
   : "=&w" (cnt)
   : "r" (ms), "r" (delay_count)
   );
}
void ZB_Reset()
{
        DDRD  |= (1 << DDD7) | (1 << DDD1) ; //Set Direction register as output
    PORTD = (0 << PD7); //Resetting the ZB chip by pulling low RST pin
   
 delay(10);
  
    PORTD = (1 << PD7); //Set to normal mode ZB chip to pulling high
 delay(25);
}
void SPI_MasterInit(void)
{
  
  
   /* Set MISO MOSI and SCK output, all others input */
   DDRB |= (0<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0);
   /* Enable SPI, Master, set clock rate fck/16 */
   SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  
}
uint8_t SPI_SingularTransaction(uint8_t data)
{
  SPDR = data;
  while(!(SPSR &(1<<SPIF)));
  return SPDR;
}
void SPIDrvWrite(uint8_t reg_address, uint16_t reg_data)
{
 
  uint8_t reg_data_high = reg_data >> 8;
  uint8_t reg_data_low = reg_data;
  SPI_PORT = (1<<SS); /* Pull the slave select line low to start the transmission */

  /* 3 SPI Bursts for one transaction */
  temp = SPI_SingularTransaction(reg_address);
  temp = SPI_SingularTransaction(reg_data_high);
  temp = SPI_SingularTransaction(reg_data_low);
  SPI_PORT = (0<<SS); /* Pull the slave select line high to end the transaction */
}
void SPIDrvRead(uint8_t reg_address)
{
  reg_address |= 0x80;                         /* set MSB to 1 for read access*/
  SPI_PORT = (1<<SS);
  temp = SPI_SingularTransaction(reg_address);
  Rx_SPI[0] = SPI_SingularTransaction(0xFF);   /* Read the received 16 bit data in Rx_SPI */
  Rx_SPI[1] = SPI_SingularTransaction(0xFF);
 
  SPI_PORT = (0<<SS);
}
void Init_MC13192()
{
    SPIDrvWrite(0x11,0x80FF);   /* Eliminate Unlock Conditions due to L01 */
    SPIDrvWrite(0x1B,0x8000);   /* Disable TC1. */
    SPIDrvWrite(0x1D,0x8000);   /* Disable TC2. */
    SPIDrvWrite(0x1F,0x8000);   /* Disable TC3. */
    SPIDrvWrite(0x21,0x8000);   /* Disable TC4. */
    SPIDrvWrite(0x07,0x0E00);   /* Enable CLKo in Doze */
    SPIDrvWrite(0x0C,0x0300);   /* IRQ pull-up disable. */
    SPIDrvRead(0x25);           /* Sets the reset indicator bit */
    SPIDrvWrite(0x04,0xA08D);   /* New cal value */
    SPIDrvWrite(0x08,0xFFF7);   /* Preferred injection */
    SPIDrvWrite(0x05,0x8351);   /* Acoma, TC1, Doze, ATTN masks, LO1, CRC */
    SPIDrvWrite(0x06,0x4720);   /* CCA, TX, RX, energy detect */
    /* Read the status register to clear any undesired IRQs. */
    SPIDrvRead(0x24);           /* Clear the status register, if set */
    //gu8RTxMode = IDLE_MODE;   /* Update global to reflect MC13192 status */
}
void main()
{
        uint8_t reg;
        delay_count = F_CPU/4000;
        reg = 0x30;  /* BER_Enable register. The default register value after reset is 0x0004*/
   
        ZB_Reset();
        SPI_MasterInit(); /*Initialize the MCU SPI port*/
        Init_MC13192();
      
       SPIDrvRead(reg);
  
 asm volatile ("nop" : : );
  
   
}

 
Labels (1)
0 Kudos
4 Replies

547 Views
bobbyAIR
Contributor I
void SPIDrvRead(uint8_t reg_address)
{
  reg_address |= 0x80;                         /* set MSB to 1 for read access*/
  SPI_PORT = (1<<SS);
  temp = SPI_SingularTransaction(reg_address);
  Rx_SPI[0] = SPI_SingularTransaction(0xFF);   /* Read the received 16 bit data in Rx_SPI */
  Rx_SPI[1] = SPI_SingularTransaction(0xFF);
 
  SPI_PORT = (0<<SS);
}

This won't work.
First to select device as a slave You have to put Slave Select pin LOW not HIGH.
Second SPI_PORT = (1<<SS); sets all pins on PORTB LOW and SS pin HIGH.
The function should look more like this

void SPIDrvRead(uint8_t reg_address)
{
  reg_address |= 0x80;                         /* set MSB to 1 for read access*/
  SPI_PORT &= ~(1<<SS);
  temp = SPI_SingularTransaction(reg_address);
  Rx_SPI[0] = SPI_SingularTransaction(0xFF);   /* Read the received 16 bit data in Rx_SPI */
  Rx_SPI[1] = SPI_SingularTransaction(0xFF);
 
  SPI_PORT |= (1<<SS);
}

Notice that to set bit in some register ( lets sai PA2 in PORTA ) you hawe to write
PORTA |= (1<<PA2) if You dont want to chainge any other bits in that register. To clear bit Yoy hawe to use PORTA &=~(1<<PA2) to not change other bits
0 Kudos

547 Views
Ravs
Contributor I
Well, thank you Bobby. I have incorporated those changes. But do we need to initialize all the MC13192 registers before we can read some?
 
What i have done in my code is that, after initializing my SPI interface on the MCU(AT90CAN128) side, i RESET my MC13192 transceiver. I can see the clocks on my oscilloscope once i release the RESET line to high.
 
As the transceiver's reference manual says, after RESET the Transceiver goes to the Idle condition and the registers are set to there default values. So, through my code , i am trying to read some of the registers by sending register address on the MOSI. But for each register address, what i get on MISO is 0x0000. Here is my code for the same:
 
#include<avr/io.h>
#include<avr/interrupt.h>
#include<inttypes.h>
#define F_CPU 16000000L   /* MCU Clock Speed */
#define SPI_PORT PORTB    /* Define SPI port */
#define SS PB0            /* The SPI Slave Select Bit */
uint16_t u16Rx_SPI = 0x1234; /* Initial Values. They have no meaning in perticular */
uint16_t delay_count;
uint8_t u8temp = 0x65;      /* Initial Values. They have no meaning in perticular */

/* RESET delay routine */
void delay(uint8_t ms)
{
   uint16_t cnt;
   asm volatile (
   "\n"
   "L_dl1%=:" "\n\t"
   "mov %A0, %A2" "\n\t"
   "mov %B0, %B2" "\n"
   "L_dl2%=:" "\n\t"
   "sbiw %A0, 1" "\n\t"
   "brne L_dl2%=" "\n\t"
   "dec %1" "\n\t"
   "brne L_dl1%=" "\n\t"
   : "=&w" (cnt)
   : "r" (ms), "r" (delay_count)
   );
}

void AssertSPI()
{
    SPI_PORT |= (0<<SS);
}

void DeAssertSPI()
{
    SPI_PORT |= (1<<SS);
}

void MC13192_Reset()
{

    DDRD  |= (1 << DDD7) | (1 << DDD1) | (1<<DDD0); //Set Direction register as output
    PORTD |= (0 << PD7); //Resetting the ZB chip by pulling low RST pin
   
    delay(10);
  
    PORTD |= (1 << PD7); //Set to normal mode ZB chip to pulling high
    delay(25);
}
void SPI_MasterInit(void)
{
  
  
     /* Set MOSI and SCK and SS as output */
     DDRB |= (1<<DDB2)|(1<<DDB1)|(1<<DDB0);
     /* Enable SPI, Master, set clock rate fck/16 */
     SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);
 
  
}
uint8_t SPI_SingularTransaction(uint8_t data)
{
    SPDR = data;
    while(!(SPSR &(1<<SPIF)));
    return SPDR;
}
void SPIDrvRead(uint8_t reg_address)
{
    reg_address |= 0x80; /* Set MSB for read access */
    AssertSPI();
    u8temp = SPI_SingularTransaction(reg_address);  /* Temp clear's the MISO initial data */
    u16Rx_SPI = SPI_SingularTransaction(0x99);         /* 0x99 is the dummy data */
    u16Rx_SPI = (Rx_SPI<<8);
    u16Rx_SPI |= SPI_SingularTransaction(0x99);        /* 0x99 is the dummy data */
 
  DeAssertSPI();
}
 
void main()
{
        delay_count = F_CPU/4000;
 
        SPI_MasterInit();
        ZB_Reset();
 
        SPIDrvRead(0x0F);
        SPIDrvRead(0x10);
        SPIDrvRead(0x12);
        SPIDrvRead(0x1B);
 
        while(1);
}
0 Kudos

547 Views
bobbyAIR
Contributor I
Still You do not select modem as a SPI slave. You have to change AssertSPI() to
void AssertSPI(){
    SPI_PORT &= ~(1<<SS);
}
Notice that:
1<<SS is the same like 00000000 and if SS (PB0) pin is high ( it shoud be on startup ) your instruction doesnt do anything because
xxxxxxx1 | 00000000 = xxxxxxx1 ( where x is 0 or 1 )
If You use ~(1<<SS) You will get 11111110 and instruction
xxxxxxx1 & 11111110 = xxxxxxx0 wil do what you want.
Next in SPI_master_init() You shoud put SS pin High as default state because in this place You put this pin as uotput but it remains low becase its is its default state ( after reset all ports registers are 0x00 )
so you have to put
SPI_PORT |= (1<<SS) or deassertSPI() function it it
Also you can write assert and deassert functions as inline functions
And in SPI_Drv_Read ther is instruction between two SPI tranzactions but it is better to not put anything there because it can brake transaction I think better is to do something like that

uint16_t SPIDrvRead(uint8_t reg_address)
{
   uint8_t msb,lsb;
    reg_address |= 0x80; /* Set MSB for read access */
    AssertSPI();
    SPI_SingularTransaction(reg_address);  /* Temp clear's the MISO initial data */
    msb = SPI_SingularTransaction(0x99);         /* 0x99 is the dummy data */
    lsb= SPI_SingularTransaction(0x99);        /* 0x99 is the dummy data */
    DeAssertSPI();
    return (msb<<8)|lsb;
}


0 Kudos

547 Views
GusPS
Contributor I

Anteoo System have a nice open source sample to use as starting point: http://www.anteeo.se/zigbee.php

 

I've taken that code and doing some changes to implement the Packet Mode and a version not so dependant on the ISR. If anyone is interested to see that code and/or help with development, let me know.

0 Kudos