PDA

View Full Version : Interrupt and Serial communication to PC.



obaskirt
- 12th June 2005, 15:10
I have a DS1820 one wire digital temp. sensor, I designed a temperature measurement and control circuit and I used PIC16F877, I connected a led on PORTB7 and I wrote a pc program with C# 2005 Beta 2. In PC program I made a two buttons (turn led off and turn led on) . Led initial condititon is off. When I pressed turn on Led have to tuurn on. And also when I pressed turn off, led have to turn off. But there is a tricky problem. I used SERIN comand for receiving data, but when PBP code came to that command it waited a response from PC so for solving that problem I used a THREAD in PC program I send "0" every 2 seconds and when "0" sending to the pic, pic goes to the mainloop. When I send "1" , then PIC turns off the led, when I send "2" pic turns on the led. But When thread is starting, I mean when pc send "0" automatically and after that you pressed "1" or "2" PBP not respond this. Because when PC send "0" PBP program goes to mainloop and after a little time later if you press "1" or "2" PBP program maybe is not at line where SERIN command exist so both of the buttons wont work. I increased timeout but anyway this means wait at serin command for example 5 second then if user dis not pressed any button send "0" to PIC. This is not a exact solution. Exact solution is using INTERRUPT. But ı could not accomplish that. Please help me... How to use interrupt for this program??? I mean when interrupt comes to pic from usart ("1", or "2") then pic will leave current job and jump to the if value is "1" turn on the led or value is "2" turn off the led after this process resume previous position in the main loop. Thanks for your attention...

mister_e
- 12th June 2005, 17:03
Assuming that you have a MAX232 attach between your PIC and your PC, here is something to play with.



'
' Simple program to handle USART interrupt using PIC16F877 @20MHZ
' ================================================== =============
'
' This program will Blink a LED on PORTB.0 to show
' that the PIC is running.
'
' This program also allow the user to activate or deactivate
' a LED connected on PORTB.1 pin by sending command from a PC
' terminal software using 9600,n,8,1 setting
'
' User command:
' =============
' 1. If character "1" is received => enable the LED
' 2. if character "2" is received => disable the LED
'
'
DEFINE LOADER_USED 1 ' using bootloader
DEFINE OSC 20 ' running at 20 MHZ

' PORT setting
' ============
'
TRISC=%10000000 ' RC.7 => USART RX pin set to input
' all other pin set to output
'
TRISB=0 ' RB<7:0> set to output

' USART setting
' =============
' Since we will not use HSERIN/HSEROUT, we must
' write directly to internal PIC register
'
TXSTA=$24 ' enable transmit and SPBRGH=1
RCSTA=$90 ' Enable USART and continuous receive
SPBRG=129 ' BAUD RATE = 9600 BAUDS

' Interrupt definition
' ====================
'
PIE1.5 =1 ' enable USART receive interrupt
INTCON.6 =1 ' enable peripheral interrupt

' Alias definition
' ================
'
RCIF var PIR1.5 ' receiver interrupt
StatusLED var PORTB.0 ' the LED who show a 'running process'
UserLED var PORTB.1 ' the LED that user want to control

' Variable definition
' ===================
'
Delay var word '
DataIn var byte ' use to store RCREG content
Discard var byte ' use to erase RCREG register

' Hardware/software initialisation
' ================================
'
PORTB=0 ' clear PORTB
on interrupt goto USARTInterrupt

Start:
' Main program loop that make the user happy to
' see a LED flashing to mean that something is
' running
'
toggle statusled
for delay = 1 to 5000 ' use a loop delay to ensure
pauseus 5 ' getting interrupt as fast as
next ' possible
goto start


disable interrupt
USARTInterrupt:
' Here's the interrupt routine who will make the user
' much happy by giving him the feeling to have the
' control on the machine when the status of the user
' LED will change
'
RCSTA=0 ' Disable serial port AND
' clear possible error (FERR,OERR)

datain=RCREG ' Get data

while RCif ' wait untill the RCREG is empty
discard=RCREG ' by reading it and store result in a
wend ' don't care variable

select case datain ' What to do with that data???

case "1" ' User selection = 1
userled=1 ' => Enable the LED

case "2" ' User selection =2
userled=0 ' => disable the LED

