Advertisement
HDS

Maple Nonblocking serial receiver up to 115200 baud

HDS
Mar 21st, 2012
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.52 KB | None | 0 0
  1. //Softserial by Joern Heinrich, for ARM Cortex M3 / leflabs maple5.
  2. //featuring a nonblocking software serial input on ARM Cortex M3, using
  3. //an interrupt routine on a pin combined with one of the four general
  4. //hardware timers of the ARM Cortex M3
  5. //Conventions: 8 bit, no parity, one stop bit
  6. //Serial-Input buffer: sizeable
  7.  
  8. //1 cycle = 0.01388888888 µsec @ 72 MHz
  9. //50 cycles    = 0.695  µsec = one digital write / read
  10. //bit duration @ 38400 Baud = 26,06 µsec = 1920 cycles  
  11.  
  12. const unint8 SS_receivePin = 37;     //pin 37 is 5V tolerant
  13. const int SS_bufsize = 256;          //size of input bugffer in bytes  
  14. volatile uint8 SS_INbuf[SS_bufsize]; //input buffer, beeing filled by timercontrol
  15. volatile int   SS_INbitcnt  =  -1;   //bit counter of incoming byte, begins with -1 = stop bit
  16. volatile int   SS_INwritePt =  0;    //writing index pointer on input buffer
  17. volatile int   SS_INreadPt  =  0;    //reading index pointer on input buffer
  18.          int   SS_baud = 38400;      //default Baud rate of input
  19.          int   SS_period;    //duration of one bit
  20. HardwareTimer timerSERin(3); //ARM COrtex M3 leaflabs maple general purpose timer
  21.  
  22.  
  23. void SoftSerSetup(int b){
  24.     SS_baud   = b;             
  25.     SS_period = 1000000 / SS_baud; //Binary modulation, bit rate = baud rate, bitPeriod in µsec
  26.                                    //38400 Baud : 26,042 µs
  27.                                    //2400  Baud : 416,66666 µS
  28.     pinMode(SS_receivePin, INPUT_PULLUP);  //first: stop bit pulls LOW
  29.     timerSERin.pause();
  30.     timerSERin.setMode(2, TIMER_OUTPUT_COMPARE);
  31.     timerSERin.setPeriod(SS_period); // in microseconds
  32.     timerSERin.setCompare(2, timerSERin.getOverflow()-1 ); // Interrupt just before Overflow
  33.     timerSERin.attachInterrupt(2, SS_NextBit);
  34.     timerSERin.refresh();    
  35.     timerSERin.pause();  
  36.     attachInterrupt(SS_receivePin, SS_OnPinChange, FALLING); //SS_receivePin = 37, 5V tolerant
  37. }
  38.  
  39. void SS_OnPinChange(){        //interrupt gets called, when pin goes LOW in start bit
  40.     if (SS_INbitcnt==-1) {    //start bit received, new byte underways  
  41.         SS_INbitcnt++;        // Inbitcnt = 0 which annotates the first and LSB  
  42.         timerSERin.refresh(); // reset to zero
  43.         timerSERin.resume();  // start timer.
  44.         //for all those to which here is lacking the half-Bit-period delay for a "centering"
  45.         // of the first bit read after the start bit, be assured:
  46.         //The interrupt routine overhead, the Timer refresh and resume
  47.         // is well enough to provide a "digital read" set off so far from the next input pin
  48.         // digital level change to perform secure communication at baud rates from 600 baud
  49.         // up to 115200 baud on the ARM Cortex M3 (leflabs maple)
  50.     }
  51. }
  52.  
  53. void SS_NextBit(){ //called by timer interrupt
  54.     uint8 b=0;
  55.     b = digitalRead(SS_receivePin);  //HIGH = 1; LOW = 0  
  56.     switch (SS_INbitcnt){
  57.         case 0: //gather first bit
  58.             SS_INbuf[SS_INwritePt] = b; //resetting the Buffer contetnt to zero or one
  59.             SS_INbitcnt++;          
  60.         break;
  61.         case 1: //collect further bits...
  62.         case 2:
  63.         case 3:
  64.         case 4:
  65.         case 5:
  66.         case 6:
  67.         case 7:
  68.             SS_INbuf[SS_INwritePt] |= (b << SS_INbitcnt++);  //setting appropriate bit          
  69.         break;
  70.         case 8: //stop bit, reset of bit counter for next start bit
  71.             timerSERin.refresh();     //reset to zero
  72.             timerSERin.pause();       //and end working
  73.             SS_INbitcnt = -1;         //input pin interrupt active again
  74.             if (SS_INwritePt>=SS_bufsize-1 ) {
  75.                  SS_INwritePt = 0; //cycling the buffer
  76.             }
  77.             else { SS_INwritePt++;}
  78.         break;        
  79.     }
  80. }
  81.  
  82. int SS_available(){ //yields the number of new bytes in the input buffer
  83.     int i=0;
  84.     if (SS_INwritePt != SS_INreadPt){
  85.         if (SS_INwritePt > SS_INreadPt){
  86.             i = SS_INwritePt-SS_INreadPt;
  87.         }
  88.         else {i = SS_INwritePt + SS_bufsize - SS_INreadPt;}
  89.     }
  90.     else {i=0;}
  91.     return i;    
  92. }
  93.  
  94. char SS_read(){ //reads one byte from the input buffer and "deletes it"
  95.     char b;  
  96.     if (SS_available() > 0) {
  97.         //first read then increment reading index pointer, writing procedure does the same.
  98.         b = SS_INbuf[SS_INreadPt];
  99.         if (SS_INreadPt<SS_bufsize-1) {
  100.             SS_INreadPt++;
  101.         }
  102.         else {
  103.             SS_INreadPt=0;
  104.         }
  105.     }
  106.     else b='#'; //no chars available but read anyway
  107.     return b;
  108. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement