Version:0.9 StartHTML:0000000105 EndHTML:0000081438 StartFragment:0000001119 EndFragment:0000081422 mikroIDE
program Temperature_sensor
'-------------------------------------------------------------------------------
'AUTORE: Marco Massari
'DATA: 03/2010
'DESCRIZIONE: Programma gestione sensore di temperatura sistema MassaBus
' ------------------------------------------------------------------------------
'Dichiarazione variabili registri I/O
dim led_activity as sbit at portb.7
dim tx_uart_enable as sbit at txsta.5
dim rx_uart_enable as sbit at rcsta.4
dim RS485_bus_direction as sbit at portb.3
dim program_button as sbit at portb.5
'-------------------------------------------------------------------------------
'Dichiarazione variabili flag timer
dim tmr1_enable as sbit at t1con.0
dim tmr1_interrupt as sbit at pir1.0
'-------------------------------------------------------------------------------
'I/O Sensore
dim port_sensor as byte at PORTA
const sensor_pin = 4 register
'-------------------------------------------------------------------------------
'Dichiarazione variabili memoria
dim adr_m as byte
dim adr_s as byte
dim adr_sender_test as byte
dim get_data_received as string[11]
dim string_compose as string[11]
dim temp_byte_1 as byte
dim temp_byte_2 as byte
dim sensor_present as byte
dim read_request as byte
dim last_send_data as string[11]
dim correct_packet as byte
dim address_packet as byte
dim type_packet  as byte
dim data1_packet as byte
dim data2_packet as byte
dim count_tmr1 as byte
dim conversion_complete as byte
'-------------------------------------------------------------------------------
'Dischiarazione costante device type (tipologia dispositivo)
const device_type as byte =  84 'dispositivo tipo T
'Cicli ritardo lettura sensore (dipende da clock, a 4Mhz, 2)
const delay_cicle as byte = 1
'-------------------------------------------------------------------------------
'Procedura Interrupt
 sub procedure interrupt
 'Se interrupt provocato da Timer1 (OverFlow)
   if tmr1_interrupt then
    'Resetto il flag di interrupt timer
    tmr1_interrupt = 0
    'Essendo (a 4 Mhz) la frequenza degli interrupt di 2Hz (500ms)
    'il delay_byte viene moltiplicato * 2 per ottenere un delay_byte
    'pari ai secondi di intervallo
    if (count_tmr1 = delay_cicle) then
     'Resetto i registri del timer
      tmr1h = 0
      tmr1l = 0
     'Resetto variabile di conteggio interrupt timer
      count_tmr1 = 0
      conversion_complete.0 = 1
    else 'altrimenti incremento count_tmr1
     count_tmr1 = count_tmr1 + 1
    end if
   end if
 end sub
'---------------------------------------------------------------
sub procedure send_data(dim byref datasend as string[11])
last_send_data = datasend
led_activity = 1 'attiva led per segnalare invio
delay_ms(5)'Attende il rilascio del bus
tx_uart_enable = 1 'abilita invio seriale
RS485_bus_direction = 1 'seleziona la direzione di comunicazione
delay_us(400'attende attivazione MAX485
UART1_Write_Text(datasend) 'invia la stringa generata
delay_ms(2'attende invio dei segnali
led_activity = 0 'disattiva led attivitā
RS485_bus_direction = 0 'seleziona la direzione di comunicazione (in ascolto)
tx_uart_enable = 0 'disabilita invio seriale
end sub
'-------------------------------------------------------------------------------
'Procedura invio dati su bus
sub procedure code_data_to_send(dim address_master_send as bytedim type_s as byte,
dim data1_s as bytedim data2_s as byte)
'Dichiarazione varibili
dim checksum_send as byte
dim checksum_send_low as byte
dim checksum_send_hi as byte
dim type_to_send as byte
dim data_send_1 as byte
dim data_send_2 as byte
dim address_slave_send as byte
'sposto di 2 bit il tipo di pacchetto
type_to_send = type_s * 4
'se č in bradcast inserico indirizzo 255
if (address_master_send <> 255then
 address_slave_send = adr_s
else
 address_slave_send = 255
end if
'Verifico la presenza dei dati a 0
if (data1_s = 0then
 data_send_1 = 48
 type_to_send.0 = 1
else
 data_send_1 = data1_s
end if
if (data2_s = 0then
 data_send_2 = 48
 type_to_send.1 = 1
else
 data_send_2 = data2_s
end if
'Costruisco i byte di checksum
checksum_send = address_master_send xor address_slave_send xor type_to_send xor data_send_1 xor data_send_2
checksum_send_low = (checksum_send and 15or 128
checksum_send_hi =  (checksum_send / 16or 128
'Compongo la stringa da inviare
string_compose[0] = "S"
string_compose[1] = address_master_send
string_compose[2] = address_slave_send
string_compose[3] = type_to_send
string_compose[4] = data_send_1
string_compose[5] = data_send_2
string_compose[6] = checksum_send_low
string_compose[7] = checksum_send_hi
string_compose[8] = 3
string_compose[9] = 3
string_compose[10] = 3
string_compose[11] = 0
send_data(string_compose)
end sub
'-------------------------------------------------------------------------------
'Procedura decodifica dati ricevuti su bus
sub procedure decode_ric_data(dim byref array_in_data as string[11], dim byref correct_data as byte,
 dim byref address_ric as bytedim byref address_master as bytedim byref type_ric as byte,
 dim byref data1_ric as bytedim byref data2_ric as byte)
'Dichiarazione variabili
dim chk_low as byte
dim chk_hi as byte
dim checksum as byte
dim calcolated_checksum as byte
correct_data = 0
'Verifico la correttezza del pacchetto
if (array_in_data[0] = 83then 'se start byte č corretto
    'il controllo della terminazione del pacchetto viene effettuata dalla procedura di lettura seriale
    'Ricostruzione byte checksum
     chk_low = array_in_data[6and 15
     chk_hi = array_in_data[7and 15
     checksum = (chk_hi * 16or chk_low 'mette insieme i 2 byte per ricostruire il byte di checksum
     'Controllo del dato ricevuto con checksum
     calcolated_checksum = array_in_data[1xor array_in_data[2xor array_in_data[3xor array_in_data[4xor array_in_data[5]
     if (calcolated_checksum = checksum) and (array_in_data[6].7 = 1and (array_in_data[7].7 = 1then 'se il checksum č corretto
      address_ric = array_in_data[1]
      address_master = array_in_data[2]
      type_ric = (array_in_data[3and 252)/4 'preleva il byte che seleziona il tipo di chiamata
      'eliminando gli zero flag inseriti
      if (array_in_data[4] = 48and (array_in_data[3].0 = 1then 'se data1 č uguale a zero (controllo zero flag 1)
       data1_ric = 0
       else 'altrimenti viene copiato il byte
       data1_ric = array_in_data[4]
      end if
      if (array_in_data[5] = 48and (array_in_data[3].1 = 1then 'se data2 č uguale a zero (controllo zero flag 2)
       data2_ric = 0
       else 'altrimenti viene copiato il byte
       data2_ric = array_in_data[5]
      end if
      'imposto il flag di pacchetto corretto a 1
      correct_data = 1
     end if
end if
end sub
'-------------------------------------------------------------------------------
'Procedura attivazione conversione sensore
sub procedure start_conversion_temp()
'Do il comando di reset
sensor_present = Ow_Reset(port_sensor, sensor_pin)
'inverto il valore di sensor present essendo restituito in logica negata
sensor_present = not sensor_present 'inverto sato logico
'Do il comando di partenza della conversione
Ow_Write(port_sensor, sensor_pin, 0xCC)
Ow_Write(port_sensor, sensor_pin, 0x44)
'Solo se il sensore č presente
if sensor_present.0 then
 'Resetto timer
 tmr1h = 0
 tmr1l = 0
 count_tmr1 = 0
 'Abilito timer
 tmr1_enable = 1
end if
end sub
'-------------------------------------------------------------------------------
'Procedura lettura temperatura convertita
sub procedure read_temp()
'Resetto il sensore
Ow_Reset(port_sensor, sensor_pin)
'Invio comandi di lettura
Ow_Write(port_sensor, sensor_pin, 0xCC)
Ow_Write(port_sensor, sensor_pin, 0xBE)
'Salvo i valori di temperatura ricevuti
temp_byte_1  = Ow_Read(port_sensor, sensor_pin)
temp_byte_2 = Ow_Read(port_sensor, sensor_pin)
'Disattivo timer
tmr1_enable = 0
'-------------------------------------------------------------------------------
end sub

main'inizio programma
cmcon = $07 'disabilito modulo CCP
trisa = $FF 'configura gli i/o di porta (bin 11111111)
trisb = $73 'configura gli i/o di portb (bin 01110011)
porta = 0 'reset delle porte
portb = 0
'---------------------------------------------------
'Configurazione Interrupt e timer1
INTCON = $C0
PIE1 = $01
PIR1 = $00
T1CON = $34
'---------------------------------------------------
'Reset dei timer
tmr1_enable = 0
tmr1h = 0
tmr1l = 0
count_tmr1 = 0
conversion_complete = 0
'---------------------------------------------------
uart1_init(9600'inizializzazione uart hardware pic a 9600 bps
tx_uart_enable = 0 'disabilita invio seriale
rx_uart_enable = 0 'diabilita ricezione seriale
adr_m = EEPROM_Read($00'Prelievo degli indirizzi dalla EEPROM
adr_s = EEPROM_Read($01)
'---------------------------------------------------
'Procedura rilevazione sensore
led_activity = 1 'attivo led
'Per verificare la presenza del sensore
start_conversion_temp() 'effettuo una lettura di temperatura
delay_ms(750)'Attendo conversione
if (sensor_present.0 = 1then 'se il sensore č presente disattivo led
 led_activity = 0
end if
'--------------------------------------------------
get_data_received = "" 'azzero dato ricezione
read_request = 0 'azzera la richiesta di lettura
rx_uart_enable = 1  'abilito ricezione seriale
'----------------------------------------------------
'Loop programma principale
while true
   clrwdt 'resetto watchdog timer
   if conversion_complete.0 then
    conversion_complete.0 = 0
    read_temp()
   end if
   if (UART1_Data_Ready() = 1)  then
     UART1_Read_Text(get_data_received, ""11'la trama termina con 3 byte 3
     rx_uart_enable = 0 'disabilita ricezione UART
     delay_ms(2'attende 2ms prima di far partire la procedura
     decode_ric_data(get_data_received, correct_packet, address_packet, adr_sender_test, type_packet, data1_packet, data2_packet)
     if (correct_packet = 1then 'risposnde solo se il pacchetto č corretto ed inviato dal master
         if (adr_s = address_packet) and (adr_sender_test = adr_m) and (program_button = 0then
          select case type_packet
           case 1
            if (data1_packet = 63and (data2_packet = 0then
              code_data_to_send(adr_m,1,33,device_type)
            end if
           '---------------------------------------------------------------
           'Procedura lettura sensore e invio lettura
           case 20
            if (data1_packet = 63and (data2_packet = 0then
              if sensor_present.0 then 'se rileva il sensore
               'Invia conferma partenza conversione (solo se non giā richiesto)
               if (tmr1_enable = 0then
                start_conversion_temp() 'chiama la funzione di lettura temperatura
                code_data_to_send(adr_m,20,83,0)
               else 'se il timer č attivo (conversione in corso)
                code_data_to_send(adr_m,63,5,0'Invio errore conversione ancora in corso
               end if
              else
               code_data_to_send(adr_m,63,4,0)'invio errore sensore temperatura non rilevato
              end if
              'Resetto il flag che contiene le richieste di lettura
              read_request.0 = 0
            end if
            '---------------------------------------------------------------
            'Procedura invio ultima lettura (con verifica)
           case 21
            if (data1_packet = 63and (data2_packet = 0then
              if read_request.0 and sensor_present.0 then 'Verifica se č la prima richiesta di lettura
               'e se č presente il sensore
               'se si invio l'ultima lettura
               if (tmr1_enable = 0then
                code_data_to_send(adr_m,21,temp_byte_1,temp_byte_2)
                read_request.0 = 0 'resetto registro prima lettura
               else 'se il timer č attivo (conversione in corso)
                code_data_to_send(adr_m,63,5,0'Invio errore conversione ancora in corso
               end if
               else 'altrimenti
               if sensor_present.0 then 'se il sensore č presente
                 code_data_to_send(adr_m,63,3,0'invia codice errore lettura senza richiesta (errore 3)
               else
                 code_data_to_send(adr_m,63,4,0)'invio errore sensore temperatura non rilevato
               end if
              end if
            end if
            '---------------------------------------------------------------
            'Procedura invio ultima lettura (senza verifica)
           case 22
            if (data1_packet = 63and (data2_packet = 0then
              if sensor_present.0 then
               if (tmr1_enable = 0then
                code_data_to_send(adr_m,22,temp_byte_1,temp_byte_2)
               else 'se il timer č attivo (conversione in corso)
                code_data_to_send(adr_m,63,5,0'Invio errore conversione ancora in corso
               end if
              else
               code_data_to_send(adr_m,63,4,0)'invio errore sensore temperatura non rilevato
              end if
            end if
            '---------------------------------------------------------------
           case 63 'ricevuto codice errore
            if (data1_packet = 2and (data2_packet = 0then 'se l'invio precedente era errato (errore 2)
              send_data(last_send_data) 'reinvia l'ultimo dato
            end if
            '---------------------------------------------------------------
           end select
          else 'se gli indirizzi non sono di uso normale
           if (address_packet = 255and (adr_sender_test = 255then 'indirizzo che richiama tutti i dispositivi
            select case type_packet
            '---------------------------------------------------------------
            'Programmazione indirizzi
             case 60
              if (program_button = 1then 'solo se il selettore č im modalitā programmazione parte la procedura
                if (data1_packet <> 0and (data2_packet <> 0and (data1_packet < 255and
                 (data2_packet < 255and (data1_packet <> data2_packet) then
                 EEPROM_Write($00, data1_packet) 'scrivo i nuovi indirizzi in EEPROM
                 EEPROM_Write($01, data2_packet)
                 code_data_to_send(255,60,65,79'invia pacchetto programmazione corretta
                 led_activity = 1
                 delay_ms(1000)
                 led_activity = 0
                else
                 code_data_to_send(255,63,1,0'invia pacchetto programmazione errata (errore 1)
                 led_activity = 1
                 delay_ms(50)
                 led_activity = 0
                end if
              end if
              '------------------------------------------------------------
              'Richiesta lettura temperatura(senza invio)
             case 5052
              if (data1_packet = 63and (data2_packet = 0and (program_button = 0)  then
               if (tmr1_enable = 0then 'solo se non giā chiamata fa partire la conversione
                start_conversion_temp() 'chiama la funzione di lettura temperatura
               end if
               if sensor_present.0 then 'se rileva il sensore
                read_request.0 = 1
               else 'altrimenti
                read_request.0 = 0
               end if
               led_activity = 1  'Segnalo con l'attivazione del led l'attivitā
               delay_ms(20)
               led_activity = 0
              end if
              '-------------------------------------------------------------
             end select
           end if
         end if
     end if
      get_data_received = "" 'Svuoto buffer ricezione
      rx_uart_enable = 1 'Abilita ricezione UART
   end if
wend
end.