This is related to my previous thread, however now i have problems with reading response from the RAM module (RAM datasheet). I connected the oscilloscope to every pin, and as far as i can tell everything is correct. In the code below i send "0x48" as data to the RAM module and i get that response on the oscilloscope when i try to read it (on the MISO pin), however it doesn't get saved to the "value" variable and nothing is send over UART (if i hard code value as 0x48 it gets send over UART and it's properly displayed in the terminal as "H").
#include "sam.h" #include "includes/USART.h" #define SPI_CLK_FREQ 8000000 #define SPI_BAUD 50000 #define RDMR 5 // Read the Mode Register #define WRMR 1 // Write to the Mode Register #define READ 3 // Read command #define WRITE 2 // Write command #define RSTIO 0xFF // Reset memory to SPI mode #define ByteMode 0x00 // Byte mode (read/write one byte at a time) #define Sequential 0x40 // Sequential mode (read/write blocks of memory) #define DelayTicks(ticks) {volatile uint32_t n=ticks; while(n--);} //takes 8 cycles #define DelayMs(ms) DelayTicks(MS_TO_DLYTICKS(ms)) #define F_CPU 8000000 #define CYCLES_IN_DLYTICKS_FUNC 8 #define MS_TO_DLYTICKS(ms) (uint32_t)(F_CPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0 // Configure SERCOM1 SPI PINS PAD // MOSI PA16 // SCK PA17 // MISO PA19 void init_SPI_tutorial(){ while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE); SERCOM1->SPI.CTRLA.bit.ENABLE = 0; while(SERCOM1->SPI.SYNCBUSY.bit.SWRST); SERCOM1->SPI.CTRLA.bit.SWRST = 1; while(SERCOM1->SPI.CTRLA.bit.SWRST); while(SERCOM1->SPI.SYNCBUSY.bit.SWRST || SERCOM1->SPI.SYNCBUSY.bit.ENABLE); PORT->Group[0].WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG | //Enables the configuration of PINCFG PORT_WRCONFIG_WRPMUX | //Enables the configuration of the PMUX for the selected pins PORT_WRCONFIG_PMUXEN | //Enables the PMUX for the pins PORT_WRCONFIG_PMUX(MUX_PA19C_SERCOM1_PAD3) | //Bulk configuration for PMUX "C" for SERCOM1 PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_INEN | //Enable input on this pin MISO PORT_WRCONFIG_PINMASK((uint16_t)((PORT_PA19) >> 16)); //Selecting which pin is configured PB16 This bit needs to shift to fit the 16 bit macro requirements //Using the WRCONFIG register to bulk configure both PB22 and PB23 for being configured the SERCOM1 SPI MASTER MOSI and SCK pins PORT->Group[0].WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG | //Enables the configuration of PINCFG PORT_WRCONFIG_WRPMUX | //Enables the configuration of the PMUX for the selected pins PORT_WRCONFIG_PMUX(MUX_PA16C_SERCOM1_PAD0) | //Bulk configuration for PMUX PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_PMUXEN | //Enables the PMUX for the pins PORT_WRCONFIG_PINMASK ((uint16_t)((PORT_PA16 | PORT_PA17) >> 16)); //Selecting which pin is configured PM->APBCMASK.reg |= PM_APBCMASK_SERCOM1; //Enable the SERCOM 1 under the PM GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM1_GCLK_ID_CORE) | //Provide necessary clocks to the peripheral GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); while(GCLK->STATUS.bit.SYNCBUSY); //Wait for clock sync SERCOM1->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER| //Configure the Peripheral as SPI Master SERCOM_SPI_CTRLA_DOPO(0); SERCOM_SPI_CTRLA_DIPO(0x3); SERCOM1->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN; //Enable receive on SPI uint16_t BAUD_REG = ((float)SPI_CLK_FREQ / (float)(2 * SPI_BAUD)) - 1; //Calculate BAUD value SERCOM1->SPI.BAUD.reg = SERCOM_SPI_BAUD_BAUD(BAUD_REG); //Set the SPI baud rate SERCOM1->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; //Enable the Sercom SPI while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE); } uint8_t spiSend(uint8_t data){ while(SERCOM1->SPI.INTFLAG.bit.DRE == 0); SERCOM1->SPI.DATA.reg = data; while(SERCOM1->SPI.INTFLAG.bit.RXC == 0); return (uint8_t)SERCOM1->SPI.DATA.reg; } void SetMode(char Mode){ // Select for single or multiple byte transfer uint8_t retval; PORT->Group[0].OUTCLR.reg = PORT_PA18; // set CS pin to output mode retval = spiSend(WRMR); // command to write to mode register retval = spiSend(Mode); // set for sequential mode PORT->Group[0].OUTSET.reg = PORT_PA18; // high } void WriteByte(uint32_t address, uint8_t data_byte) { uint8_t retval; SetMode(ByteMode); // set to send/receive single byte of data PORT->Group[0].OUTCLR.reg = PORT_PA18; // set SPI slave select LOW; retval = spiSend(WRITE); // send WRITE command to the memory chip retval = spiSend((uint8_t)(address >> 16)); // send high byte of address retval = spiSend((uint8_t)(address >> 8)); // send middle byte of address retval = spiSend((uint8_t)address); // send low byte of address retval = spiSend(data_byte); // write the data to the memory location PORT->Group[0].OUTSET.reg = PORT_PA18; //set SPI slave select HIGH } uint8_t ReadByte(uint32_t address) { SetMode(ByteMode); // set to send/receive single byte of data uint8_t retval; PORT->Group[0].OUTCLR.reg = PORT_PA18; // set SPI slave select LOW; retval = spiSend(READ); // send READ command to memory chip retval = spiSend((uint8_t)(address >> 16)); // send high byte of address retval = spiSend((uint8_t)(address >> 8)); // send middle byte of address retval = spiSend((uint8_t)address); // send low byte of address retval = spiSend(0x00); // read the byte at that address //usart_putc(retval); PORT->Group[0].OUTSET.reg = PORT_PA18; // set SPI slave select HIGH; return retval; // send data back to the calling function } int main(void){ SystemInit(); usart_init(); init_SPI_tutorial(); PORT->Group[0].DIRSET.reg = PORT_PA18; // output PORT->Group[0].OUTSET.reg = PORT_PA18; // high PORT->Group[0].OUTCLR.reg = PORT_PA18; // low uint8_t EE_Read_data; PORT->Group[0].OUTCLR.reg = PORT_PA18; //for(;;)spiSend(0xfe); uint8_t value; while (1) { uint8_t data = 0x48; // initialize the data WriteByte(0, data); // now write the data to that value = ReadByte(0); // reads a byte of data at that memory usart_putc(value); } }
Is there an easier way to test if SPI works correctly (i don't have SPI to USB or something like that at the moment)?
Is it because I read it in the spiSend with this two lines?
while(SERCOM1->SPI.INTFLAG.bit.RXC == 0); return (uint8_t)SERCOM1->SPI.DATA.reg;