Pins stay on in a simple ASM program

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please note: I am a beginner. I started to learn AVR ASM on my own about 1/2 a year ago, stopped due to working very late and now can pick it up again.  This is not for a job or for school... its just for my own desire to learn AVR ASM (yes, I am that loony).

 

I made a simple program to help me explore the op codes and learn. It runs on an Arduino Uno board  (ATMega328P-AU)  and is programmed from within the Arduino environment (You can do AVR ASM and C directly with in the Arduino IDE).

 

All the program does is read the pin values in PORTD and write those bits to an array of LEDs I have tied to each pin in PORTB.  So if PD3 has power, PB3 should light up.

 

All PORTD pins are set with no pull up or down resistors.

 

I only have trouble with the PB0 and PB1

 

It works as expected... EXCEPT.... the LEDs for PB0 and PB1 are always on.. and this seems to be driven from the bits in PORTD.  Thus giving power to PD0 or PD1 is irrelevant since the LEDs are always on.  I know PB0 and PB1 are for the UART... are they always held HIGH?  Is that what the issue is??

 

Can some one please tell me (please remember I am still very much a beginner!) why this is happening and how to correct it.  I figured out how to write a "0" to these two bits but then I can use the button for those two bits.

 

 

Thank you in advance.  I am learning alone out of a bunch-a books and stuff I find on the internet.

 



BlinkTest4:
   // Note: you can have 000000000000000000001101  and just the LSB will be looked at, and then MSB
   //SER            R16      //  sets all bits in R16 to "1"
   LDI          R16,       0
                //  if use LD instead of LDI, then the 0b111 would have been an address of the data
   OUT          DDRB,      R16

   SER          R16
   //LDI          R16,       255
   OUT          PORTB,     R16
   RJMP           INIT 


INIT:  
   //LDI            R16,       0
   CLR            R16
   OUT            PORTB  ,   R16
   OUT            DDRD,      R16
   RJMP           MAIN

   
MAIN:
   IN             R16,       PIND
   
   // This is necessary to turn the ever-on LEDs off... 
   // and I can't use the button on them as well!
   // otherwise  LEDs 0 and 1 on PORTB are always on!
   
   CBR            R16    ,   0
   CBR            R16    ,   1
   CBR            R16    ,   2
     
   
   
   OUT            PORTB,     R16
   RJMP           MAIN
   RET

 

I am a new AVR programmer. I am learning alone out of books, the Internet, etc. Please excuse me if I ask simple questions. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR_Beginner wrote:

   LDI          R16,       0
                //  if use LD instead of LDI, then the 0b111 would have been an address of the data
   OUT          DDRB,      R16

You just set Port B to input, not output

AVR_Beginner wrote:

   SER          R16
   //LDI          R16,       255
   OUT          PORTB,     R16

You just turned on the pullup resistors on Port B

 

Edit: typo

David (aka frog_jr)

Last Edited: Thu. Nov 16, 2017 - 11:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

frog: 

 

changed but still happens :-(

I am a new AVR programmer. I am learning alone out of books, the Internet, etc. Please excuse me if I ask simple questions. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First test the hardware. Use the standard Arduino IDE C++ and the pinMode(nn, OUT);  and digitalWrite (nn, LED_ON) {either high or low depending on the LED configuration}.  Turn each LED on individually for about a half of a second, then the next one.  This will verify that the LEDs are actually working and configured correctly (anode going to positive and cathode going to negative).  Each LED should have a current-limiting resistor that prevents it from burning out.  100 to 500 ohms is fine.  When you can be assured that the hardware works reliably then start on the firmware.

 

You can use CBI and SBI instructions to directly clear and set the individual bits in the hardware output ports.   Check the PDF file of the AVR instruction set for unusual non-othorginal assembler instruction applications.  Due to its internal design, the AVR has some instructions that only work with the 16 high numbered registers.  Check if the CBR instruction uses 0-255 or 0-7 as parameter range.  The CBR and CBI instructions may use different parameter ranges.  An instruction that uses 0-255 will set/clear multiple bits with one instruction, while one that uses 0-7 will only set/clear one bit at a time.

 

An instruction that takes 0-255 as its range will not light the LED on bit 2 with the parameter value of 0x02: it will light the LED on output port bit 1 {assuming that logic high causes the LED to light} because the target register is receiving B00000010 instead of B00000100.

 

And, finally, welcome to assembler.  Working in assembler is like building a very exacting, very precise, and very fast machine.  The CPU will do exactly what you tell it to do.  You don't have to spend 10 hours trying to figure out that some idiot -O optimizer setting is wiping out your precision delay routine and giving you no clue or indication that the compiler just decided to do this on its own.  Yes, I do know that is not exactly true, but compilers can make you feel that they have a mind of their own when you haven't spent 10,000 hours mastering every stupid little detail of their operation.  Don't get discouraged.  You can transfer your assembler skills to 25 cent microprocessors in ways that you can't with complex high-level language compilers.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note that PD0/PD1 on an Arduino are connected to the USB/Serial converter.   That'll mean that PD0 essentially has a 1k pullup attached that you can't get rid of.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   //SER            R16      //  sets all bits in R16 to "1"
   LDI          R16,       0

As already pointed out, writing 0 to DDRB sets all inputs but I'm intrigued by the code here. The commented line would have set R16 to 0xFF which would have been the right value to make all those pins output so what made you change SER to LDI. (BTW the "opposite" of SER is actually CLR, true it is just a synonym for LDI Rn, 0 anyway but "CLR R16" possibly emphasises the intent more than just LDI R16, 0)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you everyone!

 

 

Simonetta:  Thank you for the advice.  I checked the board with a small arduino program to confirm all is well before I wrote the ASM.

 

westfa:  Your explanation sounds logical. It might also explain why then i have a sleeping 328P that is attached to a non-sleeping one via Tx/Rx (USART) the sleeping one can rob power no matter what i do (setting pins LOW, etc does not see to work).

 

clawson wrote:
so what made you change SER to LDI.
   Just experimentation. Learning. Trying different ways of doing the same task.

 

Thank you everyone again!

 

My take away is the PD0 and PD1 are working as designed and this is not a flaw in my code. This is the way PORTD behaves and is normal. 

I am a new AVR programmer. I am learning alone out of books, the Internet, etc. Please excuse me if I ask simple questions. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
And, finally, welcome to assembler.  Working in assembler is like building a very exacting, very precise, and very fast machine.  The CPU will do exactly what you tell it to do.  You don't have to spend 10 hours trying to figure out that some idiot -O optimizer setting is wiping out your precision delay routine and giving you no clue or indication that the compiler just decided to do this on its own.

 

 

Simonetta:

The "purity" (for lack of a better term) of it is what i find attractive. No layers of abstraction to try to figure out, no one else's head to try to understand.  Its what appeals to me and although i am still just starting out, I am enjoying my incremental victories (with help from people like you of course!).

I am a new AVR programmer. I am learning alone out of books, the Internet, etc. Please excuse me if I ask simple questions. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

is actually CLR, true it is just a synonym for LDI Rn, 0

Actually, it's a synonym for EOR Rn, Rn.

 

However, SER >>is<< a synonym for LDI Rn, 0xFF

 

The former can be used with any register, while the latter is restricted to r16 or above.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]