Coming soon!
New version on STM32 board. Maybe later on Arduino. So far, it works as communication device between two terminals. Also possible to use as remote for various toys. No code yet, need to clean it up a bit.
Still working on it, but here are first codes for STM32, later will be added codes for Arduino.
Semiduplex communication with Si4432 for STM32
Test code: working one for TX and RX. Sorry for Croatian comments…
// Moja verzija je B1, EZRadioPRO, == 00110 // Si4430/31/32 Rev B1: 00110. // Si100x Rev C, Si101x Rev A, Si102x/3x Rev A: 00110. // Si100x Rev E, Si101x Rev B: Si102x/3x Rev B: 00111. #include <SPI.h> //One out of these definitions has to be uncommented which tells to the compiler what kind //of Testcard is plugged into the Software Development board //#define SEPARATE_RX_TX //#define ANTENNA_DIVERSITY #define ONE_SMA_WITH_RF_SWITCH //we will use as breakout board has - antenna switch //byte reg1, reg2; uint8_t cmd; byte NIRQ=2; byte NSS=10; //PB2, or SS pin byte SDN=3; byte PB=4; //uint8_t value; byte ItStatus1,ItStatus2; byte Length,c; uint8_t payload[11]; uint8_t temp8; void setup() { //pinMode(A0,1);// LED1, 0=input, 1=output //pinMode(A1,1);// LED2 //pinMode(A2,1);// LED3 //pinMode(A3,1);// LED4 DDRB |= B00101100; //PB2, PB3 and PB5 are outputs (SS,MOSI,SCK) DDRC |= B00001111; //PC0, PC1, PC2 and PC3 are outputs for LEDs //pinMode(2,INPUT); //set below as DDRD |=B00001X10, where X we may replace with 0 //pinMode(NSS,1); //pin PB2 //pinMode(SDN,1); //pin PD3, already set by DDRD |=B0000X000, where X should be replaced with 1 //pinMode(4,INPUT_PULLUP); PORTD |= (1<<4); //pullup resistor on PD4 PORTD |= (1<<0); //pullup resistor for UART RX, maybe not needed?! DDRD |= B00001010; //all inputs except PD3, which is SDN on Si4432 chip, and PD1, which is UART TX //digitalWrite(A0,0);digitalWrite(A1,0);digitalWrite(A2,0);digitalWrite(A3,0);//turn off LEDs PORTC &= ~(1<<0);PORTC &= ~(1<<1);PORTC &= ~(1<<2); PORTC &= ~(1<<3); //turn off all LEDs Serial.begin(115200); SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setClockDivider(SPI_CLOCK_DIV2); //was 16 SPI.setBitOrder(MSBFIRST); //Turn on the radio by pulling down the PWRDN pin, or "SDN" pin //digitalWrite(3,0);// SDN = 0, or zero on PD3 PORTD &= ~(1<<3); //PD3 goes to zero //Wait at least 15ms befory any initialization SPI commands are sent to the radio // (wait for the power on reset sequence) delay(17); //more than 15 mS, so I put rather 17 mS //read interrupt status registers to clear the interrupt flags and release NIRQ pin ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register //SW reset SpiWriteRegister(0x07, 0x80); //write 0x80 to the Operating & Function Control1 register //wait for POR interrupt from the radio (while the nIRQ pin is high) //while (digitalRead(NIRQ) == 1); while(PIND&4); //ovaj PIND&4 je ekvivalent digitalRead(NIRQ)==1 //read interrupt status registers to clear the interrupt flags and release NIRQ pin ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register //wait for chip ready interrupt from the radio (while the nIRQ pin is high) //while(digitalRead(NIRQ)==1); while(PIND&4); //isto while(digitalRead(NIRQ)==1 //read interrupt status registers to clear the interrupt flags and release NIRQ pin ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register /*set the physical parameters*/ //set the center frequency to 915 MHz SpiWriteRegister(0x75, 0x40|0x13); //write 0x75 to the Frequency Band Select register 0x75=117 B01110101, 0x65=101 B01100101 SpiWriteRegister(0x76, 0x4e); //write 0xBB to the Nominal Carrier Frequency1 register 0xBB=187, B10111011 SpiWriteRegister(0x77, 0x00); //write 0x80 to the Nominal Carrier Frequency0 register 0x80=128, B10000000 0xBB80 gives: 48000 //f=(5+24+(48000/64000)*10000*(1+1)=... first parameter no more than 23 DEC or 0x17 , else math may be wrong //SpiWriteRegister(0x75,0x13); //was 0x75 for 915 MHz //SpiWriteRegister(0x76,0x62); //was 0xBB for 915 MHz //SpiWriteRegister(0x77,0x00); //was,0x80 for 915 MHz //set the desired TX data rate (9.6kbps) SpiWriteRegister(0x6E, 0x4E); //write 0x4E to the TXDataRate 1 register SpiWriteRegister(0x6F, 0xA5); //write 0xA5 to the TXDataRate 0 register SpiWriteRegister(0x70, 0x2C); //write 0x2C to the Modulation Mode Control 1 register //set the Tx deviation register (+-45kHz) SpiWriteRegister(0x72, 0x10); //write 0x48 to the Frequency Deviation register //I made it 0x12 or 625 kHz * 18 = 11.25 khz for 9.6 kbps (0x12) /*set the modem parameters according to the exel calculator(parameters: 9.6 kbps, * deviation: 45 kHz, channel filter BW: 102.2 kHz*/ SpiWriteRegister(0x1C, 0x12); //write 0x1E to the IF Filter Bandwidth register SpiWriteRegister(0x20, 0xD0); //write 0xD0 to the Clock Recovery Oversampling Ratio register SpiWriteRegister(0x21, 0x00); //write 0x00 to the Clock Recovery Offset 2 register SpiWriteRegister(0x22, 0x9D); //write 0x9D to the Clock Recovery Offset 1 register SpiWriteRegister(0x23, 0x49); //write 0x49 to the Clock Recovery Offset 0 register SpiWriteRegister(0x24, 0x00); //write 0x00 to the Clock Recovery Timing Loop Gain 1 register SpiWriteRegister(0x25, 0x24); //write 0x24 to the Clock Recovery Timing Loop Gain 0 register SpiWriteRegister(0x1D, 0x40); //write 0x40 to the AFC Loop Gearshift Override register SpiWriteRegister(0x1E, 0x0A); //write 0x0A to the AFC Timing Control register SpiWriteRegister(0x2A, 0x20); //write 0x20 to the AFC Limiter register /*set the packet structure and the modulation type*/ //set the preamble length to 5bytes SpiWriteRegister(0x34, 0x0A); //write 0x0A to the Preamble Length register //set preamble detection threshold to 20bits SpiWriteRegister(0x35, 0x2A); //write 0x2A to the Preamble Detection Control register //Disable header bytes; set variable packet length (the length of the payload is defined by the //received packet length field of the packet); set the synch word to two bytes long SpiWriteRegister(0x33, 0x02); //write 0x02 to the Header Control2 register //Set the sync word pattern to 0x2DD4 SpiWriteRegister(0x36, 0x2D); //write 0x2D to the Sync Word 3 register SpiWriteRegister(0x37, 0xD4); //write 0xD4 to the Sync Word 2 register //enable the TX & RX packet handler and CRC-16 (IBM) check SpiWriteRegister(0x30, 0x8D); //write 0x8D to the Data Access Control register //Disable the receive header filters SpiWriteRegister(0x32, 0x00 ); //write 0x00 to the Header Control1 register //enable FIFO mode and GFSK modulation SpiWriteRegister(0x71, 0x63); //write 0x63 to the Modulation Mode Control 2 register /*set the GPIO's according to the RF switch */ SpiWriteRegister(0x0b, 0x12); //write 0x12 to the GPIO1 Configuration(set the TX state) SpiWriteRegister(0x0c, 0x15); //write 0x15 to the GPIO2 Configuration(set the RX state) /*set the non-default Si443x registers*/ //set cap. bank SpiWriteRegister(0x09, 0xAC); //write 0xD7 to the Crystal Oscillator Load Capacitance register // Set AGC Override1 Register SpiWriteRegister(0x69, 0x60); //write 0x60 to the AGC Override1 register /*enable receiver chain*/ SpiWriteRegister(0x07, 0x05); //write 0x05 to the Operating Function Control 1 register //Enable two interrupts: // a) one which shows that a valid packet received: 'ipkval' // b) second shows if the packet received with incorrect CRC: 'icrcerror' SpiWriteRegister(0x05, 0x03); //write 0x03 to the Interrupt Enable 1 register SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register //read interrupt status registers to release all pending interrupts ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register //moje: //Power settings !!! SpiWriteRegister(0x6D,0x00);// 0x00 is minimum power, 0x07 is max power! was: (0x6D,0x08|0x00) } void loop() { //Poll the port pins of the MCU to figure out whether the push button is pressed or not //if(digitalRead(PB) == 0) if((PIND&16) == 0) //check PD4 to become zero { //Wait for releasing the push button //while(digitalRead(PB) == 0); while((PIND&16)==0); //waiting into the while loop until PD4 is again 1 //disable the receiver chain (but keep the XTAL running to have shorter TX on time!) SpiWriteRegister(0x07, 0x01); //write 0x01 to the Operating Function Control 1 register //turn on the LED to show the packet transmission //digitalWrite(A0,1); //TX_LED = 1 PORTC |= (1<<0); //PC0 goes to 1, zero shifting left of value 1 /*SET THE CONTENT OF THE PACKET*/ //set the length of the payload to 8bytes SpiWriteRegister(0x3E, 8); //write 8 to the Transmit Packet Length register //fill the payload into the transmit FIFO SpiWriteRegister(0x7F, 0x42); //write 0x42 ('B') to the FIFO Access register SpiWriteRegister(0x7F, 0x55); //write 0x55 ('U') to the FIFO Access register SpiWriteRegister(0x7F, 0x54); //write 0x54 ('T') to the FIFO Access register SpiWriteRegister(0x7F, 0x54); //write 0x54 ('T') to the FIFO Access register SpiWriteRegister(0x7F, 0x4F); //write 0x4F ('O') to the FIFO Access register SpiWriteRegister(0x7F, 0x4E); //write 0x4E ('N') to the FIFO Access register SpiWriteRegister(0x7F, 0x31); //write 0x31 ('1') to the FIFO Access register SpiWriteRegister(0x7F, 0x0D); //write 0x0D (CR) to the FIFO Access register //Disable all other interrupts and enable the packet sent interrupt only. //This will be used for indicating the successfull packet transmission for the MCU SpiWriteRegister(0x05, 0x04); //write 0x04 to the Interrupt Enable 1 register SpiWriteRegister(0x06, 0x00); //write 0x03 to the Interrupt Enable 2 register //Read interrupt status regsiters. It clear all pending interrupts and the nIRQ pin goes back to high. ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register /*enable transmitter*/ //The radio forms the packet and send it automatically. SpiWriteRegister(0x07, 0x09); //write 0x09 to the Operating Function Control 1 register /*wait for the packet sent interrupt*/ //The MCU just needs to wait for the 'ipksent' interrupt. //while(digitalRead(NIRQ) == 1); while(PIND&4); //while NIRQ==1 //read interrupt status registers to release the interrupt flags ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register //wait a bit for showing the LED a bit longer delay(10); //was delay(10) - DO NOT increase on single end! //turn off the LED //digitalWrite(A0,0); //TX_LED = 0 PORTC &= ~(1<<PC0); //not! zero shifted 0 from right to left, so PC0=0 //after packet transmission set the interrupt enable bits according receiving mode //Enable two interrupts: // a) one which shows that a valid packet received: 'ipkval' // b) second shows if the packet received with incorrect CRC: 'icrcerror' SpiWriteRegister(0x05, 0x03); //write 0x03 to the Interrupt Enable 1 register SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register //read interrupt status registers to release all pending interrupts ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register /*enable receiver chain again*/ SpiWriteRegister(0x07, 0x05); //write 0x05 to the Operating Function Control 1 register } //wait for the interrupt event //If it occurs, then it means a packet received or CRC error happened //if(digitalRead(NIRQ) == 0 ) if ((PIND&4)==0) //NIRQ pin is PD2 { //disable the receiver chain SpiWriteRegister(0x07, 0x01); //write 0x01 to the Operating Function Control 1 register //read interrupt status registers ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register /*CRC Error interrupt occured*/ if( (ItStatus1 & 0x01) == 0x01 ) { //reset the RX FIFO SpiWriteRegister(0x08, 0x02); //write 0x02 to the Operating Function Control 2 register SpiWriteRegister(0x08, 0x00); //write 0x00 to the Operating Function Control 2 register //blink all LEDs to show the error //digitalWrite(A0,1); //TX_LED = 1 PORTC |= (1<<0); //digitalWrite(A1,1); //RX_LED = 1 PORTC |= (1<<1); delay(10); //was delay(10) - DO NOT increase on single end! //digitalWrite(A0,0); //TX_LED = 0 PORTC &= ~(1<<0); //digitalWrite(A1,0); //RX_LED = 0 PORTC &= ~(1<<1); } /*packet received interrupt occured*/ if( (ItStatus1 & 0x02) == 0x02 ) { //Read the length of the received payload Length = SpiReadRegister(0x4B); //read the Received Packet Length register //check whether the received payload is not longer than the allocated buffer in the MCU if(Length < 11) { //Get the reeived payload from the RX FIFO for(temp8=0;temp8 < Length;temp8++) { payload[temp8] = SpiReadRegister(0x7F); //read the FIFO Access register Serial.print((char)payload[temp8]); } Serial.println(""); //check whether the acknowledgement packet received if( Length == 4 ) { if( memcmp(&payload[0], "ACK", 3) == 0 ) { //blink LED2 to show that ACK received //digitalWrite(A1,1); //RX_LED = 1 PORTC |=(1<<1); delay(10); //was delay(10)- DO NOT increase on single end! //digitalWrite(A1,0); //RX_LED = 0 PORTC &= ~(1<<1); } } //check whether an expected packet received, this should be acknowledged if( Length == 8 ) { if( memcmp(&payload[0], "BUTTON1", 7) == 0 ) { //blink LED2 to show that the packet received //digitalWrite(A1,1); //RX_LED = 1 PORTC |= (1<<1); delay(10); //was delay(10) - DO NOT increase on single end! //digitalWrite(A1,0); //RX_LED = 0 PORTC &= ~(1<<1); /*send back an acknowledgement*/ //turn on LED1 to show packet transmission //digitalWrite(A0,1); //TX_LED = 1 PORTC |= (1<<0); /*set packet content*/ //set the length of the payload to 4bytes SpiWriteRegister(0x3E, 4); //write 4 to the Transmit Packet Length register //fill the payload into the transmit FIFO SpiWriteRegister(0x7F, 0x41); //write 0x41 ('A') to the FIFO Access register SpiWriteRegister(0x7F, 0x43); //write 0x43 ('C') to the FIFO Access register SpiWriteRegister(0x7F, 0x4B); //write 0x4B ('K') to the FIFO Access register SpiWriteRegister(0x7F, 0x0D); //write 0x0D (CR) to the FIFO Access register //Disable all other interrupts and enable the packet sent interrupt only. //This will be used for indicating the successfull packet transmission for the MCU SpiWriteRegister(0x05, 0x04); //write 0x04 to the Interrupt Enable 1 register SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register //Read interrupt status regsiters. It clear all pending interrupts and the nIRQ pin goes back to high. ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register /*enable transmitter*/ //The radio forms the packet and send it automatically. SpiWriteRegister(0x07, 0x09); //write 0x09 to the Operating Function Control 1 register /*wait for the packet sent interrupt*/ //The MCU just needs to wait for the 'ipksent' interrupt. //while(digitalRead(NIRQ) == 1); while(PIND&4); //read interrupt status registers to release the interrupt flags ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register //wait a bit for showing the LED a bit longer delay(10); //was delay(10) - DO NOT increase on single end! //turn off the LED //digitalWrite(A0,0); //TX_LED = 0 PORTC &= ~(1<<0); //after packet transmission set the interrupt enable bits according receiving mode //Enable two interrupts: // a) one which shows that a valid packet received: 'ipkval' // b) second shows if the packet received with incorrect CRC: 'icrcerror' SpiWriteRegister(0x05, 0x03); //write 0x03 to the Interrupt Enable 1 register SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register //read interrupt status registers to release all pending interrupts ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register } } } } //reset the RX FIFO SpiWriteRegister(0x08, 0x02); //write 0x02 to the Operating Function Control 2 register SpiWriteRegister(0x08, 0x00); //write 0x00 to the Operating Function Control 2 register //enable the receiver chain again SpiWriteRegister(0x07, 0x05); //write 0x05 to the Operating Function Control 1 register } } void SpiWriteRegister(uint8_t reg,uint8_t cmd) { //digitalWrite(NSS,0); //Select the radio by pulling the nSEL pin to low (NSS=10), PB2 PORTB &= ~(1<<2); //pin PB2 is 0 SPI.transfer(0x80|reg) ;// 0x80 is first nRW bit high (1), IMPORTANT! SPI.transfer(cmd); ;// command is full byte //digitalWrite(NSS,1); //Deselect the radio by pulling high the nSEL pin PORTB |= (1<<2); //pin PB2 is 1 } byte SpiReadRegister(uint8_t reg) { //digitalWrite(NSS,0); //Select the radio by pulling the nSEL pin to low PORTB &= ~(1<<2); //PB2 is 0 SPI.transfer(reg); c=SPI.transfer(0) ;// "value" not really needed for purpose of reset flags, but...was Length //digitalWrite(NSS,1); //Deselect the radio by pulling high the nSEL pin PORTB |= (1<<2); //PB2 is 1 return c; }