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.
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
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; }
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?
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?
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
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 ;-).
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.
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.
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
/* 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
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); }
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
Ä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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.