Rf transmitter receiver module

Thread Starter

Ankish Sharma

Joined Feb 16, 2016
4
Hi, Everyone i need help on the best rf module to use for atleast 60 feet indoor through the multiple walls transmission.I used syn115 and syn460r using manchester encoding but can reach maximmum up to 30-40 feet error free transmission that too by sending multiple transmission. I have also used the popular nrf24l01 but it made the situation even worse kindly suggest me the best rf module that can fulfill my requirements.
 

ericgibbs

Joined Jan 29, 2010
18,766
Hi AS,
Look at the HC12 transceiver module, I use it successfully under similar conditions as your project.
It is TTL RS232 data

IMHO the NRF24l01 operating range is over specified in its documentation, I have dumped my NRF's!
E
 

Attachments

Thread Starter

Ankish Sharma

Joined Feb 16, 2016
4
Hi, i have ordered hc12 module to check but i can't find any refrence code for interfacing it to pic microcontroller which i am using in my current project.Kindly help me with refrence code on mikroc or c compiler.
 

LesJones

Joined Jan 8, 2017
4,174
Here is some code that uses an HC-12 with a PIC12F1840.

Code:
;   This is for reading the output from a DH22 temp / humidity sensor and outputing data as serial data.
;    Being modified to send data after receiving character string. (29/11/16)
;******************************************************************************************

;

;******************************************************************************************
;
;  OSC  : Internal OSC 4 MHz
;
;******************************************************************************************
  LIST  P=PIC12F1840,ST=OFF,R=DEC
  INCLUDE  "P12F1840.inc"

  __CONFIG _CONFIG1,  _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF &  _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF


  __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_HI & _LVP_OFF

;*******************************************************************************
; Constants
;*******************************************************************************

Station_ID   equ   'A'   ;Station identification character for this station   


RAM_START  equ  0x20


; The periods are timed with timer1 which is set to run at the internal clock
; rate (4 Mhz) of Fosc/4 or 1.0MHz which is equal to a 1 uS period.




DELAY_6MS   equ   D'2993'    ;Value to give delay of 6 mS
RX_Timer   equ   D'200'

;*******************************************************************************
; Pin Assignments
;*******************************************************************************
;
;   PIC signals
;
   #DEFINE     TX_Data     PORTA, 0     ;
   #DEFINE     RX_Data     PORTA, 1     ;
;
   #DEFINE     DHT22_Pin   PORTA, 2     ;
   #DEFINE     Button     PORTA, 3     ; Push button to trigger a DHT22 read (Not used)


; I/O pin use
;   RA0   TX      (Pin 7)  (To pin 4 on programmer connection)
;   RA1   RX      (Pin 6)  (To pin 5 on programmer connection)
;   RA2   DHR22 data       (Pin 5)
;   RA3   Trigger button     (Pin 4)   NOTE THIS PIN CAN ONLY BE USED AS AN INPUT.  Use for push button to trigger a read of the DHT22
;            (This is VPP for programming This could be connected to pin 3 or 5 of the header to program the chip on header.)
;   RA4   Not used       (Pin 3)
;   RA5       (Pin 2)




;  Define GENERAL PURPOSE RAM AREA (80 bytes maximum)

;*******************************************************************************
; File Register Variables
;*******************************************************************************
  cblock  RAM_START

param1:   1  ; parameter 1  (Used in delay cycles routine)
param2:   1  ; parameter 2  (Used in delay cycles routine)
Temp_1:   1     ;Used in 2 second delay

tmpData:   1     ; Used in output_hexbyte routine

; delay counters
Del_Count:  1
   
DHT_Data0:   1  ; 40 bit value from DHT  (Most significant byte)
DHT_Data1:   1   ; 0 & 1 Humidity
DHT_Data2:   1   ; 2 & 3 Temperature Bit 7 of byte 2 is sign bit (Set for negative.)
DHT_Data3:   1
DHT_Data4:   1   ; Byte 4 is the checksum

; bit counter
  bitcnt:  1
; byte counter
  bytcnt:  1

ESEVN:   1     ; 10 000,000 (digit 8)
ESIX:   1     ; 1000,000s (digit 7 )
EFIVE:   1     ; 100,000s digit 6 store
EFOUR:   1     ; 10,000s digit 5 store
ETHREE:   1     ; 1000s digit 4 store (kHz)
ETWO:   1     ; 100s digit 3 store
EONE:   1     ; 10s digit 2 store
EZERO:   1     ; 1's digit 1 store (Hz)



COUNT:   1

BCD1:   1     ; overrange
BCD2:   1     ; MS decimal value
BCD3:   1     ;
BCD4:   1     ; decimal value
BCD5:   1     ; ls decimal value
   
BIN1:   1     ; LS binary value
BIN2:   1     ;
BIN3:   1     ;
BIN4:   1     ; MS binary value

TEMP:   1
RX_Count:   1


  endc
;*******************************************************************************
; Common RAM (0x70 to 0x7F)
;*******************************************************************************

TX_temp     EQU 0x70     ;Temporary storage for character to be transmitted.
RX_Temp     EQU 0x71     ;Temporary storage for received character.

;*******************************************************************************
;  Define Macro  Takes 2 uS
;*******************************************************************************
SELBANK MACRO  #BANK_NO
  MOVLW  #BANK_NO   ;1 cycle - 1 uS
  MOVWF  BSR     ;1 cycle - 1 uS
  ENDM


; *****************************

  ORG  0h
  GOTO  START
  ORG  4h
  GOTO  START