end select
RCSTA=$90 ' Re-enable the serial PORT AND
resume ' get out of here
enable interrupt

obaskirt
- 17th June 2005, 20:01
Thank you for the code. I have just learned interrupts thanks to your code. But I have solved my problem in PC programming part. I have made some modifications in my algorithm but I think interrupts is more powerful than threads. Anyway I have not enough information about assembly language and some of the complex PBPro instruction (ex: on interrupt). Do you know links that I will find sufficient informations about these topics.

Yes I used MAX232 voltage level converter. I used PIC16F877-04/P, 4 MHZ Crystal, comminication rate is 2400 Baud. I am gonna try that code.
My current code is below, I have to fix some unnecessary declerations and variables, I have played that codes several times. Also I will try to use interrupts. But I am a newbie so maybe I will get lost in some complex timing analysis problems. Hopefully, you will help me.

Additionaly in my graduation project presentation my instructor asked: "what is DS1820's baud rate?". My PIC baud rate is 2400, in pc program I set baud rate 2400 , but I dont know DS1820's baud rate??? I have confused. If you know something about that please answer it.


' --------------------- [DIGITAL TEMPERATURE MEASUREMENT and CONTROL]-----------------------

temperature VAR WORD ' Temperature storage. (for storing measured value)
count_remain VAR BYTE ' Count remaining
count_per_c VAR BYTE ' Count per degree C
tempc VAR WORD
DQ VAR PORTC.2 ' One-wire data pin. (Ds1820's Dq line connected to RC2)
RX VAR WORD ' Receive byte from PC.
counter VAR BYTE ' Counter for Automatic Control
state VAR BYTE
maxtemp VAR BYTE
mintemp VAR BYTE

OUTPUT PORTB.5 ' Set portb pin 0 to an output. For LED. (or -> TRISB.0 = 0)
OUTPUT PORTB.7 ' device
INPUT PORTB.1 ' Set portb pin 1 to an input. (or -> TRISB.1 = 1)
OUTPUT PORTC.5 ' Sound output pin. Set portc pin 5 to an output (or -> TRISC.5 = 0)
OUTPUT PORTC.6 ' Serial comm. output pin. Set portc pin 6 to an output. (or -> TRISC.6 = 0)
INPUT PORTC.7 ' Serial comm. input pin. Set portc pin 7 to an input. (or -> TRISC.7 = 1)

'---------------------------------------------[Includes/Defines]-----------------------------------------------

DEFINE LCD_DREG PORTD ' I/O port with LCD. (Defining LCD data port)
DEFINE LCD_DBIT 4 ' When using a 4 bit data bus, (0 or 4) designate beginning of data bits.
DEFINE LCD_RSREG PORTD ' Defining LCD's register port.
DEFINE LCD_RSBIT 2 ' Register select pin.
DEFINE LCD_EREG PORTD ' Defining LCD's enable port.
DEFINE LCD_EBIT 3 ' Defining LCD's enable pin.
DEFINE LCD_BITS 4 ' Defining LCD has 4-bit data bus
DEFINE LCD_LINES 2 ' LCD has two charecter lines
INCLUDE "modedefs.bas" ' Including serial modes.

' Set PORTA and PORTE to digital. Any PICmicro MCU with analog inputs, such as the PIC16C7xx,
' PIC16F87x and PIC12C67x series devices, will come up in analog mode.
' You must set them to digital if that is how you intend to use them: ADCON1 = 7
ADCON1 = 7
PAUSE 100 ' Pause for starting LCD

'-------------------------------------------------[Main Code]---------------------------------------------------

' OWOut and OWIn commands are detailly explained in PBP official manual.

' OWOUT Pin,Mode,[Item...]:
' Optionally send a reset pulse to a one-wire device and then writes one or
' more bits or bytes of data to it, optionally ending with another reset pulse.
' Mode of %001 (decimal 1) means reset before data and byte-sized data.

' OWIN Pin,Mode,[Item...]:
' Optionally send a reset pulse to a one-wire device and then read one or
' more bits or bytes of data from it, optionally ending with another reset pulse.
' Mode of %000 (decimal 0) means no reset and byte-sized data, Mode of %100 (decimal 4)
' means no reset and bit-sized data. SKIP for skipping a number of input values.

HIGH PORTB.7
counter= 0
state=0
maxtemp=29
mintemp=17

