Version:0.9 StartHTML:0000000105 EndHTML:0000081438 StartFragment:0000001119 EndFragment:0000081422
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 byte, dim type_s as byte,
dim data1_s as byte, dim 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 <> 255) then
address_slave_send = adr_s
else
address_slave_send = 255
end if
'Verifico la presenza dei dati a 0
if (data1_s = 0) then
data_send_1 = 48
type_to_send.0 = 1
else
data_send_1 = data1_s
end if
if (data2_s = 0) then
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 15) or 128
checksum_send_hi = (checksum_send / 16) or 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 byte, dim byref address_master as byte, dim byref type_ric as byte,
dim byref data1_ric as byte, dim 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] = 83) then '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[6] and 15
chk_hi = array_in_data[7] and 15
checksum = (chk_hi * 16) or chk_low 'mette insieme i 2 byte per ricostruire il byte di checksum
'Controllo del dato ricevuto con checksum
calcolated_checksum = array_in_data[1] xor array_in_data[2] xor array_in_data[3] xor array_in_data[4] xor array_in_data[5]
if (calcolated_checksum = checksum) and (array_in_data[6].7 = 1) and (array_in_data[7].7 = 1) then 'se il checksum č corretto
address_ric = array_in_data[1]
address_master = array_in_data[2]
type_ric = (array_in_data[3] and 252)/4 'preleva il byte che seleziona il tipo di chiamata
'eliminando gli zero flag inseriti
if (array_in_data[4] = 48) and (array_in_data[3].0 = 1) then '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] = 48) and (array_in_data[3].1 = 1) then '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 = 1) then '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 = 1) then 'risposnde solo se il pacchetto č corretto ed inviato dal master
if (adr_s = address_packet) and (adr_sender_test = adr_m) and (program_button = 0) then
select case type_packet
case 1
if (data1_packet = 63) and (data2_packet = 0) then
code_data_to_send(adr_m,1,33,device_type)
end if
'---------------------------------------------------------------
'Procedura lettura sensore e invio lettura
case 20
if (data1_packet = 63) and (data2_packet = 0) then
if sensor_present.0 then 'se rileva il sensore
'Invia conferma partenza conversione (solo se non giā richiesto)
if (tmr1_enable = 0) then
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 = 63) and (data2_packet = 0) then
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 = 0) then
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 = 63) and (data2_packet = 0) then
if sensor_present.0 then
if (tmr1_enable = 0) then
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 = 2) and (data2_packet = 0) then '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 = 255) and (adr_sender_test = 255) then 'indirizzo che richiama tutti i dispositivi
select case type_packet
'---------------------------------------------------------------
'Programmazione indirizzi
case 60
if (program_button = 1) then 'solo se il selettore č im modalitā programmazione parte la procedura
if (data1_packet <> 0) and (data2_packet <> 0) and (data1_packet < 255) and
(data2_packet < 255) and (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 50, 52
if (data1_packet = 63) and (data2_packet = 0) and (program_button = 0) then
if (tmr1_enable = 0) then '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.