START
; *****************************
;  Initialized Segment
; *****************************
; Initialise OSC (4MHz, IntOSC)
  SELBANK 1  ; SET BANK1
  MOVLW  B'11101010'   
  MOVWF  OSCCON

   BCF   INTCON,GIE

; Initialise I/O port
  SELBANK 1  ; SET BANK1
  MOVLW  B'00111010'     ; Bits 0, output Bit 1, 3, 4, 5 input. Bit 2 Initialy an output but changed during DHT data read.
  MOVWF  TRISA

;Set pullup on PORTA,3

   BCF   OPTION_REG,NOT_WPUEN

     SELBANK 4  ; SET BANK 4
   MOVLW   B'00001000'
   MOVWF   WPUA

     SELBANK 3  ; SET BANK 3
   MOVLW   0x00
   MOVWF   ANSELA     ; All I/O set to digital

     SELBANK 2  ; SET BANK2

; Initialized Comparitor.
     MOVLW  B'00000000'     ; Comparator disabled.
   MOVWF   CM1CON0       ;In bank 2
     SELBANK 0  ; SET BANK0

   CLRF   PORTA     ;Set all outputs low
   BSF   DHT22_Pin   ;Initial condition high



; Initialized EUSART
     SELBANK 3  ; SET BANK 3
   MOVLW   B'00000000'
   MOVWF   BAUDCON

   BSF   TXSTA,BRGH   ; Set baud rate high bit
     BSF  TXSTA,TXEN  ;enable transmission  

   MOVLW   0x19     ; Decimal 25 for 9600 baud rate
   MOVWF   SPBRGL
   MOVLW   0x00
   MOVWF   SPBRGH

   BSF  RCSTA,SPEN  ;enable serial port
   BSF  RCSTA,CREN  ;enable receive

     SELBANK 0  ; SET BANK0

; Initialized Timer 1
     SELBANK 0  ; SET BANK0

   MOVLW   B'00010100'   ;Clock source FOSC, 1:2 prescale, Dedicated Timer1 oscillator circuit disabled,
  ;Do not synchronize external clock input, Timer off

   MOVWF   T1CON     ;With 4 Mhz clock timer will increment every 500 nS

   MOVLW   0x00     ;All bits clear (Gate control not used.)
   MOVWF   T1GCON



; *****************************
;  Program main
; *****************************
; Main loop

   CALL Delay_2_Sec



Wait_Rx_Chr:       ;Wait for a received character
   CALL   SerialReceive
;   CALL    SerialTransmit ;Echo character as a test
;   MOVF   RX_Temp,W

   XORLW   '#'     ;Wait for # character.
   BTFSS   STATUS,Z
   GOTO   Wait_Rx_Chr   ; Not # character

   MOVLW   RX_Timer   ; Number of 10 mS to wait for station ID character
   MOVWF   RX_Count

Test_DAV:
     btfsc  PIR1,RCIF  ;check if data received
   GOTO   Read_Data
   CALL   Delay_10mS
   DECFSZ   RX_Count
   GOTO   Test_DAV
   GOTO   Wait_Rx_Chr



Read_Data:
   SELBANK 3  ; SET BANK 3
     movf  RCREG,W  ;get received data into W
   MOVWF   RX_Temp
     SELBANK 0  ; SET BANK 0
   MOVF   RX_Temp,W
   XORLW   Station_ID
   BTFSS   STATUS,Z
   GOTO   Wait_Rx_Chr   ; Not this station
MAIN:

   CALL   Read_DHT

   CALL   send_data     ;Output in raw HEX format

   MOVLW   0x0D     ;C/R
   CALL   SerialTransmit

   MOVLW   0x0A     ;L/F
   CALL   SerialTransmit

   CALL   Output_Decimal     ;Output in decimal

   MOVLW   0x0D     ;C/R
   CALL   SerialTransmit

   MOVLW   0x0A     ;L/F
   CALL   SerialTransmit

   CALL Delay_2_Sec

   GOTO   Wait_Rx_Chr
;     --------------------------------------------------------------------------------------


; *****************************
;  Subroutines
; *****************************
           
;*****************************************************************************   
;
;  Function :  SerialTransmit
;  This function sends the byte in W over the RS232 port. The
;  function will wait until previous data has been sent
;
;  Input:  Byte in W
;
;  Output:   
;
;*****************************************************************************   
SerialTransmit:
   MOVWF   TX_temp
     btfss  PIR1,TXIF  ;check that buffer is empty
     goto  $-1
     SELBANK 3  ; SET BANK 3
   MOVF   TX_temp,W   
     movwf  TXREG  ;transmit byte
     SELBANK 0  ; SET BANK 0
     return
;*****************************************************************************
   
SerialReceive:
     btfss  PIR1,RCIF  ;check if data received
     goto  $-1  ;wait until new data
   SELBANK 3  ; SET BANK 3
     movf  RCREG,W  ;get received data into W
   MOVWF   RX_Temp
     SELBANK 0  ; SET BANK 0
   MOVF   RX_Temp,W
     return
;*****************************************************************************  
   
;*Read DHT22
;* Result in DHT_Data  (5 bytes.)
;*
;*****************************************************************************  
;
   
Read_DHT:

; make data pin  output

     SELBANK 1  ; SET BANK 1     2 uS
   BCF   TRISA,2     ; Set DHT_Pin as output  1 uS
     SELBANK 0  ; SET BANK 0     2 uS

   BCF   DHT22_Pin       ; set it low for 18ms

