View previous topic :: View next topic |
Author |
Message |
unzeitig
Joined: 31 Jan 2008 Posts: 25
|
Posted: Mon Feb 22, 2016 4:40 pm Post subject: Port reading problem MEGA162 |
|
|
Hello,
can anybody explain me why simple code:
Dim Inputs as Byte
Config Porta=Input
Porta = 255
Inputs = Pina
doesn't work properly when:
Config Porta=Input
Porta = 255
For X = 0 To 7
Inputs.x = Pina.x
Next
works without any problem?
I do not understand it.
[b][color=red](BASCOM-AVR version : 2.0.7.9 , Latest : 2.0.7.8 )[/b][/color] |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Mon Feb 22, 2016 4:49 pm Post subject: |
|
|
better show the rest of the code since indeed that does not make any sense. _________________ Mark |
|
Back to top |
|
|
unzeitig
Joined: 31 Jan 2008 Posts: 25
|
Posted: Mon Feb 22, 2016 5:52 pm Post subject: |
|
|
I have prepared very simple not working code. You can try it.
There are 4 7-segment units on my board - they are parts of my final project, Halve of PortB is connected to PNP transistors for common anodes of segments, cathodes of segments are connected to PortA.
I can see result immediatelly. After reading of PortA I send result to PortA and it is displayed.
$regfile = "M162DEF.DAT"
$hwstack = 64
$swstack = 64
$framesize = 64
$lib "adr2.lib"
Const Crystalfrekq = 8000000
$crystal = Crystalfrekq
Dim Inputs as Byte
Dim X As Byte
Config Portb = Output
Do
Config Porta = Input
Porta = 255
' For X = 0 To 7
' Inputs.x = Pina.x
' Next
Inputs = Pina
Config Porta = Output
Porta = Inputs
Portb = 0
Waitms 500
Portb = 255
Loop |
|
Back to top |
|
|
albertsm
Joined: 09 Apr 2004 Posts: 5913 Location: Holland
|
Posted: Mon Feb 22, 2016 9:05 pm Post subject: |
|
|
well it works ok. i think you need to include some delay between switching from input to output.
in any case, reading the PINA port does what it suppose to do. And the other port manipulating commands also do what they should do : read/write from the proper register. _________________ Mark |
|
Back to top |
|
|
unzeitig
Joined: 31 Jan 2008 Posts: 25
|
Posted: Mon Feb 22, 2016 9:29 pm Post subject: |
|
|
Hello Mark,
I supposed PortA will be switched "immediatelly" so I do not need to wait. Now it really works after additional delay a few usec was included.
Example with for-next cykle automatically added delay so it worked - it is explanation now.
Thank you very much for your help. |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Mon Feb 22, 2016 11:25 pm Post subject: |
|
|
AFAIK one nop is usually enough delay:
Code: |
Porta = 255
!nop
Inputs = Pina
|
The Atmel manual states that there is a latch on the port pin to keep the value read in sync with the system clock. So you need one more clock cycle to ensure the pin value is latched after changing it before reading it.
As well as the above, the pullups on the pins enabled by setting the port high are fairly weak, and can take a bit of time to pull the line up, particularly if the pin is loaded with some capacitance. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
unzeitig
Joined: 31 Jan 2008 Posts: 25
|
Posted: Tue Feb 23, 2016 1:54 pm Post subject: |
|
|
I have tried it in my HW - I need more then 10x !NOPs to obtain stabile results.
In my project I solve fast multiplexer with many additional interrupts, so I can not waste time by waiting (but probably I will have to).
Normally, it is basic thing to read port, but do anybody know exact rule or reccomendation, how to solve as fast as possible reading - not Waitus 2? |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Feb 23, 2016 7:55 pm Post subject: |
|
|
unzeitig wrote: | There are 4 7-segment units on my board - they are parts of my final project, Halve of PortB is connected to PNP transistors for common anodes of segments, cathodes of segments are connected to PortA. |
You did not manage to explain, why you actually want to switch the segment drivers to input. It's not the duty of the users to guess your intentions.
The working solution may not be the way you think it to be, however a detailed explanation what you actually want to achieve may lead to said solution. |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Tue Feb 23, 2016 9:28 pm Post subject: |
|
|
This is propably design like this (see partial schematic)
I programm this with interrupts from all Timers without a problem
Timer0 every 2ms... but also Timer2 for Servo and even interrupt every time when PWM cut off current for motor and then I read BEMF.
Buttons can recognize short and long push (auto increment/decrement for settings)
For interrupts I use Nosave option.
You must know that Wait, Witms and Waitus can be interrupted so it is safe to use Waitus 1 and when Interrupt is comming then simply everything will be done.
I also use NOP`s at the begining but finally I have Waitus 1.
Last edited by EDC on Tue Feb 23, 2016 11:26 pm; edited 1 time in total |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Tue Feb 23, 2016 10:57 pm Post subject: |
|
|
From what I can see, you use the internal pullups of the port to hold the switch lines high. But with all the extra circuitry connected to those lines, there is probably significant capacitance ( think about the bases of those digit driver transistors ) to charge up before the lines actually go high. While the AVR manual specifies exactly what wait state is needed for the internals to work, it cannot take into account external circuitry and its effects.
The AVR internal pullups are not tightly specified, and may be as much as 50 Kohm. To get a reasonably short ( and well defined ) pullup time, I would add say 4.7 Kohm external pullups. Poking around with an oscilloscope would also be useful to measure the pullup time.
If you use a timer IRQ to scan the display drives, you could also consider reading the switch states during the IRQ, since somewhere in there you must already turn off the drive, and wait a bit before driving the next digit, to prevent 'ghosting' on the display.
You could also consider putting the switches on the segment drive lines, rather than the digit drive lines. Its usually a better place. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Tue Feb 23, 2016 11:16 pm Post subject: |
|
|
You dont get transistor bases because LED in segments lead only one direction.
But case is more complicated. You dont want to light any segment when button is pushed and hold So 4k7 resistor is used in circuit.
If you pull up inputs with 4k7 to 5V then if switch is pressed you get 2,5V on input
This combination give you keyboard and displays on one port to spare pins but everything must be balanced |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Tue Feb 23, 2016 11:25 pm Post subject: |
|
|
If you do the pullups directly on the switches, you can get full rail swings on the port lines. But yes, putting both switches and LEDs on the same port is a balancing act _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Feb 24, 2016 12:02 pm Post subject: |
|
|
AdrianJ wrote: | If you do the pullups directly on the switches, you can get full rail swings on the port lines. |
Not sure how you want to improve anything this way, do you want to explain?
The problem results imho out of a certain capacitance of the pcb traces and segment leds, together with the resistors several R/C circuits are created.
Additionally the internal pullup, led current limiting resistors and resistors in series with the switches creates a voltage divider.
And so it simply needs some time to change charge.
This may help:
1) before switching to input and all segment lines high, set these lines high in output mode.
The output drivers are much stronger for changing charge to the desired high-level, which otherwise the weaker pullups have to.
2) decrease the switches series resistor value
3) use the multiplex-ISR itself for the delay. Even in an short ISR the contained operations provide enough delay.
In case standard saving and restoring registers is used (no NOSAVE), saving the registers can be used to provide more than enough delay:
Code: | On Int0 MPX_ISR NOSAVE
' ...
MPX_ISR:
!PUSH R16
!LDI R16, &hFF
!OUT PORTA, R16 ' all pins high
!LDI R16, &h00
!OUT DDRA, R16 ' all pins input
!POP R16
PUSHALL
'
' your code here
POPALL
Return |
|
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Wed Feb 24, 2016 11:23 pm Post subject: |
|
|
I mean like in the attached.
The trick of doing the wait by using the 'spare' time in the IRQ before the pushall is neat ! _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Thu Feb 25, 2016 10:51 am Post subject: |
|
|
AdrianJ wrote: | I mean like in the attached. |
The benefit would be a stronger defined high and this would help to change charge of the segment-lines.
However I suspect, that alone actively driving the segment pins high for a few cycles, before switching to input would solve this issue. As already suggested.
It won't require change of hardware, so it would be easiest.
Feedback of the TO is desirable, which surly would help the TO in return to get feedback next time he needs help.
Quote: | The trick of doing the wait by using the 'spare' time in the IRQ before the pushall is neat ! |
Thanks. Btw., as no one of these asm commands changes SREG, it does not need to be saved, uses up less cycles. |
|
Back to top |
|
|
|