Forum: Mikrocontroller und Digitale Elektronik M16C SPI


von Til (Gast)


Lesenswert?

Moin,

ich möchte an meinen M16C26 SPI nutzen, nur finde ich leider nichts im
Datenblatt zu SPI, nur Informationen zum clock synchronous Mode, was ja
eigentlich SPI ist.

Hat jemand schon mal SPI mit dem M16C programmiert und dabei die
seriellen Funktionen des M16C genutzt (kein Portgeklapper!)?

Anregungen oder Codebeispiele helfen mir weiter!!

Danke.

von Sascha (Gast)


Lesenswert?

Hi,

so läuft es bei mir:

//********************************************************************** 
********
//   SPI-Ansteuerung MAX186
//  Basiernd auf RENESAS M16C62 Using the M16C62 UART for SPI
Communication
//
//   /CS = P73
//   DIN = P70/TXD2  !Bei TXD2 unbedingt ext. PullUp!
//   DOUT = P71/RXD
//  SCLK = P72/CLK
//  SSTRB = P74
//********************************************************************** 
********

void init_spi(void)
{
  pur1=0xff;
    CS_MAX186_DDR = 1;  // Change CHIP_SELECT port to output
  CS_MAX186 = 1;    // Bring CHIP_SELECT high
  SSTRB_DDR = 0;
    /* configure UART2 for SPI */
    u2c0   = 0x91;
  u2c1   = 0x00;    /* no data reverse, rx & tx disabled */
  u2brg  = 5;      // 2MHz SPI-CLK
  ckpol_u2c0 = 0;    // Clock polarity, bit 6 of U2C0 register
    ckph_u2smr3 = 0;  // Clock phase, bit 1 of U2SMR3 register.
    u2mr   = 0x01;    /* synchronous mode, internal clock, no reverse*/
}

unsigned char SPI_send_receive(unsigned char cmd)
{
  unsigned char i;
  while( !ti_u2c1 );      // Ensure transmit buffer is empty
    while( !txept_u2c0 );    // Ensure transmit register is empty
  i = u2rbl;           // Read receive buffer to empty it
    re_u2c1 = 1;        // Enable rx
    te_u2c1 = 1;        // Enable tx
    u2tbl = cmd;    // Transmit data
    while( !ri_u2c1 );    // Wait for rx to be completed
    i = u2rbl;    // Copy received data to buffer
    re_u2c1 = 0;        // Disable rx
    te_u2c1 = 0;        // Disable tx
  return i;
}

unsigned int RD_MAX186(unsigned char cmd)
{
  unsigned char RB1,RB2,RB3=0;
  unsigned int AD_WERT=0;
  CS_MAX186 = 0;
  RB1=SPI_send_receive(cmd);    // Kanal Wahl
  CS_MAX186 = 1;
  while(!SSTRB);          // Warte bis Wandlung fertig
  CS_MAX186 = 0;
  RB2=SPI_send_receive(0x00);
  RB3=SPI_send_receive(0x00);
  CS_MAX186 = 1;
  AD_WERT=(RB2<<8)|RB3;
  AD_WERT>>=3;
  return AD_WERT;
}


Mfg Sascha

von Torsten (Gast)


Lesenswert?

Na dann hier auch mal mein code (für SIO3):

Init:
  // SIO 3 (SPI Interface)
  PRCR|= 0x01 | 0x02 | 0x04;  // disable write protection again
  S3C =  //1 |  //  f/8 as clock source
      2 |    //  f/32 as source
      //4 |   //  output is disabled
      8 |    //  Sout as Output , CLK function
      //16|   //  CLK polarity
      //32 |   //  transfer MSB first
      64 ;  //  use internal sync. clock

  // SPI Baudrate Divisor
  S3BRG= 0xFF;

  // S3 Interrupt Control Register
  S3IC = 0x00;  //INTERRUPTPRIO_SPI;

  //enable protection
  PRCR &= ~(0x01|0x02|0x04);

Und die Schreibfunktion

unsigned char SPI_WriteByte(unsigned char Byte)
{
  int timeout = MAX_SPI_WAIT_TOUT;
  S3IC &= ~0x08;
  S3TRR = Byte;
        do{__no_operation();}
  while((!(S3IC & 0x08)) && (timeout--));
  if(timeout<=0)
  return 0;
    else
  return S3TRR;

}