; delay 6 ms
  movlw  LOW DELAY_6MS  ; Delay for 6 milliseconds  Normal value used
  movwf  param1  ;
  movlw  HIGH DELAY_6MS     ;  Normal value used
  movwf  param2  ;
  call  delay_cycles  ;


; Set data line high for 30 us
   BSF   DHT22_Pin       ;

; delay for 30 us
   movlw 0x09       ; 1 uS
   movwf Del_Count       ; 1 uS
Del_30us
   decfsz Del_Count, f     ; 1 uS while looping, 2 uS on exit
   goto Del_30us       ; 2 uS
   NOP

; Init bit counter
     MOVLW  D'40'
     MOVWF  bitcnt



; DHT22 now outputs data
; set data line for input
; Wait until it is low

     SELBANK 1  ; SET BANK 1     2 uS
   BSF   TRISA,2     ; Set DHT_Pin as input  1 uS
     SELBANK 0  ; SET BANK 0     2 uS

wait_responce_low:
     btfsc  DHT22_Pin  ; skip next inst if it is already low
     goto  wait_responce_low


; the DHT should next set the data line high for 80us
wait_responce_high
     btfss  DHT22_Pin
     goto  wait_responce_high


; now wait for it to go low again, marking the begining of the start bit
wait_bit_start:
     btfsc  DHT22_Pin
     goto  wait_bit_start
; start of bit -  50us low on the data line followed
; by 26-28 us high if is a "0" or a 70 us high if is a "1"
; So half way between is 49 uS

start_bit
; wait for the start bit to end
wait_high
     btfss  DHT22_Pin
     goto  wait_high

; delay for 49 us
   movlw 0x09     ; (1uS)                 1 uS
   movwf Del_Count     ;(1uS)                 2 uS
     bcf  STATUS, C   ;(1uS)   Set to 1 initially           3 uS

Del_49us:
   decfsz Del_Count, f   ;(1uS) (2 uS on skip)             4 uS  (Loop is 5 uS)
   goto No_timeout     ;(2 uS)                 6 uS
     bsf  STATUS, C   ; More than 40 uS have elapsed so clear carry bit. (1 uS)
No_timeout:
; Has data line gone low ? (End of bit.)

     btfsc  DHT22_Pin   ;(1uS) (2 uS on skip) Test for end of bit       7 uS
   goto    Del_49us     ;(2 uS)               9 uS


;Shift carry bit into Bit 0  (We have 50 uS before start of next bit)
Shift_bit:
   RLF   DHT_Data4
   RLF   DHT_Data3
   RLF   DHT_Data2
   RLF   DHT_Data1
   RLF   DHT_Data0

dec_bit
     decfsz  bitcnt,f
     goto  wait_high    ;For next bit of frame.

Frame_End:
   RETURN

;     -----------------------------------------------------------------------------

;Output the data in HEX format
send_data:
; initialize the FSR0
     movlw  DHT_Data0
     movwf  FSR0L
   CLRF   FSR0H
; set byte counter
     movlw  0x5
     movwf  bytcnt

sendloop:
     movf  INDF0,w  ; get a byte of data

   CALL   output_hexbyte
; point to the next byte
     incf  FSR0L
     decfsz  bytcnt,f
     goto  sendloop
; All 5 bytes of data outputted
   RETURN
;

;*****************************************************************************   
;
;  Function :  output_hexbyte
;  Outputs the byte W to serial port
;  Input:  data in W
;
;  Output:  Data displayed
;
;*****************************************************************************   
output_hexbyte:
   MOVWF   tmpData
     swapf  tmpData,W
     sublw  0x09
     swapf  tmpData,W
     andlw  0x0F
     btfss  STATUS,DC
     addlw  'A' - .10 - '0'
     addlw  '0'
     call  SerialTransmit
     movfw  tmpData
     sublw  0x09
     movfw  tmpData
     andlw  0x0F
     btfss  STATUS,DC
     addlw  'A' - .10 - '0'
     addlw  '0'
     call  SerialTransmit
     return

Delay_10mS:       ;Need to set param to (10000 - 14)/2  = 9986/2 = 4993 = 0x1381
   MOVLW   0x13
   MOVWF   param2
   MOVLW   0x81
   MOVWF   param1
   GOTO   delay_cycles




Delay_100mS:
   MOVLW   0xC3
   MOVWF   param2
   MOVLW   0x49
   MOVWF   param1
   GOTO   delay_cycles
   
Delay_2_Sec:
   MOVLW   D'20'
   MOVWF   Temp_1
D2_Loop:
   CALL   Delay_100mS
   DECFSZ   Temp_1
   GOTO   D2_Loop
   RETURN

;*******************************************************************************
; Function:  delay_cycles
; Description: Delay a specified number of instruction cycles including
;  interrupt cycles.  The function call overhead adds between
;  13 and 16 cycles of delay on top of the specified value.
; With 4 Mhz system clock and 1:2 prescale
;Delay will be  param * 2 uS + (13 * 1uS)  + 0 to 3 uS
;     = param * 2 uS + (13 to16.0 uS)  (Use 14 uS for calculation.)
;  So param = No. of uS/2 - 7
; Parameters:  param1 - least significant byte of 16 bit cycle delay
;  param2 - most significant byte of 16 bit cycle delay
; Returns:  None
;*******************************************************************************
delay_cycles:
  comf  param1,F  ; negate the delay by complementing the     (1 uS)    (1 cycle)
  comf  param2,F  ; low and high bytes         (1 uS)    (1 cycle)
  bcf  T1CON,TMR1ON  ; stop timer 1           (1 uS)    (1 cycle)
  movf  param1,W  ; move the low byte of the delay into     (1 uS)    (1 cycle)
  movwf  TMR1L  ; timer 1           (1 uS)    (1 cycle)
  movf  param2,W  ; move the high byte of the delay into     (1 uS)    (1 cycle)
  movwf  TMR1H  ; timer 1           (1 uS)    (1 cycle)
  bcf  PIR1,TMR1IF  ; clear the timer 1 rollover flag     (1 uS)    (1 cycle)
  bsf  T1CON,TMR1ON  ; turn on timer 1         (1 uS)    (1 cycle)
   
