' **************************************************************** ' * File: uk_gmb_iob.pbas - Ver. 1.1 * ' * Compiler: mikroBasic for PIC by mikroElektronica * ' * IDE: mikroBasic for PIC by mikroElektronica * ' * Compiler Version: 1.1.5.0 * ' * Boards: GMM 4620 + GMB HR168 * ' * GRIFO(R) via Dell'Artigiano 8/6 * ' * 40016 S. Giorgio di Piano (BO) * ' * Tel. +39 051 892052 Fax. +39 051 893661 * ' * http://www.grifo.com http://www.grifo.it * ' * by Graziano Gaiba del 22.02.05 * ' **************************************************************** ' ' This demo program allows to se immediatly both the relay outputs ' available respectively on connnectors CN3 and CN4 and the ' optocoupled inputs available respectively on connnectors CN1 and ' CN2. ' ' It is possible to see the status of the sixteen NPN/PNP inputs ' on the console or to set the status of the eight output relays. ' In addition the Mini Module peripherals can perform developed ' features like: hardware counted inputs, etc. ' ' Rel 1.1 - by Graziano Gaiba ' Demo program of buffered I/O peripherals of GMB HR168 driven by ' Mini Module GMM 4620 ' ' ' ******************** Compiler definitions ********************** ' program uk_gmb_iob ' ' ******************* Constants declaration ********************** ' const ASC_1 = 49 const ASC_2 = 50 ' ' ******************** Variables declaration ********************* ' ' Generic variables dim i as byte dim scelta as byte dim d_in as byte dim d_out as byte ' ' ' Used by interrupts dim cnt_int0 as byte dim cnt_int1 as byte ' ' ' Used by Timers dim cnt_tmr1_int as byte ' ' ' **************** Procedures definition ****************** ' ' ' CPU and signals directions initialization sub procedure Init_cpu ADCON1=$0f ' Imposta come I/O digitale i pin AN0..12 CMCON=$07 ' Imposta come I/O digitale RA0..4 ' Optocoupled Inputs of CN1 are: ' IN1-1 <-> RA0 ' IN2-1 <-> RA1 ' IN3-1 <-> RB0 ' IN4-1 <-> RB1 ' IN5-1 <-> RA4 ' IN6-1 <-> RC0 ' IN7-1 <-> RC1 ' IN8-1 <-> RC5 trisa.0=1 trisa.1=1 trisa.4=1 trisb.0=1 trisb.1=1 trisc.0=1 trisc.1=1 trisc.5=1 ' Optocoupled Inputs of CN2 are: ' IN1-2 <-> RD0 ' IN2-2 <-> RD1 ' IN3-2 <-> RD2 ' IN4-2 <-> RD3 ' IN5-2 <-> RD4 ' IN6-2 <-> RD5 ' IN7-2 <-> RD6 ' IN8-2 <-> RD7 trisd=$ff ' Relay outputs of CN3 are: ' OUT A1 <-> RB4 ' OUT A2 <-> RB5 ' OUT B1 <-> RB6 ' OUT B2 <-> RB7 ' OUT C1 <-> RB3 ' OUT C2 <-> RB2 trisb=trisb and $03 ' Relay outputs of CN4 are: ' OUT D1 <-> RA3 ' OUT D2 <-> RC2 (J10 in position 3-4) trisa.3=0 trisc.2=0 ' Initialize module USART (8 bit, 19200 baud rate, ' no parity) Usart_init(19200) end sub ' ' ' Send a string of characters to the serial port sub procedure print_USART(dim byref txt as char[255]) dim i as byte dim l as byte l = txt[0] for i = 1 to l USART_Write(txt[i]) next i end sub ' ' ' Send CR + LF sub procedure print_CRLF USART_Write(10) USART_Write(13) end sub ' ' ' Clear screen, sending 25 times CR + LF. sub procedure clrscr for i = 0 to 24 print_CRLF next i end sub ' ' ' Asks for a key press sub procedure wait_key dim c as byte print_usart("Press a key...") do nop loop until USART_Data_Ready = 1 c = USART_Read end sub ' ' ' Procedure to set the status of the relays on connectors CN3 and CN4. ' According to the bits of port_val, each relay is turned ON ' (contact closed) or OFF (contact open). ' Bits of port_val have this meanging: ' -- CN3 ' port_val.0 drives relay OUT A1 ' port_val.1 drives relay OUT A2 ' port_val.2 drives relay OUT B1 ' port_val.3 drives relay OUT B2 ' port_val.4 drives relay OUT C1 ' port_val.5 drives relay OUT C2 ' -- CN4 ' port_val.6 drives relay OUT D1 ' port_val.7 drives relay OUT D2 ' ' Each bit has the following meaning: ' bit Meaning ' 0 Relay turned OFF (contact open) ' 1 Relay turned ON (contact closed) sub procedure set_relays(dim port_val as byte) ' Relays are driven in complemented logic, so port_val must be ' complemented too port_val=port_val xor $ff portb.4=port_val.0 portb.5=port_val.1 portb.6=port_val.2 portb.7=port_val.3 portb.3=port_val.4 portb.2=port_val.5 porta.3=port_val.6 portc.2=port_val.7 end sub ' ' ' Procedure to read the status of optocoupled inputs on connector CN1. ' Bits of port_val have this meanging: ' port_val.0 is status of IN1-1 ' port_val.1 is status of IN2-1 ' port_val.2 is status of IN3-1 ' port_val.3 is status of IN4-1 ' port_val.4 is status of IN5-1 ' port_val.5 is status of IN6-1 ' port_val.6 is status of IN7-1 ' port_val.7 is status of IN8-1 ' ' According to the bits of port_val, each input is closed or open. ' Each bit has the following meaning: ' bit Meaning ' 0 Contact open ' 1 Contact closed sub function get_opto_1 as byte dim port_val as byte port_val.0 = porta.0 port_val.1 = porta.1 port_val.2 = portb.0 port_val.3 = portb.1 port_val.4 = porta.4 port_val.5 = portc.0 port_val.6 = portc.1 port_val.7 = portc.5 ' Optocoupled inputs are driven in complemented logic, ' so port_val must be complemented too port_val = port_val xor $ff Result = port_val end sub ' ' ' Procedure to read the status of optocoupled inputs on connector CN2. ' Bits of port_val have this meanging: ' port_val.0 is status of IN1-2 ' port_val.1 is status of IN2-2 ' port_val.2 is status of IN3-2 ' port_val.3 is status of IN4-2 ' port_val.4 is status of IN5-2 ' port_val.5 is status of IN6-2 ' port_val.6 is status of IN7-2 ' port_val.7 is status of IN8-2 ' ' According to the bits of port_val, each input is closed or open. ' Each bit has the following meaning: ' bit Meaning ' 0 Contact open ' 1 Contact closed sub function get_opto_2 as byte dim port_val as byte ' Optocoupled inputs are driven in complemented logic, ' so port_val must be complemented too port_val = portd xor $ff Result = port_val end sub ' ' ' Sends its argument to the serial port as two hexadecimal figures. sub procedure print_HEX_2(dim value as byte) dim tmp as byte ' Most significant nibble tmp = value >> 4 ' If greater than 9, transform it in a char from 'A' if tmp > 9 then tmp = tmp + 55 else ' Transform it in a char from '0' tmp = tmp + 48 end if USART_Write(tmp) ' ' Least significant nibble tmp = value and $0f ' If greater than 9, transform it in a char from 'A' if tmp > 9 then tmp = tmp + 55 else ' Transform it in a char from '0' tmp = tmp + 48 end if USART_Write(tmp) end sub ' ' ' Check if the input parameter is an hexadecimal digit. sub function is_HEX_digit(dim v as byte) as byte dim flag as byte flag = 0 if (v >=48) and (v <= 57) then flag = 1 end if if (v >= 65) and (v <= 70) then flag = 1 end if if (v >= 97) and (v <= 102) then flag = 1 end if Result = flag end sub ' ' ' Returns the value of a single hexadecimal digit. ' Does NOT check if input parameter is an hexadecimal digit. sub function HEX_val(dim v as byte) as byte v = v - 48 if v > 9 then v = v - 17 if v > 5 then v = v - 32 end if v = v + 10 end if Result = v end sub ' ' ' Inputs an hexadecimal vale of up to four digits. ' Input parameter is number of digits, it returns an interger ' containing the value input by te user. ' It can manage backspace (ASCII 08) and accepts digits from ' '0' to '9', from 'a' to 'f' and from 'A' to 'F'. ' It sends a bell character (ASCII 07) when receives a character ' not acceptable for input, or user tries to input or delete out ' of possible range. sub function inputHEX(dim n_char as byte) as word dim str_input as byte[6] dim idx as byte dim chr_input as byte dim pow_of_16 as word[5] dim value as word pow_of_16[1] = 1 pow_of_16[2] = 16 pow_of_16[3] = 256 pow_of_16[4] = 4096 ' Index must start from 1 idx = 1 Inc(n_char) ' No character in input chr_input = 0 ' Starting value value = 0 ' Loop until CR is received while chr_input <> 13 ' If a data is ready if usart_data_ready = 1 then ' Read it chr_input = USART_Read ' If backspace (ASCII BS) if chr_input = 8 then ' and buffer is not empty if idx > 1 then ' Send data read USART_Write(chr_input) ' Delete character USART_Write(32) USART_Write(chr_input) ' delete last input data Dec(idx) else ' Bell to indicate an error USART_Write(7) end if end if ' If CR received, elaborate the value and return it if chr_input = 13 then n_char = 0 while idx > 1 Dec(idx) Inc(n_char) value = value + HEX_val(str_input[n_char]) * pow_of_16[idx] wend else ' If character can be input if idx < n_char then ' If data received is in valid range: ' 0..9 or 'a'..'f' or 'A'..'F' if is_HEX_digit(chr_input) = 1 then ' Send data read USART_Write(chr_input) ' Store it in input buffer str_input[idx] = chr_input ' Point to next position Inc(idx) end if else ' Bell to indicate an error USART_Write(7) end if end if end if wend print_CRLF Result = value end sub ' ' ' Demo of optocoupled digital inputs sub procedure digital_inputs clrscr print_USART("Demo of optocoupled inputs section") print_CRLF print_CRLF print_USART("Status of inputs of CN1 and CN2 is continuously visualized") print_CRLF print_USART("Press a key to exit.") print_CRLF print_CRLF print_USART("CN1 CN2") print_CRLF do d_in = get_opto_1 print_USART(" ") print_HEX_2(d_in) d_in = get_opto_2 print_USART(" ") print_HEX_2(d_in) USART_Write(13) Delay_ms(200) loop until USART_Data_Ready = 1 i = USART_Read print_CRLF print_CRLF ' ' print_USART("IN3 and IN4 of CN1 are connected respectively to interrupts INT0 and INT1.") print_CRLF print_USART("Each falling edge on an input triggers respective interrupt, which increments") print_CRLF print_USART("a counter. The counters are continuously visualized.") print_CRLF print_USART("Press a key to exit.") print_CRLF print_CRLF print_USART("Count of: INT0 INT1") print_CRLF ' Disable priority interrupts rcon.7 = 0 ' Trigger INT0 and INT1 on falling edges intcon2.6 = 0 intcon2.5 = 0 ' Enable INT0 and INT1 intcon.4 = 1 intcon3.3 = 1 ' Peripheral interrupts enable and global interrupts enable intcon.6 = 1 intcon.7 = 1 ' Init interrupts counters cnt_int0 = 0 cnt_int1 = 0 do print_USART(" ") print_HEX_2(cnt_int0) print_USART(" ") print_HEX_2(cnt_int1) USART_Write(13) Delay_ms(50) loop until USART_Data_Ready = 1 i = USART_Read print_CRLF print_CRLF ' Global interrupts disable and peripheral interrupts disable intcon.7 = 0 intcon.6 = 0 ' Disable INT0 and INT1 intcon3.3 = 0 intcon.4 = 0 ' ' print_USART("IN5 and IN6 of CN1 are connected respectively to the external clock of") print_CRLF print_USART("Timer 0 and Timer 1.") print_CRLF print_USART("Each falling edge for Timer 0 and rising edge for Timer 1 triggers timer,") print_CRLF print_USART("which increments its hardware counter.") print_CRLF print_USART("Also, overflow of Timer 1 generate a counted interrupt.") print_CRLF print_USART("The counters are continuously visualized.") print_CRLF print_USART("Press a key to exit.") print_CRLF print_CRLF print_USART("Value of: Timer 0 Timer 1 Count of: Timer 1 overflow interrupt") print_CRLF ' Init counters tmr0h = 0 tmr0l = 0 tmr1h = $ff tmr1l = $f0 ' Init Timer 1 interrupt counter cnt_tmr1_int = 0 ' Configure Timer 0 for 16 bit, trigger falling edges of T0CKI, no prescaler t0con = $b8 ' Configure Timer 1 for trigger falling edges of T13CKI, no prescaler t1con = $83 ' Disable priority interrupts rcon.7 = 0 ' Enable Timer 1 overflow interrupt pie1.0 = 1 ' Peripheral interrupts enable and global interrupts enable intcon.6 = 1 intcon.7 = 1 do print_USART(" ") print_HEX_2(tmr0h) print_HEX_2(tmr0l) print_USART(" ") print_HEX_2(tmr1h) print_HEX_2(tmr1l) print_USART(" ") print_HEX_2(cnt_tmr1_int) USART_Write(13) Delay_ms(50) loop until USART_Data_Ready = 1 i = USART_Read print_CRLF print_CRLF ' Global interrupts disable and peripheral interrupts disable intcon.7 = 0 intcon.6 = 0 ' Disable Timer 1 overflow interrupt pie1.0 = 0 end sub ' ' ' All interrupts manager sub procedure interrupt if intcon.1 = 1 then intcon.1 = 0 cnt_int0 = cnt_int0 + 1 end if if intcon3.0 = 1 then intcon3.0 = 0 cnt_int1 = cnt_int1 + 1 end if if pir1.0 = 1 then pir1.0 = 0 cnt_tmr1_int = cnt_tmr1_int + 1 end if end sub ' ' ' Demo of relay output sub procedure relay_outputs clrscr print_USART("Demo of relay outputs section") print_CRLF print_CRLF do print_USART("Insert two hexadecimal digits to set relay status (00 to exit): ") d_out = inputHEX(2) set_relays(d_out) loop until d_out = 0 end sub ' '************************** Main Program ******************************* ' main: Init_cpu ' Turn OFF relays set_relays(0) for_ever: clrscr print_CRLF print_CRLF print_USART("Buffered I/O demo Rel 1.1 for GMM 4620 rel 120304 and GMB HR168 rel 110104") print_CRLF print_CRLF print_USART("1) Digital inputs") print_CRLF print_USART("2) Relay outputs") print_CRLF input_scelta: print_CRLF print_USART("choice: ") do nop loop until USART_Data_Ready = 1 scelta = USART_Read select case scelta case ASC_1 digital_inputs case ASC_2 relay_outputs case else goto input_scelta end select goto for_ever end.