von Til (Gast)


Lesenswert?

Danke erstmal!!

Ich hoffe das passt auch so für meinen M16C26, muss ich mal die SFRs
vergleichen.

Was ich beim M16C noch nicht ganz verstehe, normalerweise habe ich doch
bei SPI
MOSI
MISO
CS
CLK

macht der M16C das CS selbst oder muss ich da einen Portpin bedienen?

von Til (Gast)


Lesenswert?

Ich muss dazu sagen, das ich auf den SPI Kram, der über die Uart2 Pins
läuft, festgelegt bin. D.h. für mein Verständnis:

Pin 70 MOSI
Pin 71 MISO
Pin 72 CS
Pin 73 CLK

im Manual finde ich nix zu SPI, ist dann der synchrone Serial Mode das
gleiche wie SPI?

von Sascha (Gast)


Lesenswert?

Hi Til,

siehe doch mal oben in meinem Beispiel.

CS   = /CS = P73
MOSI = DIN = P70/TXD2  !Bei TXD2 unbedingt ext. PullUp!
MISO = DOUT = P71/RXD
SCLK =  SCLK = P72/CLK

P74 habe ich für den A/D MAX186 genutzt, ob festzustellen, ob Wandlung
fertig ist. SPI ist der synchrone Modus.

Mfg Sascha

von Til (Gast)


Lesenswert?

Ok, dann hab ich es doch richtig verstanden, bei mir funzt es halt noch
nicht, deshalb zweifel ich erstmal alles an und zu aller erst mein
Verständis ;-).

von Sascha (Gast)


Lesenswert?

Poste doch mal deinen Code.

Mfg Sascha

von Til (Gast)


Lesenswert?

Hier mein Code:


/*********************************************************************** 
***********************************************************/
/*! @fn               void spi_init(void)
    @brief
    @param[in]
    @param[out]
    @param[in,out]
    @return
    @retval

    Diese Funktion

    @warning
    @sa
************************************************************************ 
***********************************************************/
void spi_init(void)
{
  M_DEBUG_PUTS("spi init\r\n");


  M_SET_MOSI_INPUT();
  M_SET_MISO_OUTPUT();
  M_SET_CS_INPUT();
  M_SET_CLK_INPUT();



  /* configure UART2 for SPI */
  U2C0   = 0x91;
  U2C1   = 0x00;      /* no data reverse, rx & tx disabled
*/
  U2BRG  = 5;         /* 2MHz SPI-CLK
*/
  U2C0  &= ~0x20;
  U2SMR3 &= ~0x01;
  U2MR   = 0x01;      /* synchronous mode, internal clock, no reverse
*/
}


/*********************************************************************** 
***********************************************************/
/*! @fn               void spi_init(void)
    @brief
    @param[in]
    @param[out]
    @param[in,out]
    @return
    @retval

    Diese Funktion

    @warning
    @sa
************************************************************************ 
***********************************************************/
u8_t _spiTxRx(u8_t ucCmd)
{
  u8_t i;

#if 0
  while( (U2C1 & 0x02) != 0x02 );         /* Ensure transmit buffer is
empty      */
    while( (U2C0 & 0x08) != 0x08 );       /* Ensure transmit register
is empty    */

  M_DEBUG_PUTS("buffer empty\r\n");

  i = U2RBL;                              /*   Read receive buffer to
empty it    */

  U2C1 |= 0x05;                           /* Enable Tx and Rx
          */

  M_DEBUG_PUTS("tx\r\n");

  U2TB = ucCmd;                           /* Transmit data
          */
#endif
  M_DEBUG_PUTS("wait for data\r\n");
  while( (U2C1 & 0x08) != 0x08 );         /* Wait for rx to be
completed          */
  M_DEBUG_PUTS("rx\r\n");

  i = U2RB;                               /* Copy received data to
buffer         */
  U2C1 &= ~0x05;                          /* Disable Tx and Rx
          */

  return (i);
}




Mein M16C soll als Slave arbeiten und Daten empfangen, die ein XScale
an Ihn sende. Mein XScale sendet die ganze Zeit Daten über SPI.

von Til (Gast)


Lesenswert?

U2MR   = 0x09;      /* synchronous mode, external clock, no reverse */