tmr1_check:   
  btfss  PIR1,TMR1IF  ; wait for the timer 1 rollover flag to     1 uS while looping    (2 uS) (2 cycle) on exit
  goto  tmr1_check  ; trigger
  return         ;             (2 uS)   (2 cycle)

;**********************************************************************************
; Subroutine BCD (to convert 28-bit binary to 8-digit BCD)
; Binary value is in BIN1, BIN2, BIN3 & BIN4. BIN1 is LSB, BIN4 is MSB
; Result in BCD is in BCD1, BCD2, BCD3, BCD4 & BCD5. BCD1 is for overrange,
; BCD2 is MSB, BCD5 is LSB
;**********************************************************************************

BIN_BCD:   
   bcf   STATUS,C   ; clear carry bit
   movlw   D'32'
   movwf   COUNT     ; 32 in count
   clrf   BCD1     ; set BCD registers to 0
   clrf   BCD2
   clrf   BCD3
   clrf   BCD4
   clrf   BCD5

LOOPBCD:
   rlf   BIN1,f     ; LSB shift left binary registers
   rlf   BIN2,f
   rlf    BIN3,f
   rlf   BIN4,f     ; MSB
   rlf   BCD5,f     ; LSB shift left BCD registers
   rlf   BCD4,f
   rlf   BCD3,f
   rlf   BCD2,f
   rlf   BCD1,f     ; MSB

   decfsz   COUNT,f     ; reduce count value return when 0
   goto   DECADJ     ; continue decimal adjust
   
; result in BCD1-5. (BCD1 overrange, BCD2 MS byte)

   swapf   BCD2,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ESEVN     ; ms digit
   movf   BCD2,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ESIX

   swapf   BCD3,w     ; get next nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EFIVE     ; ms digit
   movf   BCD3,w     ; get next nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EFOUR
   
   swapf   BCD4,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ETHREE     ; ms digit
   movf   BCD4,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ETWO

   swapf   BCD5,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EONE     ; ms digit
   movf   BCD5,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EZERO
   return       ; completed decimal to BCD operation

; subroutine decimal adjust

DECADJ   movlw   BCD5     ; BCD LSB address
   movwf   FSR1L     ; pointer for BCD5
   CLRF   FSR1H
   call   ADJBCD     ; subroutine to adjust BCD
   movlw   BCD4
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD3
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD2
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD1
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   goto   LOOPBCD

; subroutine adjust BCD

ADJBCD   movlw   0x03     ; w has 03
   addwf   INDF1,w     ; add 03 to BCDx register (x is 1-5)
   movwf   TEMP     ; store w
   btfsc   TEMP,3     ; test if >7
   movwf   INDF1     ; save as LS digit
   movlw   0x30     ; 3 for MSbyte
   addwf   INDF1,w     ; add 30 to BCDx register
   movwf   TEMP     ; store w
   btfsc   TEMP,7     ; test if >7
   movwf   INDF1     ; save as MS digit
   return       ; end subroutine



;**********************************************************************************
;
;
Output_Decimal:

   CLRF   BIN4     ;Clear top 3 bytes (Not used.)
   CLRF   BIN3
   CLRF   BIN2
   
   MOVF   DHT_Data0,W   ;Humidity high byte
   MOVWF   BIN2   

   MOVF   DHT_Data1,W   ;Humidity low byte
   MOVWF   BIN1   

   CALL   BIN_BCD

Output_Humidity:
   MOVLW   'H'
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit
   

   MOVF   ETWO, W
     CALL  SerialTransmit

   MOVF   EONE, W
     CALL  SerialTransmit

   MOVLW   '.'
     CALL  SerialTransmit

   MOVF   EZERO, W
     CALL  SerialTransmit

   MOVLW   '%'
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit

Output_Temp:

   CLRF   BIN4     ;Clear top 2 bytes (Not used.)
   CLRF   BIN3
   CLRF   BIN2
   
   MOVF   DHT_Data2,W   ;Temp high byte
   MOVWF   BIN2   

   MOVF   DHT_Data3,W   ;Temp low byte
   MOVWF   BIN1   

   CALL   BIN_BCD



   MOVLW   'T'
     CALL  SerialTransmit
   MOVLW   'e'
     CALL  SerialTransmit
   MOVLW   'm'
     CALL  SerialTransmit
   MOVLW   'p'
     CALL  SerialTransmit
   MOVLW   ' '
     CALL  SerialTransmit
   MOVLW   '+'
   
   BTFSC   DHT_Data2,7     ;Test sign bit
   MOVLW   '-'

     CALL  SerialTransmit

   MOVF   ETWO, W
     CALL  SerialTransmit

   MOVF   EONE, W
     CALL  SerialTransmit

   MOVLW   '.'
     CALL  SerialTransmit

   MOVF   EZERO, W
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit
   MOVLW   'C'
     CALL  SerialTransmit


   RETURN



   end
This code reads data from a DH22 temperature and humidity sensor and outputs it as an ASCII string via the HC-12. A reading is triggered by sending "#A" to it from the other HC-12.
The parts of the code that deal with the HC-12 are :-
Initialized EUSART
SerialTransmit:
SerialReceive:

The code will be very similar for other PICs

Les.
 

Thread Starter

Ankish Sharma

Joined Feb 16, 2016
4
Here is some code that uses an HC-12 with a PIC12F1840.

Code:
;   This is for reading the output from a DH22 temp / humidity sensor and outputing data as serial data.
;    Being modified to send data after receiving character string. (29/11/16)
;******************************************************************************************

;

;******************************************************************************************
;
;  OSC  : Internal OSC 4 MHz
;
;******************************************************************************************
  LIST  P=PIC12F1840,ST=OFF,R=DEC
  INCLUDE  "P12F1840.inc"

  __CONFIG _CONFIG1,  _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF &  _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF


  __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_HI & _LVP_OFF

;*******************************************************************************
; Constants
;*******************************************************************************

Station_ID   equ   'A'   ;Station identification character for this station  


RAM_START  equ  0x20


; The periods are timed with timer1 which is set to run at the internal clock
; rate (4 Mhz) of Fosc/4 or 1.0MHz which is equal to a 1 uS period.




DELAY_6MS   equ   D'2993'    ;Value to give delay of 6 mS
RX_Timer   equ   D'200'

;*******************************************************************************
; Pin Assignments
;*******************************************************************************
;
;   PIC signals
;
   #DEFINE     TX_Data     PORTA, 0     ;
   #DEFINE     RX_Data     PORTA, 1     ;
;
   #DEFINE     DHT22_Pin   PORTA, 2     ;
   #DEFINE     Button     PORTA, 3     ; Push button to trigger a DHT22 read (Not used)


; I/O pin use
;   RA0   TX      (Pin 7)  (To pin 4 on programmer connection)
;   RA1   RX      (Pin 6)  (To pin 5 on programmer connection)
;   RA2   DHR22 data       (Pin 5)
;   RA3   Trigger button     (Pin 4)   NOTE THIS PIN CAN ONLY BE USED AS AN INPUT.  Use for push button to trigger a read of the DHT22
;            (This is VPP for programming This could be connected to pin 3 or 5 of the header to program the chip on header.)
;   RA4   Not used       (Pin 3)
;   RA5       (Pin 2)




;  Define GENERAL PURPOSE RAM AREA (80 bytes maximum)

;*******************************************************************************
; File Register Variables
;*******************************************************************************
  cblock  RAM_START

param1:   1  ; parameter 1  (Used in delay cycles routine)
param2:   1  ; parameter 2  (Used in delay cycles routine)
Temp_1:   1     ;Used in 2 second delay

tmpData:   1     ; Used in output_hexbyte routine

; delay counters
Del_Count:  1
  
DHT_Data0:   1  ; 40 bit value from DHT  (Most significant byte)
DHT_Data1:   1   ; 0 & 1 Humidity
DHT_Data2:   1   ; 2 & 3 Temperature Bit 7 of byte 2 is sign bit (Set for negative.)
DHT_Data3:   1
DHT_Data4:   1   ; Byte 4 is the checksum

; bit counter
  bitcnt:  1
; byte counter
  bytcnt:  1

ESEVN:   1     ; 10 000,000 (digit 8)
ESIX:   1     ; 1000,000s (digit 7 )
EFIVE:   1     ; 100,000s digit 6 store
EFOUR:   1     ; 10,000s digit 5 store
ETHREE:   1     ; 1000s digit 4 store (kHz)
ETWO:   1     ; 100s digit 3 store
EONE:   1     ; 10s digit 2 store
EZERO:   1     ; 1's digit 1 store (Hz)



COUNT:   1

BCD1:   1     ; overrange
BCD2:   1     ; MS decimal value
BCD3:   1     ;
BCD4:   1     ; decimal value
BCD5:   1     ; ls decimal value
  
BIN1:   1     ; LS binary value
BIN2:   1     ;
BIN3:   1     ;
BIN4:   1     ; MS binary value

TEMP:   1
RX_Count:   1


  endc
;*******************************************************************************
; Common RAM (0x70 to 0x7F)
;*******************************************************************************

TX_temp     EQU 0x70     ;Temporary storage for character to be transmitted.
RX_Temp     EQU 0x71     ;Temporary storage for received character.

;*******************************************************************************
;  Define Macro  Takes 2 uS
;*******************************************************************************
SELBANK MACRO  #BANK_NO
  MOVLW  #BANK_NO   ;1 cycle - 1 uS
  MOVWF  BSR     ;1 cycle - 1 uS
  ENDM


; *****************************

  ORG  0h
  GOTO  START
  ORG  4h
  GOTO  START
START
; *****************************
;  Initialized Segment
; *****************************
; Initialise OSC (4MHz, IntOSC)
  SELBANK 1  ; SET BANK1
  MOVLW  B'11101010'  
  MOVWF  OSCCON

   BCF   INTCON,GIE

; Initialise I/O port
  SELBANK 1  ; SET BANK1
  MOVLW  B'00111010'     ; Bits 0, output Bit 1, 3, 4, 5 input. Bit 2 Initialy an output but changed during DHT data read.
  MOVWF  TRISA

;Set pullup on PORTA,3

   BCF   OPTION_REG,NOT_WPUEN

     SELBANK 4  ; SET BANK 4
   MOVLW   B'00001000'
   MOVWF   WPUA

     SELBANK 3  ; SET BANK 3
   MOVLW   0x00
   MOVWF   ANSELA     ; All I/O set to digital

     SELBANK 2  ; SET BANK2

; Initialized Comparitor.
     MOVLW  B'00000000'     ; Comparator disabled.
   MOVWF   CM1CON0       ;In bank 2
     SELBANK 0  ; SET BANK0

   CLRF   PORTA     ;Set all outputs low
   BSF   DHT22_Pin   ;Initial condition high



; Initialized EUSART
     SELBANK 3  ; SET BANK 3
   MOVLW   B'00000000'
   MOVWF   BAUDCON

   BSF   TXSTA,BRGH   ; Set baud rate high bit
     BSF  TXSTA,TXEN  ;enable transmission 

   MOVLW   0x19     ; Decimal 25 for 9600 baud rate
   MOVWF   SPBRGL
   MOVLW   0x00
   MOVWF   SPBRGH

   BSF  RCSTA,SPEN  ;enable serial port
   BSF  RCSTA,CREN  ;enable receive

     SELBANK 0  ; SET BANK0

; Initialized Timer 1
     SELBANK 0  ; SET BANK0

   MOVLW   B'00010100'   ;Clock source FOSC, 1:2 prescale, Dedicated Timer1 oscillator circuit disabled,
  ;Do not synchronize external clock input, Timer off

   MOVWF   T1CON     ;With 4 Mhz clock timer will increment every 500 nS

   MOVLW   0x00     ;All bits clear (Gate control not used.)
   MOVWF   T1GCON



; *****************************
;  Program main
; *****************************
; Main loop

   CALL Delay_2_Sec



Wait_Rx_Chr:       ;Wait for a received character
   CALL   SerialReceive
;   CALL    SerialTransmit ;Echo character as a test
;   MOVF   RX_Temp,W

   XORLW   '#'     ;Wait for # character.
   BTFSS   STATUS,Z
   GOTO   Wait_Rx_Chr   ; Not # character

   MOVLW   RX_Timer   ; Number of 10 mS to wait for station ID character
   MOVWF   RX_Count

Test_DAV:
     btfsc  PIR1,RCIF  ;check if data received
   GOTO   Read_Data
   CALL   Delay_10mS
   DECFSZ   RX_Count
   GOTO   Test_DAV
   GOTO   Wait_Rx_Chr



Read_Data:
   SELBANK 3  ; SET BANK 3
     movf  RCREG,W  ;get received data into W
   MOVWF   RX_Temp
     SELBANK 0  ; SET BANK 0
   MOVF   RX_Temp,W
   XORLW   Station_ID
   BTFSS   STATUS,Z
   GOTO   Wait_Rx_Chr   ; Not this station
MAIN:

   CALL   Read_DHT

   CALL   send_data     ;Output in raw HEX format

   MOVLW   0x0D     ;C/R
   CALL   SerialTransmit

   MOVLW   0x0A     ;L/F
   CALL   SerialTransmit

   CALL   Output_Decimal     ;Output in decimal

   MOVLW   0x0D     ;C/R
   CALL   SerialTransmit

   MOVLW   0x0A     ;L/F
   CALL   SerialTransmit

   CALL Delay_2_Sec

   GOTO   Wait_Rx_Chr
;     --------------------------------------------------------------------------------------


; *****************************
;  Subroutines
; *****************************
          
;*****************************************************************************  
;
;  Function :  SerialTransmit
;  This function sends the byte in W over the RS232 port. The
;  function will wait until previous data has been sent
;
;  Input:  Byte in W
;
;  Output:  
;
;*****************************************************************************  
SerialTransmit:
   MOVWF   TX_temp
     btfss  PIR1,TXIF  ;check that buffer is empty
     goto  $-1
     SELBANK 3  ; SET BANK 3
   MOVF   TX_temp,W  
     movwf  TXREG  ;transmit byte
     SELBANK 0  ; SET BANK 0
     return
;*****************************************************************************
  
SerialReceive:
     btfss  PIR1,RCIF  ;check if data received
     goto  $-1  ;wait until new data
   SELBANK 3  ; SET BANK 3
     movf  RCREG,W  ;get received data into W
   MOVWF   RX_Temp
     SELBANK 0  ; SET BANK 0
   MOVF   RX_Temp,W
     return
;***************************************************************************** 
  
;*Read DHT22
;* Result in DHT_Data  (5 bytes.)
;*
;***************************************************************************** 
;
  
Read_DHT:

; make data pin  output

     SELBANK 1  ; SET BANK 1     2 uS
   BCF   TRISA,2     ; Set DHT_Pin as output  1 uS
     SELBANK 0  ; SET BANK 0     2 uS

   BCF   DHT22_Pin       ; set it low for 18ms

; delay 6 ms
  movlw  LOW DELAY_6MS  ; Delay for 6 milliseconds  Normal value used
  movwf  param1  ;
  movlw  HIGH DELAY_6MS     ;  Normal value used
  movwf  param2  ;
  call  delay_cycles  ;


; Set data line high for 30 us
   BSF   DHT22_Pin       ;

; delay for 30 us
   movlw 0x09       ; 1 uS
   movwf Del_Count       ; 1 uS
Del_30us
   decfsz Del_Count, f     ; 1 uS while looping, 2 uS on exit
   goto Del_30us       ; 2 uS
   NOP

; Init bit counter
     MOVLW  D'40'
     MOVWF  bitcnt