mainloop:
OWOut DQ, 1, [$CC, $44]
waitloop:
OWIn DQ, 4, [count_remain]
IF count_remain = 0 THEN waitloop

OWOut DQ, 1, [$CC, $BE]
OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE, Skip 4, count_remain, count_per_c]
temperature = (((temperature >> 1) * 100) - 25) + (((count_per_c - count_remain) * 100) / count_per_c)
tempc = (temperature / 100)
LCDOut $fe, 1, "TEMP: ", SDEC (temperature / 100), ".", SDEC2 temperature, " C"

IF tempc < maxtemp THEN
LCDOut $fe, $c0, "STATUS OK"
ENDIF

' LCDOut $fe, $c0, temperature/100, "-", HEX (temperature / 100),"-", BIN (tempc)

GOTO automatic

'-----------------------------------------[Automatic and Manuel Control]----------------------------------------

' If temperature is equal or higher than 29 C then led status off and Buzzer generates sound also LCD monitors Alarm.
' Else led status is on, buzzer status off, LCD monitors status OK.

automatic:

IF PORTB.1 = 1 THEN ' Test button value. If button is pressed.
LOW PORTB.7 ' device status is off.
counter=0
SEROUT PORTC.6, T2400, ["disabled",10,13]
IF tempc >= maxtemp THEN ' Test temperature value.
SOUND PORTC.5,[80,10,60,10] ' If temperature higher than 25 C than buzzer generates sound that is
' between 80 & 60 frequency band about 120 ms seconds interval.
LCDOut $fe, $c0, "ALARM!!!" ' LCD monitors ALARM.
Pause 200
ENDIF
SEROUT PORTC.6, T2400, [#tempc,10]
GOTO mainloop ' Do it forever
ENDIF

IF state=1 OR state=2 THEN

IF tempc >= maxtemp THEN ' Test temperature value.
HIGH PORTB.5 ' LED status is on.
SOUND PORTC.5,[40,10,60,10] ' If temperature higher than 25 C than buzzer generates sound that is
' between 80 & 60 frequency band about 120 ms seconds interval.
LCDOut $fe, $c0, "ALARM!!!" ' LCD monitors ALARM.
ENDIF

IF tempc < maxtemp THEN ' Test temperature value.
LOW PORTB.5 ' LED status is off.
ENDIF
GOTO serial
ENDIF

IF tempc >= maxtemp THEN ' Test temperature value.
HIGH PORTB.5 ' LED status is on.
SOUND PORTC.5,[40,10,60,10] ' If temperature higher than 25 C than buzzer generates sound that is
' between 80 & 60 frequency band about 120 ms seconds interval.
LCDOut $fe, $c0, "ALARM!!!" ' LCD monitors ALARM.
counter = (counter + 1)
IF counter = 20 THEN
LOW PORTB.7
SEROUT PORTC.6, T2400, ["automatic", 10, 13]
ENDIF
GOTO serial ' Do it forever
ENDIF

IF tempc < maxtemp THEN ' Test temperature value.
LOW PORTB.5 ' LED status is off.
HIGH PORTB.7 ' Device on
counter=0
GOTO serial
ENDIF ' Do it forever


'------------------------------------------------[Serial Communication]-----------------------------------------

serial:

' ****** [Menu setup on PC screen] *************************
serout PORTC.6, T2400, [#tempc,10]

' ***** [Receive the menu selection from PC] ***************
serin PORTC.7, T2400,RX ' Receive menu number
RX = RX - $30


' Convert ASCII number to decimal (0 = $30, 1 = $31, etc).

SELECT CASE RX
CASE 0
goto zero
CASE 1
goto one
CASE 2
goto two
CASE 3
goto disconnect
CASE IS > 3
goto error
CASE IS < 0
goto error
CASE ELSE
goto mainloop
END SELECT

error:
goto mainloop

zero:
state=0
goto mainloop

one:
LOW PORTB.7 ' LED status is off.
state=1
GOTO mainloop

two:
HIGH PORTB.7 ' LED status is off.
state=2
GOTO mainloop

disconnect:
LCDOut $fe, $c0, "TURNED OFF " ' LCD monitors ALARM.
Pause 1000
Goto mainloop
'---------------------------------------------------------------------------------------------------------------

End ' End of program.