Advertisement
meerweten

I2C Slave

Apr 22nd, 2020
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.41 KB | None | 0 0
  1.  
  2. #include <xc.h>
  3. #include "Libraries/Global/conf.h"
  4. #include "Libraries/I2C/I2C.h"
  5. #include "Libraries/Relais/Relais.h"
  6.  
  7.  
  8. struct Relais _relais;
  9.     char data = 0;
  10.     char data2 = 0;
  11.  
  12.  
  13. void System_INIT();
  14. void OSC_INIT();
  15. void Pinning_INIT();
  16.  
  17. /*
  18.  *
  19.  * Main Function
  20.  *
  21.  */
  22.  
  23. void main(void) {
  24.     System_INIT();                              //Call the System Initialisation function
  25.  
  26.     while(1)
  27.     {
  28.         Relais_Turn_ON_OFF(_relais.value);      //Call Relais function, turns on/off relais
  29.         _data = Relais_Validate_State();
  30.     }
  31.     return;
  32. }
  33.  
  34. /*
  35.  * Name: ISR
  36.  * Function: Interrupt function, call all other interupt functions
  37.  * Input: None
  38.  * Output: None
  39.  */
  40.  
  41. void __interrupt() ISR()
  42. {
  43.     data = I2C_Slave_Read(&data2);          //call the interrupt for I2C bus
  44.     __delay_us(1);                          //dummy delay
  45.     if (data2)                              //check if received info is data or address
  46.     {
  47.         _relais.value = data;               //transfer data to relais struct
  48.     }
  49. }
  50.  
  51. /*
  52.  *
  53.  * Init Functions
  54.  *
  55.  */
  56.  
  57. void System_INIT()
  58. {
  59.     OSC_INIT();                             //Init clock
  60.     Pinning_INIT();                         //init Pinning
  61.     Relais_INIT();                          //init relais pinning
  62.     _relais.value = 0xff;                   //initialize relais values (should be 0, but test board has inverted logic)
  63.     I2C_Init(I2C_SLAVE, 0x2A);              //Init I2C
  64. }
  65.  
  66. void OSC_INIT()
  67. {
  68.     OSCCON1bits.NOSC = 0b110;               // = HFINTOSC
  69.     OSCCON1bits.NDIV = 0b0000;              // Clock divider = 1
  70.     OSCFRQbits.HFFRQ = 0b1000;              // HFINTOSC Frequency selection bits: 64 Nominal Freq (MHz)
  71.     OSCENbits.HFOEN = 0b1;                  // HFINTOSC is explicitly enabled, operating as specified by OSCFRQ
  72. }
  73.  
  74. void Pinning_INIT()
  75. {
  76.     _GPIO_LOW(IO_LED);                      //turn test led low
  77.     _GPIO_OUT(IO_LED);                      //enable output for led
  78.     _GPIO_DIGITAL(IO_LED);                  //set output to digital
  79.  
  80. }
  81.  
  82. void I2C_Init(uchar master, uchar clock_speed_addres)
  83. {    
  84.     PPSLOCK = 0x55;
  85.     PPSLOCK = 0xAA;
  86.     PPSLOCKbits.PPSLOCKED = 0;
  87.     SSP1CLKPPS = 0x13;      // MSSP1:SCL1->RC3;
  88.     SSP1DATPPS = 0x14;      // MSSP1:SDA1->RC4;
  89.     RC3PPS = 0x0F;          // RC3->MSSP1:SCL1;    
  90.     RC4PPS = 0x10;          // RC4->MSSP1:SDA1;  
  91.    
  92.     PPSLOCK = 0x55;
  93.     PPSLOCK = 0xAA;
  94.     PPSLOCKbits.PPSLOCKED = 1;
  95.     _GPIO_DIGITAL(IO_SCL);          //Make digital
  96.     _GPIO_DIGITAL(IO_SDA);
  97.  
  98.     _GPIO_LOW(IO_SCL);              // make low
  99.     _GPIO_LOW(IO_SDA);
  100.     _GPIO_IN(IO_SCL);               //Make tristate
  101.     _GPIO_IN(IO_SDA);
  102.     TRISCbits.TRISC3 = 0b1;
  103.     TRISCbits.TRISC4 = 0b1;
  104.     // Analog Select Register
  105.     //  1 Digital Input buffers are disabled
  106.     //  0 ST and TTL input buffers are enabled
  107.     ANSELCbits.ANSELC3 = 0b0;
  108.     ANSELCbits.ANSELC4 = 0b0;
  109.     // Input Level Control Register
  110.     // 1 ST input used for port reads and interrupt-on-change
  111.     // 0 TTL input used for port reads and interrupt-on-change
  112.     INLVLCbits.INLVLC3 = 0b1;
  113.     INLVLCbits.INLVLC4 = 0b1;
  114.     // Slew Rate Control
  115.     //  1 Port pin slew rate is limited
  116.     //  0 Port pin slew at maximum rate
  117.     SLRCONCbits.SLRC3 = 0b0;
  118.     SLRCONCbits.SLRC4 = 0b0;
  119.    
  120. #ifdef testing
  121.     WPUCbits.WPUC3 = 0b1;
  122.     WPUCbits.WPUC4 = 0b1;
  123. #endif
  124.    
  125.     if (master)
  126.     {
  127.         SSP1CON1 = 0b00101000;            //SSP Module as Master
  128.         SSP1CON2 = 0;
  129.         SSP1ADD = (_XTAL_FREQ/(4*clock_speed_addres))-1; //Setting Clock Speed
  130.         SSP1STAT = 0;        
  131.     }
  132.     else
  133.     {
  134.         SSP1STAT = 0x80;    
  135.         SSP1ADD = clock_speed_addres<<1; //Setting address
  136.         SSP1CON1 = 0x36;    //As a slave device
  137.         SSP1CON2 = 0x01;        
  138.         SSP1CON3 = 0b00000110;
  139.         GIE = 1;          //Global interrupt enable
  140.         PEIE = 1;         //Peripheral interrupt enable
  141.         SSP1IF = 0;        //Clear interrupt flag
  142.         SSP1IE = 1;        //Synchronous serial port interrupt enable
  143.         SSP1MSK = 0xFF;
  144.     }
  145. }
  146.  
  147. void I2C_Master_Wait()
  148. {
  149.   while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F)); //Transmit is in progress
  150. }
  151.  
  152. void I2C_Master_Start()
  153. {
  154.   I2C_Master_Wait();    
  155.   SEN1 = 1;             //Initiate start condition
  156. }
  157.  
  158. void I2C_Master_RepeatedStart()
  159. {
  160.   I2C_Master_Wait();
  161.   RSEN1 = 1;           //Initiate repeated start condition
  162. }
  163.  
  164. void I2C_Master_Stop()
  165. {
  166.   I2C_Master_Wait();
  167.   PEN1 = 1;           //Initiate stop condition
  168. }
  169.  
  170. char I2C_Master_Write(unsigned data_byte)
  171. {
  172.   I2C_Master_Wait();
  173.   SSP1BUF = data_byte;         //Write data to SSPBUF
  174.   I2C_Master_Wait();
  175.   return ACKSTAT1;
  176. }
  177.  
  178. uchar I2C_Master_Read(uchar ACK)
  179. {
  180.   unsigned short retVal;
  181.   I2C_Master_Wait();
  182.   RCEN1 = 1;
  183.   I2C_Master_Wait();
  184.   retVal = SSP1BUF;      //Read data from SSPBUF
  185.   I2C_Master_Wait();
  186.   ACKDT1 = (ACK)?0:1;    //Acknowledge bit
  187.   ACKEN1 = 1;          //Acknowledge sequence
  188.   return retVal;
  189. }
  190.  
  191. void I2C_Master_Write_Byte(char address, char data)
  192. {
  193.     I2C_Master_Start();
  194.     I2C_Master_Write(address);
  195.     I2C_Master_Write(data);
  196.     I2C_Master_Stop();
  197. }
  198.  
  199. char I2C_Slave_Read(char *data)
  200. {
  201.     GIE = 0;
  202.     char retVal = 0;
  203.   if(SSP1IF == 1)
  204.   {
  205.     //CKP1 = 0;
  206.       data[0]=0;
  207.  
  208.     if ((SSPOV1) || (WCOL1)) //If overflow or collision
  209.     {
  210.       retVal = SSP1BUF; // Read the previous value to clear the buffer
  211.       SSPOV1 = 0; // Clear the overflow flag
  212.       WCOL1 = 0; // Clear the collision bit
  213.       CKP1 = 1;
  214.     }
  215.  
  216.   if(!SSP1STATbits.D_nA && !SSP1STATbits.R_nW) //If last byte was Address + Write
  217.   {
  218.     retVal = SSP1BUF;
  219.     CKP1 = 1;
  220.     while(BF1);
  221.     //while(!BF1);
  222.    
  223.     //PORTD = ~SSP1BUF;
  224.     //CKP1 = 1;
  225.   }
  226.   else if(SSP1STATbits.D_nA && !SSP1STATbits.R_nW)
  227.   {
  228.     retVal = ~SSP1BUF;
  229.     CKP1 = 1;
  230.     data[0] = 1;
  231.   }
  232.   else if(!SSP1STATbits.D_nA && SSP1STATbits.R_nW) //If last byte was Address + Read
  233.   {    
  234.     SSP1IF = 0;
  235.     retVal = SSP1BUF;
  236.     while(BF1);
  237. //    BF1 = 0;
  238.     SSP1BUF = _data ;
  239.     CKP1 = 1;
  240.     //while(!SSP1IF);
  241.     SSP1IF = 0;
  242.     //while(SSP1STATbits.BF);
  243.     SSP1IF = 0;
  244.     if(ACKSTAT1)
  245.     {        
  246.         SSP1BUF = _data ;
  247.         CKP1 = 1;
  248.         //while(!SSP1IF);
  249.         SSP1IF = 0;
  250.     }
  251.     CKP1 = 1;
  252.     SSP1IF = 0;
  253.   }
  254.  
  255.   SSP1IF = 0;
  256.   }
  257.     SSP1IF  =0;
  258.     GIE = 1;
  259.     return retVal;
  260. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement