Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to speed up my Pic16f877A

Status
Not open for further replies.

IGIF16

Junior Member level 2
Joined
Dec 19, 2010
Messages
22
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Frince
Activity points
1,442
hi
i wrote this code every thing is good but my problem is the Pic16877A take along time to response, like when this get true
"if out_light > 1 then
portc.2 = 0
else portc.2 = 1
end if"

the portc.2 take at lest 2 second to be 0 :shock:
but i need it simultaneously
i don't have any problem with the other output delay but this portc.2 i need it simultaneously :twisted:

Code:
dim rs_temp as integer
dim st_temp as integer
dim out_light as integer
dim x as integer
dim y as integer
dim digit_1 as byte
dim digit_10 as byte
dim Rh as integer
dim q as integer
dim tt as integer
dim i as byte
dim in as short
dim out as short
dim c4_perv as byte
dim c5_perv as byte

sub function mask(dim num as byte) as byte
select case num
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select
end sub

main:
trisa = $FF
trisb = $0F
trisd = $00
trisc = $30
trise = $00
porte = 0
portd = 0
Adcon1 = %10000010
igi:
rs_temp = ADC_Read(1)
rs_temp = (rs_temp - 546)/2
st_temp = ADC_Read(2)
st_temp = ((st_temp/50) + 14)
Rh = ADC_Read(4)
Rh = (Rh - 4)*7
for i =1 to 40                    "for multiplexing 4-digit 7segement to
x = rs_temp mod 10           "display the temperature 
tt = mask (x)
portd = tt xor $FF
porte.1 = 1
delay_ms (5)
porte.1 = 0
x = (rs_temp /10) mod 10
tt = mask (x)
portd = tt xor $FF
porte.0 = 1
delay_ms (5)
porte.0 = 0
x = 0
tt = mask (x)
portd = tt xor $FF
porte.2 = 1
delay_ms (5)
porte.2 = 0
portd = $46
portc.3 = 1
delay_ms (5)
portc.3 = 0
next i
delay_ms (2500)
for i = 1 to 40                 "for multiplexing 4-digit 7segement to
y = Rh mod 10                 "display the humidity  
q = mask (y)
portd = q xor $FF
porte.1 = 1
delay_ms (5)
porte.1 = 0
y = (Rh /10) mod 10
q = mask (y)
portd = q xor $FF
porte.0 = 1
delay_ms (5)
porte.0 = 0
y = (Rh /100) mod 10
q = mask (y)
portd = q xor $FF
porte.2 = 1
delay_ms (5)
porte.2 = 0
portd = $09
portc.3 = 1
delay_ms (5)
portc.3 = 0
next i
delay_ms (2500)
if rs_temp > st_temp  then
portc.0 = 1
else portc.0 = 0
end if
if rs_temp < st_temp then
portc.1 = 1
else portc.1 = 0
end if
out_light = ADC_Read(3)             "for outer lighting 
out_light = (out_light)                 " from LDR
if out_light > 1 then
portc.2 = 0
else portc.2 = 1
end if
goto igi
end.
 

use higher value oscillator
 

you mean i have to use 20MHz XT
ok but the delay between the two displays it should be at least 2 second
 

should be a bit faster. Let me know the result :)
 

One thing you could do for sure is optimize the code.
For example, the 'mask' function has a variable execution time and uses a lot of instructions to return a value.

In order to test if num is 9, it needs to go trough the whole process of checking whether it's 0, 1, 2, 3,....8 and then finally 9. Since it takes 3-4 instructions to test a number (load literal, subtract literal from number, check if zero flag is set), it means that the routine will take some anywhere between 5 and 40 instructions to return a mask value. In terms of microcontrollers, this is incredibly slow

There's a better way to do the same thing.
For example, let's assume that general purpose registers from 0x30 to 0x39 are free (you choose a range that is unused by your code) and fill it with the mask values corresponding to "num" values 0 - 9 upon startup (one time)

Then use the indirect addressing function of a PIC microcontroller (address in FSR lets you read contents of the addressed register from INDF) and do the following:
1) Add 0x30 to the 'num' value to get the address of the appropriate mask register
2) Put the address in the FSR register
3) Read the mask value from INDF register
4) Return from subroutine.

This will do the exact same thing as your switch routine, but will ALWAYS take only 3 instructions (not counting the call and return instructions) regardless of whether 'num' is 1 or 9. This pretty simple change in code reduced your execution time five times.


EDIT: If you're low on available general purpose registers, you could use EEPROM memory to permanently store the mask values and read them from there. Reading from EEPROM is just as fast as from a GPR, only writing takes a long time.
 

hi jumper2high i understand the concept but i can't edit my code because it will take from me time to understand how to read and write on EEPROM or the concept of the general purpose registers.
Then if you can help me with the code i ll be very thankful for you
and i ll change my XT from 4MHz to 20MHz tomorrow
 

Hey, if you need to figure out how to write data to a register, you seriously should consider a different profession/hobby such as gardening or something :D

Every variable (Dim xxxx as Byte) is stored in one or more general purpose registers.
 

hi
jumper2high i do it with EEPROM but the same delay nothing change this is the new code

dim rs_temp as integer
dim st_temp as integer
dim out_light as integer
dim x as integer
dim y as integer
dim digit_1 as byte
dim digit_10 as byte
dim Rh as integer
dim i as byte
dim in as short
dim out as short
dim c4_perv as byte
dim c5_perv as byte

sub procedure interrupt
portb.5 = 1
delay_ms (200)
portb.5 = 0
delay_ms (200)
TMr0 = 0
intcon = $20
end sub

main:
OPTION_REG = $80
trisa = $FF
trisb = $0F
trisd = $00
trisc = $30
trise = $00
porte = 0
portd = 0
portc.6 = 1
portc.7 = 1
in = 0
out = 0
Adcon1 = %10000010
igi:
rs_temp = ADC_Read(1)
rs_temp = (rs_temp - 546)/2
st_temp = ADC_Read(2)
st_temp = ((st_temp/50) + 14)
Rh = ADC_Read(4)
Rh = (Rh - 4)*7
if portc.4 = 1 then
if c4_perv = 0 then
in = in + 1
out = out - 1
portc.6 = 0
end if
else portc.6 = 1
end if
c4_perv = portc.4
if out < 0 then
out = 0
end if
if portc.5 = 1 then
if c5_perv = 0 then
out = out + 1
in = in - 1
portc.7 = 0
end if
else portc.7 = 1
end if
c5_perv = portc.5
if in < 0 then
in = 0
end if
if in > 0 then
portb.6 = 1
else
portb.6 = 0
end if
if out > 0 then
portb.7 = 1
else
portb.7 = 0
end if
for i =1 to 40
x = rs_temp mod 10
portd = EEPROM_Read(x + 0x00) xor $FF
porte.1 = 1
delay_ms (5)
porte.1 = 0
x = (rs_temp /10) mod 10
portd = EEPROM_Read(x + 0x00) xor $FF
porte.0 = 1
delay_ms (5)
porte.0 = 0
x = 0
portd = EEPROM_Read(x + 0x00) xor $FF
porte.2 = 1
delay_ms (5)
porte.2 = 0
portd = $46
portc.3 = 1
delay_ms (5)
portc.3 = 0
next i
delay_ms (2500)
for i = 1 to 40
y = Rh mod 10
portd = EEPROM_Read(y + 0x00) xor $FF
porte.1 = 1
delay_ms (5)
porte.1 = 0
y = (Rh /10) mod 10
portd = EEPROM_Read(y + 0x00) xor $FF
porte.0 = 1
delay_ms (5)
porte.0 = 0
y = (Rh /100) mod 10
portd = EEPROM_Read(y + 0x00) xor $FF
porte.2 = 1
delay_ms (5)
porte.2 = 0
portd = $09
portc.3 = 1
delay_ms (5)
portc.3 = 0
next i
delay_ms (2500)
if rs_temp > st_temp then
portc.0 = 1
else portc.0 = 0
end if
if rs_temp < st_temp then
portc.1 = 1
else portc.1 = 0
end if
out_light = ADC_Read(3)
out_light = (out_light)
if out_light > 1 then
portc.2 = 0
else portc.2 = 1
end if
goto igi
end.
 

hi
Mr. john blue
i changed my code as Mr. jumper2high told to me "use EEPROM" and i change my OSC to 20Mhz the system was faster but the 4-digit 7 segment was faster to
 

It is good but now we have a new problem with the blank of the 4-digit 7 segment

---------- Post added at 13:45 ---------- Previous post was at 13:45 ----------

it is too fast
 

Yup. Need to change to proper delay for the 7 segmnet :)
 

Hi
john blue when i changed to proper delay for 7 segment, i return to the zero point, i mean i get the same problem
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top