Hello there,
I wrote a nice program that works in the IDE. but it would not work correctly on the AVR. I've traced the problem down to the outputs.
So I made a very basic program to test four outputs on the avr. This works in the debugger, I set all the bits in the watch window, set break points on all the outputs (so I could step through them) and then ran it. Now If I change PIND.B2 from 0 to 1 and back to zero again, all the outputs change their states as they should, no problem at all.
I then load the program into the AVR, this is where the trouble starts. If I press the button that controls PIND.B2 I can see the outputs trying to change states. They go from zero to about 3.47 vdc. 3.47 vdc? how is that? So I put my scope on one of the output pins, and sure enough it's being driven high then low again. Just like it was being pulse width modulated.
I checked PIND.B2 with the scope and it's nice and smooth from 0 to 4.96 Vdc on the input.
Why will the output not turn fully on? And why are the output pins being Pulse width modulated?
I certainly can not use this IDE if it can't hold an output pin in the correct state.
Below is the test program that I'm using to test the four output pins with. This is set to use the ATMega88PA AVR. with the internal oscillator at 8 MHZ and no CKDIV8 fuse.
program MyProject
' Declarations section
main:
DDRD = 0xF8 '- Set Port D0-D2 to be inputs, D3-D7 are outputs.
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2.
PortD = 0x00 '- Set Port D to all off.
while TRUE
if PIND.B2 = 1 then ' If PORTD.2 is High
PIND.B6 = 0 '- LED three off
PIND.B5 = 0 '- LED two off
PIND.B3 = 0 '- LED one off
PIND.B7 = 0 '- LED four off
else ' If PORTD.2 is Low
PIND.B6 = 1 '- LED three on
PIND.B5 = 1 '- LED two on
PIND.B3 = 1 '- LED one on
PIND.B7 = 1 '- LED four on
end if
wend ' endless loop
end.
I also tried setting the output states to one and then tried just zero, same results. the output never turns fully on.
I then wrote the same program in assembly language, in avr studio. it works fine then. Only when I put the mikroBasic program on the avr does it have this behavior.
So what gives here? why do the output pins have this behavior in Mikro basic?
Robert
Problem with holding an output state
-
- Posts: 145
- Joined: 14 Nov 2012 00:30
- Location: China
- Contact:
- dejan.odabasic
- mikroElektronika team
- Posts: 2649
- Joined: 30 Apr 2012 14:20
Re: Problem with holding an output state
Hello,
You need to use appropriate PORT output register.
PIND - input register of PORTD
PORTB - output register of PORTB
try changing the code:
Also please check the pullup setup:
Best regards.
You need to use appropriate PORT output register.
PIND - input register of PORTD
PORTB - output register of PORTB
try changing the code:
Code: Select all
if PIND.B2 = 1 then ' If PORTD.2 is High
PORTD.B6 = 0 '- LED three off
PORTD.B5 = 0 '- LED two off
PORTD.B3 = 0 '- LED one off
PORTD.B7 = 0 '- LED four off
else ' If PORTD.2 is Low
PORTD.B6 = 1 '- LED three on
PORTD.B5 = 1 '- LED two on
PORTD.B3 = 1 '- LED one on
PORTD.B7 = 1 '- LED four on
end if
Code: Select all
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2.
PortD = 0x00 '- Set Port D to all off.
-
- Posts: 145
- Joined: 14 Nov 2012 00:30
- Location: China
- Contact:
Re: Problem with holding an output state
Thank you for the timely response,
I did in fact try that before, and the outputs would not change states in the IDE.
I also tried using it without the internal pullups enabled. It still had the same affect.
Alas, I did check my code from the other attempts. it was more along the lines of:
if PIND.B2 = 1 then ' If PORTD.2 is High
PORTD.6 = 0 '- LED three off
end if.
I'm guessing this it what happens when you write code with no sleep. (over 32 hours)
I did make a couple of post on here with "PINA.B0 = 0 ' Turn off PortA bit zero"
I will have to go back and correct that mistake.
Yes, even in assembly language PORTB = 0xFF is an output for the entire register.
And the setting of the bits:
Pause:
sbic PIND,PD2 ; PD2 Switch 2 pressed ?
ret ; if Not, Return
rjmp WPause ; If pressed, jump to WPause to check for release
WPause:
sbis PIND,PD1 ; Wait for switch to be released
rjmp WPause ; if Not, released loop until it is
rjmp LEDS_ON ; Pause button released, Jump to LEDS_ON
LEDS_ON:
sbi PORTD, PD3 ; Mode 1 LED on
sbi PORTD, PD5 ; Mode 2 LED on
sbi PORTD, PD6 ; Mode 3 LED on
sbi PORTD, PD7 ; Mode 4 LED on
ret
But in assembly language language, to enable the pullup resistors, it's done right after setting the PORT direction. IE:
ldi Wreg, 0b11111000 ; set Port D0-D2 to be inputs, D3-D7 are outputs.
out DDRD, Wreg ; Data Direction register.
ldi Wreg, 0b00000111 ; Enable internal pullup resistors on PORTD D0-D2.
out PORTD, Wreg ; Write it to the port.
ldi Wreg, 0b00000111 ; set Port D to all off.
out PORTD, Wreg ; Write it to the port.
I will try again with:
if PIND.B2 = 1 then ' If PORTD.2 is High
PORTD.B6 = 0 '- LED three off
PORTD.B5 = 0 '- LED two off
PORTD.B3 = 0 '- LED one off
PORTD.B7 = 0 '- LED four off
else ' If PORTD.2 is Low
PORTD.B6 = 1 '- LED three on
PORTD.B5 = 1 '- LED two on
PORTD.B3 = 1 '- LED one on
PORTD.B7 = 1 '- LED four on
end if
and play with the internal pull up
I'm sure it will work fine, Thank you for pointing that out.
regards,
Robert
I did in fact try that before, and the outputs would not change states in the IDE.
I also tried using it without the internal pullups enabled. It still had the same affect.
Alas, I did check my code from the other attempts. it was more along the lines of:
if PIND.B2 = 1 then ' If PORTD.2 is High
PORTD.6 = 0 '- LED three off
end if.
I'm guessing this it what happens when you write code with no sleep. (over 32 hours)
I did make a couple of post on here with "PINA.B0 = 0 ' Turn off PortA bit zero"
I will have to go back and correct that mistake.
Yes, even in assembly language PORTB = 0xFF is an output for the entire register.
And the setting of the bits:
Pause:
sbic PIND,PD2 ; PD2 Switch 2 pressed ?
ret ; if Not, Return
rjmp WPause ; If pressed, jump to WPause to check for release
WPause:
sbis PIND,PD1 ; Wait for switch to be released
rjmp WPause ; if Not, released loop until it is
rjmp LEDS_ON ; Pause button released, Jump to LEDS_ON
LEDS_ON:
sbi PORTD, PD3 ; Mode 1 LED on
sbi PORTD, PD5 ; Mode 2 LED on
sbi PORTD, PD6 ; Mode 3 LED on
sbi PORTD, PD7 ; Mode 4 LED on
ret
But in assembly language language, to enable the pullup resistors, it's done right after setting the PORT direction. IE:
ldi Wreg, 0b11111000 ; set Port D0-D2 to be inputs, D3-D7 are outputs.
out DDRD, Wreg ; Data Direction register.
ldi Wreg, 0b00000111 ; Enable internal pullup resistors on PORTD D0-D2.
out PORTD, Wreg ; Write it to the port.
ldi Wreg, 0b00000111 ; set Port D to all off.
out PORTD, Wreg ; Write it to the port.
I will try again with:
if PIND.B2 = 1 then ' If PORTD.2 is High
PORTD.B6 = 0 '- LED three off
PORTD.B5 = 0 '- LED two off
PORTD.B3 = 0 '- LED one off
PORTD.B7 = 0 '- LED four off
else ' If PORTD.2 is Low
PORTD.B6 = 1 '- LED three on
PORTD.B5 = 1 '- LED two on
PORTD.B3 = 1 '- LED one on
PORTD.B7 = 1 '- LED four on
end if
and play with the internal pull up
I'm sure it will work fine, Thank you for pointing that out.
regards,
Robert
Last edited by robert_d1968 on 29 Nov 2012 21:09, edited 1 time in total.
-
- Posts: 145
- Joined: 14 Nov 2012 00:30
- Location: China
- Contact:
Re: Problem with holding an output state
OK,
I tried it again using the correct output statement of PORTD.B3, this works very well.
Also great catch on the pullup resistors setup.
DDRD = 0xF8 '- Set Port D0-D2 to be inputs, D3-D7 are outputs.
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2.
PortD = 0x00 '- Set Port D to all off. <------------------------ "ERROR"
Should in fact be:
DDRD = 0xF8 '- Set Port D0-D2 to be inputs, D3-D7 are outputs.
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2
PortD = 0x07 '- Set Port D to all off. <------------------------ "Now it's happy"
Thanks,
Robert
I tried it again using the correct output statement of PORTD.B3, this works very well.
Also great catch on the pullup resistors setup.
DDRD = 0xF8 '- Set Port D0-D2 to be inputs, D3-D7 are outputs.
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2.
PortD = 0x00 '- Set Port D to all off. <------------------------ "ERROR"
Should in fact be:
DDRD = 0xF8 '- Set Port D0-D2 to be inputs, D3-D7 are outputs.
PortD = 0x07 '- Enable internal pullup resistors on PORTD D0-D2
PortD = 0x07 '- Set Port D to all off. <------------------------ "Now it's happy"
Thanks,
Robert