/*************************************************************************** * EM430F6137RF900 + CMR3000 + SCA3100 viestien lähetys. * Tämä puoli hoitaa viestien keräämisen antureilta ja lähettää arvot radion * kautta toiselle laudalle. Laudassa on kiinni anturit CMR300 ja SCA3100. Kun radio- * linkki on muodostettu lautojen välille syttyy vihreä ledi. Tämän jälkeen ohjelma jää * odottamaan uutta tietoa antureilta. Anturien arvot luetaan aina kun CMR3000-anturi * antaa keskeytyksen (interrupt), kun tiedot ovat valmiit. Tämän jälkeen luetaan anturien * rekistereistä x, y ja z akselien arvot. Jokaisesta akselista luetaan LSB * (vähiten merkitsevät) ja MSB (eniten merkitsevät) arvot. Arvot lähetetään * radion kautta toiselle laudalle. Punainen ledi menee aina päälle kun uusi * arvo antureilta on valmiina ja menee pois päältä kun viesti on lähetetty * radion kautta eteenpäin. * * Anturien liitännät lautaan: * * Liitännät molemmissa antureissa: * * AVSS/DVSS = CON9 pin 1 * AVDD/DVDD = CON9 pin 5 * MISO = PORT1 pin 6 * MOSI = PORT1 pin 7 * SCK = PORT1 pin 8 * * CMR3000: * CSB = PORT2 pin 8 * INT = PORT2 pin 5 * * SCA3100: * CSB = PORT2 pin 7 */ // LIBRARIES #include "bsp.h" #include "mrfi.h" #include "nwk_types.h" #include "nwk_api.h" #include "cc430x613x.h" #include "bsp_leds.h" // SPI delays #define XTAL 16000000L #define TICKSPERMS (XTAL / 1000 / 5 - 1) #define TICKSPERUS (TICKSPERMS / 1000) #define SPICLOCK 600 //SPI clock = 500kHz #define SPIFRAMEDELAY ((1000 / SPICLOCK) * 6) // SPI interframe delay [us] = 6 * Tsck #define SPICSBDELAY ((1000 / SPICLOCK) / 2) // SCK -> CSB delay [us] = 0.5 * Tsck static void linkTo(void); static uint8_t sRxCallback(linkID_t); static linkID_t sLinkID1 = 0; #define SPIN_ABOUT_A_SECOND NWK_DELAY(1000) char mode=0; // PORT DEFINITIONS #define PORT_CSB_OUT P2OUT #define PORT_CSB_DIR P2DIR //CMR3000 DEFINE #define CMR3000_PORT_INT_IN P2IN #define CMR3000_PORT_INT_OUT P2OUT #define CMR3000_PORT_INT_DIR P2DIR #define CMR3000_PORT_INT_IE P2IE #define CMR3000_PORT_INT_IES P2IES #define CMR3000_PORT_INT_IFG P2IFG #define CMR3000_PORT_INT_VECTOR PORT2_VECTOR #define CMR3000_PIN_INT BIT4 //CMR300 AXIS REG #define CMR3000_X_LSB 0x0C #define CMR3000_X_MSB 0x0D #define CMR3000_Y_LSB 0x0E #define CMR3000_Y_MSB 0x0F #define CMR3000_Z_LSB 0x010 #define CMR3000_Z_MSB 0x11 #define CMR3000_PIN_CSB BIT7 //CMR3000 muuttujat unsigned short CMR3000_x_msb; unsigned short CMR3000_x_lsb; short CMR3000_x_value; unsigned short CMR3000_y_msb; unsigned short CMR3000_y_lsb; short CMR3000_y_value; unsigned short CMR3000_z_msb; unsigned short CMR3000_z_lsb; short CMR3000_z_value; unsigned char CMR3000_Data; #define CTRL 0x02 #define RESET 0x80 // Set device in reset #define INT_LEVEL_LOW 0x40 // INT active high #define I2C_DIS 0x10 // I2C disabled #define MODE_80 0x06 // Measurement mode BW=80 Hz // SCA3100 init // SCA3100 AXIS REG #define SCA3100_X_LSB 0x04 #define SCA3100_X_MSB 0x05 #define SCA3100_Y_LSB 0x06 #define SCA3100_Y_MSB 0x07 #define SCA3100_Z_LSB 0x08 #define SCA3100_Z_MSB 0x09 #define SCA3100_PIN_CSB BIT6 //SCA3100 muuttujat unsigned short SCA3100_x_msb; unsigned short SCA3100_x_lsb; short SCA3100_x_value; unsigned short SCA3100_y_msb; unsigned short SCA3100_y_lsb; short SCA3100_y_value; unsigned short SCA3100_z_msb; unsigned short SCA3100_z_lsb; short SCA3100_z_value; //SPI init #define TX_BUFFER UCA0TXBUF #define RX_BUFFER UCA0RXBUF #define SPI_CTL0 UCB0CTL0 #define SPI_CTL1 UCB0CTL1 #define SPI_BR0 UCB0BR0 #define SPI_BR1 UCB0BR1 //CMR3000 FUNCTION PROTOTYPES unsigned char CMR3000_ReadRegister(unsigned char Address); unsigned char CMR3000_WriteRegister(unsigned char Address, unsigned char Data); //SCA3100 FUNKTION PROTOTYPES unsigned char SCA3100_ReadRegister(unsigned char Address); //COMMON FUNKTION PROTOTYPES unsigned short realValues(unsigned short values); void wait_ms(unsigned short ms); void wait_us(unsigned short us); void Init_CMR3000_SCA3100(); void Init_CMR3000(); void Init_SCA3100(); void Read_CMR3000_SCA3100(); void Read_CMR3000(); void Read_SCA3100(); // Tehdään tarvittavat alustukset ja muodostetaan linkki toiseen lautaan void main(void) { BSP_Init(); // laudan alustus SMPL_Init(sRxCallback); // radion ja SimpliciTI protokollan alustus wait_ms(100); while(1) { linkTo(); // muodostetaan yhteys toisen laudan kanssa ja jäädään odottamaan CMR3000 anturin interruptia } } // Antureiden alustus void Init_CMR3000_SCA3100() { WDTCTL = WDTPW+WDTHOLD; // sammuta watchdog timer UCSCTL5 |= DIVS_3; PMAPPWD = 0x02D52; // hanki kirjoitusoikeudet porttitaulukon registereihin P1MAP6 = PM_UCA0SIMO; // UCA0SIMO lähtö P1.6 (portti 1, pinni 6) P1MAP5 = PM_UCA0SOMI; // UCA0SOMI lähtö P1.5 (portti 1, pinni 5) P1MAP7 = PM_UCA0CLK; // UCA0CLK lähtö P1.7 (portti 1, pinni 7) P2REN |= BIT4; // ota käyttöön sisäinen vastus P2.2 Enable P1.4 internal resistance P2OUT |= BIT4; // Set P1.4 as pull-Up resistance P2IE |= BIT4; // interrupt päällä P1.4 P2IES |= BIT4; // P1.4 Hi/Lo edge P2IFG &= ~BIT4; // P1.4 IFG cleared PORT_CSB_DIR |= CMR3000_PIN_CSB; PORT_CSB_OUT |= CMR3000_PIN_CSB; // otetaan CMR3000 pois käytöstä PORT_CSB_DIR |= SCA3100_PIN_CSB; PORT_CSB_OUT |= SCA3100_PIN_CSB; // otetaan SCA3100 pois käytöstä P1DIR |= BIT5 + BIT6 + BIT7; // asettaa portin 1, pinnit 6, 7 ja 8 lähdöiksi P1SEL |= BIT5 + BIT6 + BIT7; // avaa portin 1, pinnit 6, 7 ja 8 UCA0CTL1 |= UCSWRST; // Resetoi USCI moduulin UCA0CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB; // valitaan: UCMST = masterin valinta, UCSYNC = valitaan SPI mode, // UCCKPH = kellon vaihe 0x80, UCMSB = MSB ensin UCA0MCTL = 0; // ei modulointia UCA0CTL1 |= UCSSEL1; // SMCLK, USCI 0 Clock Source Select 1 SPI_BR0 = 0x04; // Low byte of division factor for baud rate (500kHz) SPI_BR1 = 0x00; // High byte of division factor for baud rate UCA0CTL1 &= ~UCSWRST; // alustetaan USCI } void Init_CMR3000() { WDTCTL = WDTPW+WDTHOLD; // sammuta watchdog timer UCSCTL5 |= DIVS_3; PMAPPWD = 0x02D52; // hanki kirjoitusoikeudet porttitaulukon registereihin P1MAP6 = PM_UCA0SIMO; // UCA0SIMO lähtö P1.6 (portti 1, pinni 6) P1MAP5 = PM_UCA0SOMI; // UCA0SOMI lähtö P1.5 (portti 1, pinni 5) P1MAP7 = PM_UCA0CLK; // UCA0CLK lähtö P1.7 (portti 1, pinni 7) P2REN |= BIT4; // ota käyttöön sisäinen vastus P2.2 Enable P1.4 internal resistance P2OUT |= BIT4; // Set P1.4 as pull-Up resistance P2IE |= BIT4; // interrupt päällä P1.4 P2IES |= BIT4; // P1.4 Hi/Lo edge P2IFG &= ~BIT4; // P1.4 IFG cleared PORT_CSB_DIR |= CMR3000_PIN_CSB; PORT_CSB_OUT |= CMR3000_PIN_CSB; // otetaan CMR3000 pois käytöstä P1DIR |= BIT5 + BIT6 + BIT7; // asettaa portin 1, pinnit 6, 7 ja 8 lähdöiksi P1SEL |= BIT5 + BIT6 + BIT7; // avaa portin 1, pinnit 6, 7 ja 8 UCA0CTL1 |= UCSWRST; // Resetoi USCI moduulin UCA0CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB; // valitaan: UCMST = masterin valinta, UCSYNC = valitaan SPI mode, // UCCKPH = kellon vaihe 0x80, UCMSB = MSB ensin UCA0MCTL = 0; // ei modulointia UCA0CTL1 |= UCSSEL1; // SMCLK, USCI 0 Clock Source Select 1 SPI_BR0 = 0x04; // Low byte of division factor for baud rate (500kHz) SPI_BR1 = 0x00; // High byte of division factor for baud rate UCA0CTL1 &= ~UCSWRST; // alustetaan USCI } void Init_SCA3100() { WDTCTL = WDTPW+WDTHOLD; // sammuta watchdog timer UCSCTL5 |= DIVS_3; PMAPPWD = 0x02D52; // hanki kirjoitusoikeudet porttitaulukon registereihin P1MAP6 = PM_UCA0SIMO; // UCA0SIMO lähtö P1.6 (portti 1, pinni 6) P1MAP5 = PM_UCA0SOMI; // UCA0SOMI lähtö P1.5 (portti 1, pinni 5) P1MAP7 = PM_UCA0CLK; // UCA0CLK lähtö P1.7 (portti 1, pinni 7) PORT_CSB_DIR |= SCA3100_PIN_CSB; PORT_CSB_OUT |= SCA3100_PIN_CSB; // otetaan SCA3100 pois käytöstä P1DIR |= BIT5 + BIT6 + BIT7; // asettaa portin 1, pinnit 6, 7 ja 8 lähdöiksi P1SEL |= BIT5 + BIT6 + BIT7; // avaa portin 1, pinnit 6, 7 ja 8 UCA0CTL1 |= UCSWRST; // Resetoi USCI moduulin UCA0CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB; // valitaan: UCMST = masterin valinta, UCSYNC = valitaan SPI mode, // UCCKPH = kellon vaihe 0x80, UCMSB = MSB ensin UCA0MCTL = 0; // ei modulointia UCA0CTL1 |= UCSSEL1; // SMCLK, USCI 0 Clock Source Select 1 SPI_BR0 = 0x04; // Low byte of division factor for baud rate (500kHz) SPI_BR1 = 0x00; // High byte of division factor for baud rate UCA0CTL1 &= ~UCSWRST; // alustetaan USCI } // Linkin muodostin. Tässä laitetaan samalla CMR3000 anturi 80Hz modeen static void linkTo() { //uint8_t len, tid; while (SMPL_SUCCESS != SMPL_Link(&sLinkID1)) // odotetaan että linkki lautojen välille on muodostettu { SPIN_ABOUT_A_SECOND; } SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); // käynnistää radio while(1) { if(mode == 0x31 || mode == 0x32) { if(mode == 0x31) { Init_CMR3000_SCA3100(); // alustaa SPI:n antureille } if(mode == 0x32) { Init_CMR3000(); } wait_ms(10); BSP_TURN_ON_LED1(); CMR3000_Data = CMR3000_WriteRegister(CTRL, RESET); // resetoi cmr3000 anturi wait_ms(20); // odotetaan että resetointi valmis CMR3000_Data = CMR3000_WriteRegister(CTRL, I2C_DIS | MODE_80); // laitetaan I2C pois päältä ja 80hz mittaus mode vielä kerran varmuuden vuoksi päällle wait_ms(20); __bis_SR_register(LPM4_bits + GIE); // mennään virransäästötilaan, mutta sallii yleiset interruptit while (1) // jäädään odottamaan CMR3000 anturin interruptia { if(mode != 0x31 || mode != 0x32) { break; } } } if(mode == 0x33) { Init_SCA3100(); wait_ms(10); while(1) { Read_SCA3100(); if(mode != 0x33) { break; } } } } } static uint8_t sRxCallback(linkID_t port) { uint8_t msg[3], len; // tarkistetaan otetaan vastaan oikealta laitteelta if (port == sLinkID1) { // vastaanotetaan viesti if ((SMPL_SUCCESS == SMPL_Receive(sLinkID1, msg, &len))) // { mode = msg[0]; //tähän voidaan laittaa jotakin mitä halutaan tehdä kun viesti saapui takaisin toiselta laudalta, jos on tarvetta return 1; } } return 0; } //CMR3000 anturin keskeytys funktio. #pragma vector=CMR3000_PORT_INT_VECTOR __interrupt void Port_INT_ISR(void) { CMR3000_Data = CMR3000_WriteRegister(CTRL, I2C_DIS | MODE_80); // laitetaan I2C pois päältä ja 80hz mittaus mode vielä kerran varmuuden vuoksi päällle if (CMR3000_PORT_INT_IN & CMR3000_PIN_INT) // kun uusi uuden arvot ovat valmiita, luetaan molempien antureiden arvot { if(mode == 0x31) { Read_CMR3000_SCA3100(); // antureiden arvojen luku } if(mode == 0x32) { Read_CMR3000(); // antureiden arvojen luku } } } // CMR3000 anturin rekistereiden luku unsigned char CMR3000_ReadRegister(unsigned char Address) { unsigned char Result; Address <<= 2; // shiftataan osoitetta vasemmalle kahdella PORT_CSB_OUT &= ~CMR3000_PIN_CSB; // valitaan CMR3000 anturi Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = Address; // kirjoitetaan osoite TX bufferiin while (!(UCA0IFG&UCRXIFG)); // odotetaan että uusi tieto on kirjoitettu RX bufferiin Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = 0; // kirjoitetaan TX bufferiin arvo 0 while (!(UCA0IFG&UCRXIFG)); // odotetaan että uusi tieto on kirjoitettu RX bufferiin Result = RX_BUFFER; // luetaan RX bufferi wait_us(SPICSBDELAY); PORT_CSB_OUT |= CMR3000_PIN_CSB; // otetaan CMR3000 pois käytöstä wait_us(SPIFRAMEDELAY); return Result; // palautetaan RX bufferista saatu data } // CMR3000 anturin rekistereihin kirjoitus unsigned char CMR3000_WriteRegister(unsigned char Address, unsigned char Data) { unsigned char Result; Address <<= 2; // shiftataan osoitetta vasemmalle kahdella Address |= 0x02; // asetetaan toinen bitti ykköseksi, tekee siitä silloin kirjoittavan PORT_CSB_OUT &= ~CMR3000_PIN_CSB; // valitaan CMR3000 anturi Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = Address; // kirjoitetaan osoite TX bufferiin while (!(UCA0IFG&UCRXIFG)); // odotetaan että uusi tieto on kirjoitettu RX bufferiin Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = Data; // kirjoitetaan haluttu tieto TX bufferiin while (!(UCA0IFG&UCRXIFG)); // pyyhitään interrupt lippu lukemalla RX bufferi Result = RX_BUFFER; // luetaan RX bufferi wait_us(SPICSBDELAY); PORT_CSB_OUT |= CMR3000_PIN_CSB; // otetaan CMR3000 pois käytöstä wait_us(SPIFRAMEDELAY); return Result; } // SCA3100 anturin rekistereiden luku unsigned char SCA3100_ReadRegister(unsigned char Address) { unsigned char Result; Address <<= 2; // shiftataan osoitetta vasemmalle kahdella PORT_CSB_OUT &= ~SCA3100_PIN_CSB; // valitaan SCA3100 anturi Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = Address; // kirjoitetaan osoite TX bufferiin r while (!(UCA0IFG&UCRXIFG)); // odotetaan että uusi tieto on kirjoitettu RX bufferiin Result = RX_BUFFER; // pyyhitään interrupt lippu lukemalla RX bufferi TX_BUFFER = 0; // kirjoitetaan TX bufferiin arvo 0 while (!(UCA0IFG&UCRXIFG)); // odotetaan että uusi tieto on kirjoitettu RX bufferiin Result = RX_BUFFER; // luetaan RX bufferi wait_us(SPICSBDELAY); PORT_CSB_OUT |= SCA3100_PIN_CSB; // otetaan SCA3100 pois käytöstä wait_us(SPIFRAMEDELAY); return Result; // palautetaan RX bufferista saatu data } // Lukufunktio antureiden rekistereille // Tähän tullaan aina kun CMR3000-anturi lähettää interruptin // SCA3100:ssa ei ole interrupteja vaan dataa voidaan lukea koko ajan void Read_CMR3000_SCA3100() { uint8_t msg[12]; BSP_TURN_ON_LED2(); // ledi päälle kun uusi tieto on valmis // luetaan CMR3000, jokaisesta akselista luetaan LSB(vähiten merkitsevät) ja MSB(eniten merkitsevät) arvot // molemmat LSB ja MSB ovat 8bit kokoisia CMR3000_x_lsb = CMR3000_ReadRegister(CMR3000_X_LSB); CMR3000_x_msb = CMR3000_ReadRegister(CMR3000_X_MSB); CMR3000_y_lsb = CMR3000_ReadRegister(CMR3000_Y_LSB); CMR3000_y_msb = CMR3000_ReadRegister(CMR3000_Y_MSB); CMR3000_z_lsb = CMR3000_ReadRegister(CMR3000_Z_LSB); CMR3000_z_msb = CMR3000_ReadRegister(CMR3000_Z_MSB); // luetaan SCA3100, jokaisesta axelista luetaan LSB(vähiten merkitsevät) ja MSB(eniten merkitsevät) arvot // molemmat LSB ja MSB ovat 8bit kokoisia SCA3100_x_lsb = SCA3100_ReadRegister(SCA3100_X_LSB); SCA3100_x_msb = SCA3100_ReadRegister(SCA3100_X_MSB); SCA3100_y_lsb = SCA3100_ReadRegister(SCA3100_Y_LSB); SCA3100_y_msb = SCA3100_ReadRegister(SCA3100_Y_MSB); SCA3100_z_lsb = SCA3100_ReadRegister(SCA3100_Z_LSB); SCA3100_z_msb = SCA3100_ReadRegister(SCA3100_Z_MSB); // tallennetaan arvot viestin muuttujiksi, msg[0] = SCA3100_x_msb; msg[1] = SCA3100_x_lsb; msg[2] = SCA3100_y_msb; msg[3] = SCA3100_y_lsb; msg[4] = SCA3100_z_msb; msg[5] = SCA3100_z_lsb; msg[6] = CMR3000_x_msb; msg[7] = CMR3000_x_lsb; msg[8] = CMR3000_y_msb; msg[9] = CMR3000_y_lsb; msg[10] = CMR3000_z_msb; msg[11] = CMR3000_z_lsb; SMPL_Send(sLinkID1, msg, sizeof(msg)); // läheteetään arvot toiselle laudalle radion kautta BSP_TURN_OFF_LED2(); wait_ms(15); } void Read_CMR3000() { uint8_t msg[6]; BSP_TURN_ON_LED2(); // ledi päälle kun uusi tieto on valmis // luetaan CMR3000, jokaisesta akselista luetaan LSB(vähiten merkitsevät) ja MSB(eniten merkitsevät) arvot // molemmat LSB ja MSB ovat 8bit kokoisia CMR3000_x_lsb = CMR3000_ReadRegister(CMR3000_X_LSB); CMR3000_x_msb = CMR3000_ReadRegister(CMR3000_X_MSB); CMR3000_y_lsb = CMR3000_ReadRegister(CMR3000_Y_LSB); CMR3000_y_msb = CMR3000_ReadRegister(CMR3000_Y_MSB); CMR3000_z_lsb = CMR3000_ReadRegister(CMR3000_Z_LSB); CMR3000_z_msb = CMR3000_ReadRegister(CMR3000_Z_MSB); msg[0] = CMR3000_x_msb; msg[1] = CMR3000_x_lsb; msg[2] = CMR3000_y_msb; msg[3] = CMR3000_y_lsb; msg[4] = CMR3000_z_msb; msg[5] = CMR3000_z_lsb; SMPL_Send(sLinkID1, msg, sizeof(msg)); // läheteetään arvot toiselle laudalle radion kautta BSP_TURN_OFF_LED2(); wait_ms(15); } void Read_SCA3100() { uint8_t msg[6]; BSP_TURN_ON_LED2(); // ledi päälle kun uusi tieto on valmis // luetaan CMR3000, jokaisesta akselista luetaan LSB(vähiten merkitsevät) ja MSB(eniten merkitsevät) arvot // molemmat LSB ja MSB ovat 8bit kokoisia // luetaan SCA3100, jokaisesta axelista luetaan LSB(vähiten merkitsevät) ja MSB(eniten merkitsevät) arvot // molemmat LSB ja MSB ovat 8bit kokoisia SCA3100_x_lsb = SCA3100_ReadRegister(SCA3100_X_LSB); SCA3100_x_msb = SCA3100_ReadRegister(SCA3100_X_MSB); SCA3100_y_lsb = SCA3100_ReadRegister(SCA3100_Y_LSB); SCA3100_y_msb = SCA3100_ReadRegister(SCA3100_Y_MSB); SCA3100_z_lsb = SCA3100_ReadRegister(SCA3100_Z_LSB); SCA3100_z_msb = SCA3100_ReadRegister(SCA3100_Z_MSB); // tallennetaan arvot viestin muuttujiksi, msg[0] = SCA3100_x_msb; msg[1] = SCA3100_x_lsb; msg[2] = SCA3100_y_msb; msg[3] = SCA3100_y_lsb; msg[4] = SCA3100_z_msb; msg[5] = SCA3100_z_lsb; SMPL_Send(sLinkID1, msg, sizeof(msg)); // läheteetään arvot toiselle laudalle radion kautta BSP_TURN_OFF_LED2(); wait_ms(15); } void wait_ms(unsigned short ms) { unsigned short a, b; for (a = ms; a > 0; a--) for (b = TICKSPERMS; b > 0; b--) asm(" nop"); } void wait_us(unsigned short us) { unsigned short a; us *= TICKSPERUS; for (a = us; a > 0; a--) asm(" nop"); }