Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using acan2517 without INT #2

Open
thomasfla opened this issue Jan 31, 2019 · 7 comments
Open

Using acan2517 without INT #2

thomasfla opened this issue Jan 31, 2019 · 7 comments

Comments

@thomasfla
Copy link

Hi @pierremolinaro, nice work on your lib, and his doc!

I was wondering if it was possible to use this library without using the INT interrupt signal. Indeed I plan to connect 8 MCP2517FD, without enough interrupt input available. In my application, I was thinking of pooling each module through SPI to check for the presence of one (or more) CAN frames ready to be read.

Thanks for your work.

@pierremolinaro
Copy link
Owner

pierremolinaro commented Jan 31, 2019 via email

@pierremolinaro
Copy link
Owner

pierremolinaro commented Jan 31, 2019 via email

@thomasfla
Copy link
Author

Great, thank you very much!

I plan to use a Maple Mini (STM32F103RCBT6) with this core https://github.com/stm32duino. If it doesn't work, I think I'll switch to a Teensy.

For the moment I'm waiting for some components to assemble my board. As soon as I can test your library with it, I'll let you know and report here.

By the way, the PCB I'm designing will be open source. It will be used to control a mobile robot.

img_20190204_100556

@pierremolinaro
Copy link
Owner

pierremolinaro commented Feb 6, 2019 via email

@thomasfla
Copy link
Author

Hi pierre,

The lib works out of the box for SMT32 arduino core! (With my setup, I can only tested the polling version..)

I realized that MODIF bit of CiINT register was always active, and I do not understand why... This makes the polling time slower because this register is cleared at each poll call.

Looking with an oscilloscope on CLK line I can see that signe byte SPI transfers are quite far appart from each other. Maybe this is just a STM32 core problem?

Using one buffered SPI transfer for both command and data exchange, i got quite good improvment:

Here are my results with 9Mhz SPI:
Polling 8 MCP2517FD in a loop with

  • standard lib: 1.05kHz
  • standard lib without clearing MODIF: 1.33kHz
  • optimized spi transfer : 1.44kHz
  • optimized spi transfer without clearinf MODIF 1.85kHz

Polling time is critical in my application, but this should also improve CAN frame transfer..

The drawback is that it breaks your 'LEVEL FUNCTION'

Here is the modified functions:

uint32_t ACAN2517::readWordSPI (void) {
    
  #ifndef OPTIMIZED_SPI
    uint32_t result = mSPI.transfer (0) ;
    result |= ((uint32_t) mSPI.transfer (0)) <<  8 ;
    result |= ((uint32_t) mSPI.transfer (0)) << 16 ;
    result |= ((uint32_t) mSPI.transfer (0)) << 24 ;
  #else
    uint32_t result  = 0;
    unsigned char buff[4]={0};
    mSPI.transfer(buff,4);
    result |= ((uint32_t)buff[0]) << 0;
    result |= ((uint32_t)buff[1]) << 8;
    result |= ((uint32_t)buff[2]) << 16;
    result |= ((uint32_t)buff[3]) << 24;
  #endif
  return result ;
}
void ACAN2517::writeByteRegisterSPI (const uint16_t inRegisterAddress, const uint8_t inValue) {
  assertCS () ;
  #ifndef OPTIMIZED_SPI
    writeCommandSPI (inRegisterAddress) ; // Command
    mSPI.transfer (inValue) ; // Data  
  #else  
    unsigned char buff[3]={0};  
    const uint16_t writeCommand = (inRegisterAddress & 0x0FFF) | (0b0010 << 12) ;
    buff[0] = writeCommand >> 8;
    buff[1] = writeCommand & 0xFF;
    buff[2] = inValue;
    mSPI.transfer(buff,3);  
  #endif
  deassertCS () ;
}
uint32_t ACAN2517::readRegisterSPI (const uint16_t inRegisterAddress) {
  assertCS () ;
  #ifndef OPTIMIZED_SPI
    readCommandSPI (inRegisterAddress) ; // Command
    const uint32_t result = readWordSPI () ; // Data
  #else
      const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ;
      unsigned char buff[6]={0};
      buff[0] = readCommand >> 8;
      buff[1] = readCommand & 0xFF;
      uint32_t result  = 0;
      mSPI.transfer(buff,6);
      result |= ((uint32_t)buff[2+0]) << 0;
      result |= ((uint32_t)buff[2+1]) << 8;
      result |= ((uint32_t)buff[2+2]) << 16;
      result |= ((uint32_t)buff[2+3]) << 24;
  #endif
  deassertCS () ;
  return result ;
}

Another improvement to speed up the polling time could be to use the CiVEC register witch is only one byte long...

Maybe some of this is more related to efficiency than polling mode and should motivate to open an other issue?

Best,
Thomas.

@pierremolinaro
Copy link
Owner

pierremolinaro commented Feb 11, 2019 via email

@thomasfla
Copy link
Author

Hi Pierre,

Thanks! BTW, it might be easier to read the code on this commit from my fork : thomasfla@8f0a364

In this commit I also optimized the sending of a CAN frame. This shorten the sending time from 250us to 109us with my 9Mhz SPI on STM32F103.

Some function are not optimized yet like reading a can frame.

About my particular 8CAN setup, I'm considering switching to a teensy 3.6 witch should be faster, connecting the INTs pin to save the polling time, and changing my quartz to a 40Mhz to get 20Mhz SPI.
My project can be checked here https://github.com/thomasfla/8XCAN_FD

Finally, I'm also thinking of using SPI DMA to shorten the blank between SPI bytes transition. That will depend on the Teensy performances.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants