I am using the S12XE and the MCP4921 DAC with SPI interface. The MCP4921 works only while in the debugger. If I turn the power off and back on the MCP4921 does not work any more.
I have attached my test project that does the same thing.
Original Attachment has been moved to: DACtest.zip
I do not want to change your communication approach with the SPI device so I only adjusted your code. I hope you will understand.
Could you please test following. I think the issue is the debugger reads SPISR in window and the flag is not cleared in normal mode because there is no SPISR read for the first usage.
//---------------------------- SPI Write Read ------------------------------
uint16_t SpiWriteRead(uint8_t data)
{
uint8_t rxdat;
uint32_t cnt;
if(!SPI1SR_SPTEF) // to be sure everything is OK and we are able to send data, if SPTEF is set there is an error
{
return(0xFF00); // report error the SPTEF flag is set..buffer is not empty
}
(void) SPIDRL; // clear SPIF because of next tests, to be sure it is clear and any parallel action has not set it and
SPI1DRL = data; // both flags are zero before we start to test both of them
cnt=0;
while (0xA0 != (SPI1SR & 0xA0))
{
if(!(++cnt)) // to be sure everything is OK
{
return(0xFF01); // report error in Tx loop
}
}
rxdat = SPI1DRL; // read data and clear SPTIF
return(rxdat);
}
.... and expand your DAC_Main_Output:
void DAC_Main_Output(uint16_t valueDAC)
{
uint8_t temp;
uint32_t err;
DAC_MAIN_CS_active;
temp = (valueDAC >> 8) & 0x0F; // Store valueDAC[11..8] to temp[3..0]
temp |= DAC_CNTL; // Define DAC setting, see MCP4921 datasheet
err =SpiWriteRead(temp);
if(err & 0xFF00)
{
// error has happened
err = (uint8_t) err; // get 8bit code for error
}
else
{
// everything s OK
data = (uint8_t) err;
}
temp = (uint8_t)valueDAC;
err = (void)SpiWriteRead(temp);
if(err & 0xFF00)
{
// error has happened
err = (uint8_t) err; // get 8bit code for error
}
else
{
// everything s OK
data = (uint8_t) err;
}
DAC_MAIN_CS_inactive;
}
Moreover, I suggest you to clear SPI1SR in the function SPIInit...... see (void) SPI1SR; below.
void SpiInit(void)
{
MODRR_MODRR5 = 1; // SPI1 on port H
// For SPI 1
DDRD_DDRD0 = 1; // SS
// DDRH_DDRH3 = 1; // SS is an output on MC // not necessary when SPI is enabled
DDRH_DDRH2 = 1; // CLK is an output on MC // not necessary when SPI is enabled
DDRH_DDRH1 = 1; // MOSI is an output on MC // not necessary when SPI is enabled
//DDRH_DDRH0 = 0; // MISO is an input on MC // not necessary when SPI is enabled
//DDRK_DDRK3 = 0; // Synchronization Input
(void) SPI1SR; // auxiliary read for the firs time
(void) SPI1DRL;
/* SPI0CR1: SPIE=0,SPE=0,SPTIE=0,MSTR=0,CPOL=0,CPHA=0,SSOE=0,LSBFE=0 */
SPI1CR1 = 0x00U; /* Disable the SPI0 module and clearing flags in SPISR register */
/* SPI0CR2: XFRW=0,MODFEN=0,BIDIROE=0,SPISWAI=0,SPC0=0 */
SPI1CR2 = 0x00U;
/* Baud rate divider = (48MHz/96) = 500000Hz or 500Kz = SPI1BR = 00100100 */
SPI1BR = 0x24;
/* SPI0CR1: SPIE=0,SPE=1,SPTIE=0,MSTR=1,CPOL=0,CPHA=0,SSOE=0,LSBFE=0 */
SPI1CR1 = 0x50U;
}
I hope you see what I wanted to say you. If you have any questions do not hesitate to ask.
Best regards,
Ladislav
Hello Ladislav,
I decided to make one change at a time and test. I added (void) SPI1SR; and (void) SPI1DRL; to SpiInit(); and it fixed the problem in DACtest and my project that uses the same code.
Thank you..........
Any idea why the a read was needed when not in the debugger ?
Ray.
Hi
Reading SPISR in SPIinit() always was required since HC11 times. Without it MODF flag could sometimes get set, and bad things are happening then. MODF is cleared by reading SPISR followed by write to SPICR1.
Edward