; DHT22 now outputs data
; set data line for input
; Wait until it is low

     SELBANK 1  ; SET BANK 1     2 uS
   BSF   TRISA,2     ; Set DHT_Pin as input  1 uS
     SELBANK 0  ; SET BANK 0     2 uS

wait_responce_low:
     btfsc  DHT22_Pin  ; skip next inst if it is already low
     goto  wait_responce_low


; the DHT should next set the data line high for 80us
wait_responce_high
     btfss  DHT22_Pin
     goto  wait_responce_high


; now wait for it to go low again, marking the begining of the start bit
wait_bit_start:
     btfsc  DHT22_Pin
     goto  wait_bit_start
; start of bit -  50us low on the data line followed
; by 26-28 us high if is a "0" or a 70 us high if is a "1"
; So half way between is 49 uS

start_bit
; wait for the start bit to end
wait_high
     btfss  DHT22_Pin
     goto  wait_high

; delay for 49 us
   movlw 0x09     ; (1uS)                 1 uS
   movwf Del_Count     ;(1uS)                 2 uS
     bcf  STATUS, C   ;(1uS)   Set to 1 initially           3 uS

Del_49us:
   decfsz Del_Count, f   ;(1uS) (2 uS on skip)             4 uS  (Loop is 5 uS)
   goto No_timeout     ;(2 uS)                 6 uS
     bsf  STATUS, C   ; More than 40 uS have elapsed so clear carry bit. (1 uS)
No_timeout:
; Has data line gone low ? (End of bit.)

     btfsc  DHT22_Pin   ;(1uS) (2 uS on skip) Test for end of bit       7 uS
   goto    Del_49us     ;(2 uS)               9 uS


;Shift carry bit into Bit 0  (We have 50 uS before start of next bit)
Shift_bit:
   RLF   DHT_Data4
   RLF   DHT_Data3
   RLF   DHT_Data2
   RLF   DHT_Data1
   RLF   DHT_Data0

dec_bit
     decfsz  bitcnt,f
     goto  wait_high    ;For next bit of frame.

Frame_End:
   RETURN

;     -----------------------------------------------------------------------------

;Output the data in HEX format
send_data:
; initialize the FSR0
     movlw  DHT_Data0
     movwf  FSR0L
   CLRF   FSR0H
; set byte counter
     movlw  0x5
     movwf  bytcnt

sendloop:
     movf  INDF0,w  ; get a byte of data

   CALL   output_hexbyte
; point to the next byte
     incf  FSR0L
     decfsz  bytcnt,f
     goto  sendloop
; All 5 bytes of data outputted
   RETURN
;

;*****************************************************************************  
;
;  Function :  output_hexbyte
;  Outputs the byte W to serial port
;  Input:  data in W
;
;  Output:  Data displayed
;
;*****************************************************************************  
output_hexbyte:
   MOVWF   tmpData
     swapf  tmpData,W
     sublw  0x09
     swapf  tmpData,W
     andlw  0x0F
     btfss  STATUS,DC
     addlw  'A' - .10 - '0'
     addlw  '0'
     call  SerialTransmit
     movfw  tmpData
     sublw  0x09
     movfw  tmpData
     andlw  0x0F
     btfss  STATUS,DC
     addlw  'A' - .10 - '0'
     addlw  '0'
     call  SerialTransmit
     return

Delay_10mS:       ;Need to set param to (10000 - 14)/2  = 9986/2 = 4993 = 0x1381
   MOVLW   0x13
   MOVWF   param2
   MOVLW   0x81
   MOVWF   param1
   GOTO   delay_cycles




Delay_100mS:
   MOVLW   0xC3
   MOVWF   param2
   MOVLW   0x49
   MOVWF   param1
   GOTO   delay_cycles
  
Delay_2_Sec:
   MOVLW   D'20'
   MOVWF   Temp_1
D2_Loop:
   CALL   Delay_100mS
   DECFSZ   Temp_1
   GOTO   D2_Loop
   RETURN

;*******************************************************************************
; Function:  delay_cycles
; Description: Delay a specified number of instruction cycles including
;  interrupt cycles.  The function call overhead adds between
;  13 and 16 cycles of delay on top of the specified value.
; With 4 Mhz system clock and 1:2 prescale
;Delay will be  param * 2 uS + (13 * 1uS)  + 0 to 3 uS
;     = param * 2 uS + (13 to16.0 uS)  (Use 14 uS for calculation.)
;  So param = No. of uS/2 - 7
; Parameters:  param1 - least significant byte of 16 bit cycle delay
;  param2 - most significant byte of 16 bit cycle delay
; Returns:  None
;*******************************************************************************
delay_cycles:
  comf  param1,F  ; negate the delay by complementing the     (1 uS)    (1 cycle)
  comf  param2,F  ; low and high bytes         (1 uS)    (1 cycle)
  bcf  T1CON,TMR1ON  ; stop timer 1           (1 uS)    (1 cycle)
  movf  param1,W  ; move the low byte of the delay into     (1 uS)    (1 cycle)
  movwf  TMR1L  ; timer 1           (1 uS)    (1 cycle)
  movf  param2,W  ; move the high byte of the delay into     (1 uS)    (1 cycle)
  movwf  TMR1H  ; timer 1           (1 uS)    (1 cycle)
  bcf  PIR1,TMR1IF  ; clear the timer 1 rollover flag     (1 uS)    (1 cycle)
  bsf  T1CON,TMR1ON  ; turn on timer 1         (1 uS)    (1 cycle)
  