muss eher so sein, ich muss doch externe clock nehmen, also quasi das
CLK vom XScale, das dann über Pin23 reinkommt.

von Sascha (Gast)


Lesenswert?

Was sind dies den für Funktionen?

" M_SET_MOSI_INPUT();
  M_SET_MISO_OUTPUT();
  M_SET_CS_INPUT();
  M_SET_CLK_INPUT(); "

Mfg Sascha

von Til (Gast)


Lesenswert?

/* Makros
************************************************************************ 
*************************************************/
#define M_SET_MOSI_INPUT()            P7D &= ~C_MOSI_PIN
#define M_SET_MOSI_OUTPUT()           P7D |= C_MOSI_PIN
#define M_SET_MISO_INPUT()            P7D &= ~C_MISO_PIN
#define M_SET_MISO_OUTPUT()           P7D |= C_MISO_PIN
#define M_SET_CS_INPUT()              P7D &= ~C_CS_PIN
#define M_SET_CS_OUTPUT()             P7D |= C_CS_PIN
#define M_SET_CLK_INPUT()             P7D &= ~C_CLK_PIN
#define M_SET_CLK_OUTPUT()            P7D |= C_CLK_PIN

#define M_SET_MOSI_HIGH()             P7 |= C_MOSI_PIN
#define M_SET_MOSI_LOW()              P7 &= ~C_MOSI_PIN
#define M_IS_MOSI_HIGH()              ((P7 & C_MOSI_PIN) ==
C_MOSI_PIN)
#define M_SET_MISO_HIGH()             P7 |= C_MISO_PIN
#define M_SET_MISO_LOW()              P7 &= ~C_MISO_PIN
#define M_IS_MISO_HIGH()              ((P7 & C_MISO_PIN) ==
C_MISO_PIN)
#define M_SET_CS_HIGH()               P7 |= C_CS_PIN
#define M_SET_CS_LOW()                P7 &= ~C_CS_PIN
#define M_SET_CLK_HIGH()              P7 |= C_CLK_PIN
#define M_SET_CLK_LOW()               P7 &= ~C_CLK_PIN

von Til (Gast)


Lesenswert?

Hier noch mal mein aktueller Code:

void spi_init(void)
{
  M_DEBUG_PUTS("spi init\r\n");

  /* configure UART2 for SPI */
  U2C0    = 0x41;       /* rec data at falling edge, lsb first
  */
  U2C1    = 0x00;       /* no data reverse, rx & tx disabled
  */
  U2BRG   = 5;          /* 2MHz SPI-CLK
  */
  U2SMR3  &= ~0x02;
  U2MR    = 0x09;       /* synchronous mode, external clock, no reverse
  */
}

u8_t _spiTxRx(u8_t ucCmd)
{
  u8_t i;

  U2TB = 0x00;                            /* Write dummy Byte in TX
          */
  i = U2RBL;                              /* Read receive buffer to
empty it      */
  U2C1 |= 0x05;                           /* Enable Tx and Rx
          */

  M_DEBUG_PUTS("wait for data\r\n");
  while ( (U2C1 & 0x08) != 0x08 );        /* Wait for rx to be
completed          */

  i = U2RB;                               /* Copy received data to
buffer         */

  M_DEBUG_PUTS("rx=\r\n");
  M_DEBUG_PUTU32(i);
  M_DEBUG_PUTS("\r\n");

  U2C1 &= ~0x05;                          /* Disable Tx and Rx
          */

  return (i);
}

von Sascha (Gast)


Lesenswert?

Also als SPI-Master brauchst du solche Makro`s definitiv nicht. Ich
glaube auch nicht, das als Slave dies nötig ist.
Makro #define M_SET_CLK_INPUT()             P7D &= ~C_CLK_PIN
ist, sofern ich das Datenblatt verstehe, nötig. Was genau funktioniert
denn nicht? Wenn das empfangen geht, und das senden nicht, ext. PullUp
an P72 vergessen?

Mfg Sascha

von Til (Gast)


Lesenswert?

Ähmmm.... hab jetzt den Fehler gefunden... naja, wenn die Adressen im
SFR Header File nicht stimmen (bzw. für M16C26 nicht stimmen, die
Adressen im Header File waren für den 6N4), dann beschreibt man wohl
nicht so direkt die Register..... ;-)

Danke nochmal an alle!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.