Hi everyone,
I'm trying to implement simple CAN bus monitoring system where slave read messages from CAN bus and send those bytes to master via SPI protocol.
I have CAN working correctly, however, I'm having problem with SPI.
Currently, I have the master continuously reading data from slave, so master get 0x00 if slave doesn't write anything.
When slave receives a CAN message, it first write a signature byte (character 'S') follows by the message (8-bytes in length) to master.
When master receives character 'S' from slave, it assume that the next 8 bytes should be the message. So the master perform SPI read in the for loop and keep each byte in array.
The problem is that master cannot receive character 'S' sent by slave most of the time.
The reason I use the signature byte to indicate the beginning of message transmission is because I don't know how to implement a blocking SPI read function where the function will not return until slave perform SPI write.
Also since this is a monitoring system, master cannot expect time range in which slave will send the data to it. So I think there might be a synchronization problem between master and slave.
Do you think the blocking SPI read is needed or do you have any other suggestions? Any help would be highly appreciated.
The following is the code:
I simplify the master and slave code to make it easy to read. I've already test the simplified code and it have the same problem as explained above.
Master super loop:
Code:
while (1) {
rx = SPI_read();
if (rx == 'S') {
for (i = 0; i < 8; i++) {
rx = SPI_read();
printf("%02x ", rx);
delay_us(1);
}
printf("\r\n");
}
}
Slave super loop:
Note: To make the code easy to read. I write 0x00 - 0x07 to master instead of the CAN message. The 1 sec delay is to imitate the time range between each CAN message.
Code:
while (1) {
// while(!CAN_read(&message));
SPI_write('S');
for (tx = 0x00; tx < 0x08; tx++) {
SPI_write(tx);
}
delay_ms(1000);
}
SPI function:
Code:
void SPI_write(unsigned char data) {
unsigned char TempVar;
TempVar = SSPBUF; /* Clears BF */
PIR1bits.SSPIF = 0; /* Clear interrupt flag */
SSPCON1bits.WCOL = 0; /* Clear any previous write collision */
SSPBUF = data; /* clock out data */
while(!PIR1bits.SSPIF); /* wait until transmission completed */
PIR1bits.SSPIF = 0; /* clear interrupt flag bit */
}
unsigned char SPI_read(void) {
unsigned char TempVar;
TempVar = SSPBUF; /* Clear BF */
PIR1bits.SSPIF = 0; /* Clear interrupt flag */
SSPBUF = 0x00; /* initiate bus cycle */
while(!PIR1bits.SSPIF); /* wait until cycle complete */
return (SSPBUF); /* return with byte read */
}