Hi all, need a little help with the following program. Trying to perform a BCD conversion on a word variable and display it on four 7 seg LED's. The word variable I am trying to decode is set to 5621. Only the first digit is calculated correctly. Can anyone offer some advice?
dim DispMessage byte
dim dissel byte
dim Message(10)
dim dig as byte
dim value as word
PORTA = 0
Main:
value = 5621
DisplayRPM(value)
goto Main
sub DisplayRPM(rpm as word)
dim temp as word
dim temp1 as word
temp = rpm
firstdig = rpm / 1000 [WORD]
seconddig = (rpm-(firstdig*1000))/100 [WORD]
thirddig = (rpm-((firstdig*1000)+(seconddig*100)))/10 [WORD]
forthdig = rpm-((firstdig*1000)+(seconddig*100)+(thirddig*10)) [WORD]
DisplayValue 1, firstdig
wait 25 ms
DisplayValue 2, seconddig
wait 25 ms
DisplayValue 3, thirddig
wait 25 ms
DisplayValue 4, forthdig
wait 25 ms
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
GCBASIC seems to be having trouble with the subtraction - it's treating the result of firstdig*1000 as a byte, even though it's performing the calculation as a word. I'll fix this bug ASAP.
In the meantime (and possible afterwards) I'd recommend that you alter the code that GCBASIC uses to display words on the LCD, and use that:
sub LCDWord(LCDValue as word) #NR
Dim SysCalcTempX as word
SET LCD_RS On
LCDValueTemp = 0
LCDShowChar = 0
IF LCDValue >= 10000 then
LCDValueTemp = LCDValue / 10000 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 1000 then
LCDValueTemp = LCDValue / 1000 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 100 then
LCDValueTemp = LCDValue / 100 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 10 then
LCDValueTemp = LCDValue / 10 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
end if
LCDWriteByte (LCDValue + 48)
end sub
Altering this to suit your program shouldn't be too hard, just replace this:
LCDWriteByte(LCDValueTemp + 48)
with the command to display LCDValueTemp on the appropriate display. You could also take out the first IF block (the one for 10000) to save some memory.
(SysCalcTempX stores the remainder after a division, and using it saves some calculations.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Lest there be some question on BCD for future viewers, not meaning to nitpick :-). For some RTC's (and who knows what else) that work in BCD out there, a byte could represent up to decimal 99, and a word up to 9999:
Sub BINtoBCD(Decimal)
Tens = 0
Ones = 0
DecimalTemp = 0
IF Decimal >= 10 then 'Decimal is between 10 and 99
DecimalTemp = Decimal / 10
Tens = DecimalTemp * 16 'Move to high nibble
Decimal = Decimal - DecimalTemp * 10
End if
If Decimal >= 0 Then 'Decimal is between 0 and 9
Ones = Decimal
End if
BCD = Tens + Ones
End sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've now dealt with the bug that was causing GCBASIC to confuse the variable types.
I recommend a slight change to your code: store the value of the multiplications in a temporary word variable each. Multiplication is pretty slow on the PIC, and it'll save time and memory if the value is only calculated once.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi all, need a little help with the following program. Trying to perform a BCD conversion on a word variable and display it on four 7 seg LED's. The word variable I am trying to decode is set to 5621. Only the first digit is calculated correctly. Can anyone offer some advice?
#chip 16F628A, 4
#config INTRC_OSC_NOCLKOUT, WDT_OFF, LVP_ON, MCLRE_OFF
dir PORTB out
dir PORTA out
dim DispMessage byte
dim dissel byte
dim Message(10)
dim dig as byte
dim value as word
PORTA = 0
Main:
value = 5621
DisplayRPM(value)
goto Main
sub DisplayRPM(rpm as word)
dim temp as word
dim temp1 as word
temp = rpm
firstdig = rpm / 1000 [WORD]
seconddig = (rpm-(firstdig*1000))/100 [WORD]
thirddig = (rpm-((firstdig*1000)+(seconddig*100)))/10 [WORD]
forthdig = rpm-((firstdig*1000)+(seconddig*100)+(thirddig*10)) [WORD]
DisplayValue 1, firstdig
wait 25 ms
DisplayValue 2, seconddig
wait 25 ms
DisplayValue 3, thirddig
wait 25 ms
DisplayValue 4, forthdig
wait 25 ms
end sub
GCBASIC seems to be having trouble with the subtraction - it's treating the result of firstdig*1000 as a byte, even though it's performing the calculation as a word. I'll fix this bug ASAP.
In the meantime (and possible afterwards) I'd recommend that you alter the code that GCBASIC uses to display words on the LCD, and use that:
sub LCDWord(LCDValue as word) #NR
Dim SysCalcTempX as word
SET LCD_RS On
LCDValueTemp = 0
LCDShowChar = 0
IF LCDValue >= 10000 then
LCDValueTemp = LCDValue / 10000 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 1000 then
LCDValueTemp = LCDValue / 1000 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 100 then
LCDValueTemp = LCDValue / 100 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
LCDShowChar = TRUE
end if
IF LCDShowChar > 0 or LCDValue >= 10 then
LCDValueTemp = LCDValue / 10 [word]
LCDValue = SysCalcTempX
LCDWriteByte(LCDValueTemp + 48)
end if
LCDWriteByte (LCDValue + 48)
end sub
Altering this to suit your program shouldn't be too hard, just replace this:
LCDWriteByte(LCDValueTemp + 48)
with the command to display LCDValueTemp on the appropriate display. You could also take out the first IF block (the one for 10000) to save some memory.
(SysCalcTempX stores the remainder after a division, and using it saves some calculations.)
Lest there be some question on BCD for future viewers, not meaning to nitpick :-). For some RTC's (and who knows what else) that work in BCD out there, a byte could represent up to decimal 99, and a word up to 9999:
Sub BINtoBCD(Decimal)
Tens = 0
Ones = 0
DecimalTemp = 0
IF Decimal >= 10 then 'Decimal is between 10 and 99
DecimalTemp = Decimal / 10
Tens = DecimalTemp * 16 'Move to high nibble
Decimal = Decimal - DecimalTemp * 10
End if
If Decimal >= 0 Then 'Decimal is between 0 and 9
Ones = Decimal
End if
BCD = Tens + Ones
End sub
I've now dealt with the bug that was causing GCBASIC to confuse the variable types.
I recommend a slight change to your code: store the value of the multiplications in a temporary word variable each. Multiplication is pretty slow on the PIC, and it'll save time and memory if the value is only calculated once.