tmr1_check:  
  btfss  PIR1,TMR1IF  ; wait for the timer 1 rollover flag to     1 uS while looping    (2 uS) (2 cycle) on exit
  goto  tmr1_check  ; trigger
  return         ;             (2 uS)   (2 cycle)

;**********************************************************************************
; Subroutine BCD (to convert 28-bit binary to 8-digit BCD)
; Binary value is in BIN1, BIN2, BIN3 & BIN4. BIN1 is LSB, BIN4 is MSB
; Result in BCD is in BCD1, BCD2, BCD3, BCD4 & BCD5. BCD1 is for overrange,
; BCD2 is MSB, BCD5 is LSB
;**********************************************************************************

BIN_BCD:  
   bcf   STATUS,C   ; clear carry bit
   movlw   D'32'
   movwf   COUNT     ; 32 in count
   clrf   BCD1     ; set BCD registers to 0
   clrf   BCD2
   clrf   BCD3
   clrf   BCD4
   clrf   BCD5

LOOPBCD:
   rlf   BIN1,f     ; LSB shift left binary registers
   rlf   BIN2,f
   rlf    BIN3,f
   rlf   BIN4,f     ; MSB
   rlf   BCD5,f     ; LSB shift left BCD registers
   rlf   BCD4,f
   rlf   BCD3,f
   rlf   BCD2,f
   rlf   BCD1,f     ; MSB

   decfsz   COUNT,f     ; reduce count value return when 0
   goto   DECADJ     ; continue decimal adjust
  
; result in BCD1-5. (BCD1 overrange, BCD2 MS byte)

   swapf   BCD2,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ESEVN     ; ms digit
   movf   BCD2,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ESIX

   swapf   BCD3,w     ; get next nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EFIVE     ; ms digit
   movf   BCD3,w     ; get next nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EFOUR
  
   swapf   BCD4,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ETHREE     ; ms digit
   movf   BCD4,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   ETWO

   swapf   BCD5,w     ; get ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EONE     ; ms digit
   movf   BCD5,w     ; get 2nd ms nibble
   andlw   0x0F
   iorlw   0x30     ; convert to ASCII
   movwf   EZERO
   return       ; completed decimal to BCD operation

; subroutine decimal adjust

DECADJ   movlw   BCD5     ; BCD LSB address
   movwf   FSR1L     ; pointer for BCD5
   CLRF   FSR1H
   call   ADJBCD     ; subroutine to adjust BCD
   movlw   BCD4
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD3
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD2
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   movlw   BCD1
   movwf   FSR1L
   CLRF   FSR1H
   call    ADJBCD
   goto   LOOPBCD

; subroutine adjust BCD

ADJBCD   movlw   0x03     ; w has 03
   addwf   INDF1,w     ; add 03 to BCDx register (x is 1-5)
   movwf   TEMP     ; store w
   btfsc   TEMP,3     ; test if >7
   movwf   INDF1     ; save as LS digit
   movlw   0x30     ; 3 for MSbyte
   addwf   INDF1,w     ; add 30 to BCDx register
   movwf   TEMP     ; store w
   btfsc   TEMP,7     ; test if >7
   movwf   INDF1     ; save as MS digit
   return       ; end subroutine



;**********************************************************************************
;
;
Output_Decimal:

   CLRF   BIN4     ;Clear top 3 bytes (Not used.)
   CLRF   BIN3
   CLRF   BIN2
  
   MOVF   DHT_Data0,W   ;Humidity high byte
   MOVWF   BIN2  

   MOVF   DHT_Data1,W   ;Humidity low byte
   MOVWF   BIN1  

   CALL   BIN_BCD

Output_Humidity:
   MOVLW   'H'
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit
  

   MOVF   ETWO, W
     CALL  SerialTransmit

   MOVF   EONE, W
     CALL  SerialTransmit

   MOVLW   '.'
     CALL  SerialTransmit

   MOVF   EZERO, W
     CALL  SerialTransmit

   MOVLW   '%'
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit

Output_Temp:

   CLRF   BIN4     ;Clear top 2 bytes (Not used.)
   CLRF   BIN3
   CLRF   BIN2
  
   MOVF   DHT_Data2,W   ;Temp high byte
   MOVWF   BIN2  

   MOVF   DHT_Data3,W   ;Temp low byte
   MOVWF   BIN1  

   CALL   BIN_BCD



   MOVLW   'T'
     CALL  SerialTransmit
   MOVLW   'e'
     CALL  SerialTransmit
   MOVLW   'm'
     CALL  SerialTransmit
   MOVLW   'p'
     CALL  SerialTransmit
   MOVLW   ' '
     CALL  SerialTransmit
   MOVLW   '+'
  
   BTFSC   DHT_Data2,7     ;Test sign bit
   MOVLW   '-'

     CALL  SerialTransmit

   MOVF   ETWO, W
     CALL  SerialTransmit

   MOVF   EONE, W
     CALL  SerialTransmit

   MOVLW   '.'
     CALL  SerialTransmit

   MOVF   EZERO, W
     CALL  SerialTransmit

   MOVLW   ' '
     CALL  SerialTransmit
   MOVLW   'C'
     CALL  SerialTransmit


   RETURN



   end
This code reads data from a DH22 temperature and humidity sensor and outputs it as an ASCII string via the HC-12. A reading is triggered by sending "#A" to it from the other HC-12.
The parts of the code that deal with the HC-12 are :-
Initialized EUSART
SerialTransmit:
SerialReceive:

The code will be very similar for other PICs

Les.
Thanks i will check it and get back to you on the same.
 
Top