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.

Atmega328 Assembly-Send 16 bits serially!

Status
Not open for further replies.

kgavionics

Full Member level 3
Joined
Jun 12, 2012
Messages
167
Helped
7
Reputation
14
Reaction score
11
Trophy points
1,298
Location
Alberta.Canada
Activity points
2,479
Hello guys
I'm learning AVR assembly, and I'm having trouble sending 16bits data to a 74595(shift register). I have successfully written a code that works to send 8 bits data, but somehow it doesn't work (with a little modification of course) for 16 bits data.


Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
.device ATmega328P
.org 0
    ldi r16,low(ramend)
    out sph,r16
    ldi r16,high(ramend)   
    out sph,r16
 
    sbi ddrb,0 ; arduino pin 8 (serial in)
    sbi ddrd,7 ;arduino pin7 (clock)
    sbi ddrd,4 ;arduino pin 4 (latch)
start:    ldi r17,$0f
    call send
    call latch
here:   rjmp here
    .org $100
clock:  sbi portd,7
    call delay
    cbi portd,7
    call delay
    ret
 
.org $120
latch:  sbi portd,4
    call delay
        cbi portd,4
    ret
.org $140
delay:
   
    ldi r19,$0f
loop2:    ldi r20,$ff
loop1:    nop
    dec r20
    brne loop1
    dec r19
    brne loop2
    ret
 
.org $160
send:  ldi r16,$09 ; number of bits to be sent (for some unknown reason 08 sends only 7 bits, so I had to use 9 to send 8 bits
    clc
 
loop:    lsr  r17
    call clock
    brcs one
    cbi portb,0
    call delay
    rjmp go
one:    sbi portb,0
go:    dec r16
    brne loop
        ret




to send 16 bits I modified the following code, but the output is always wrong!


Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
.device ATmega328P
.org 0
    ldi r16,low(ramend)
    out sph,r16
    ldi r16,high(ramend)   
    out sph,r16
 
   
    sbi ddrb,0 ; arduino pin 8 (serial in)
    sbi ddrd,7 ;arduino pin7 (clock)
    sbi ddrd,4 ;arduino pin 4 (latch)
    ldi r17,$0f  ; low byte to be sent
    call send
    ldi r17,$f0 ; high byte to be sent
    call send
    call latch
here:   rjmp here
    .org $100
clock:  sbi portd,7
    call delay
    cbi portd,7
    call delay
    ret
 
.org $120
latch:  sbi portd,4
    call delay
        cbi portd,4
    ret
.org $140
delay:
   
    ldi r19,$0f
loop2:    ldi r20,$ff
loop1:    nop
    dec r20
    brne loop1
    dec r19
    brne loop2
    ret
 
.org $160
send:  ldi r16,$09 ; number of bits to be sent (for some unknown reason 08 sends only 7 bits, so I had to use 9 to send 8 bits
    clc
 
loop:    lsr  r17
    call clock
    brcs one
    cbi portb,0
    call delay
    rjmp go
one:    sbi portb,0
go:    dec r16
    brne loop
        ret



Does someone have an idea how to fix this?
Thanks in advance!
 
Last edited:

for some unknown reason 08 sends only 7 bits, so I had to use 9 to send 8 bits
The reason is simple, you are sending the clock before the data, thus the last bit isn't clocked anymore to the SR. The same issue is also affecting the intended 16 bit output code

Sketch a timing diagram, write and verify the code referring to the diagram. Use a simulator to check code operation line by line.
 
Hello and thank you FVM for your reply
I fixed the 8 bit code (see code below), but 16 bits is still outputting wrong numbers!

Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.org $160
send:  ldi r16,$08
    clc
 
    
loop:    lsr  r17
    call clock
    brcs one 
    cbi portb,0
    call delay
    rjmp go
one:    sbi portb,0
go:    dec r16
    brne loop
    sbi portd,7; this instruction fixed the 8 bit code
        ret

 

I just found the culprit! It was just a matter of clearing the carry flag in the beginning of the program

Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
.device ATmega328P
.org 0
    ldi r16,low(ramend)
    out sph,r16
    ldi r16,high(ramend)    
    out sph,r16
 
    sbi ddrb,0
    sbi ddrd,7
    sbi ddrd,4
    clc ; This instruction was missig before!! Now the code is working!
start:    ldi r17,$00    
    call send
    ldi r17,$00        
    call send
    call latch
here:   rjmp here
 
    .org $100
clock:  sbi portd,7
    call delay
    cbi portd,7
    call delay
    ret
 
.org $120
latch:  sbi portd,4
    call delay
        cbi portd,4
    ret
.org $140
delay:
    
    ldi r19,$0f
loop2:    ldi r20,$ff
loop1:    nop
    dec r20
    brne loop1
    dec r19
    brne loop2
    ret
 
.org $160
send:  ldi r16,$08    
    
 
    
loop:    lsr  r17
    call clock
    brcs one 
    cbi portb,0
    call delay
    rjmp go
one:    sbi portb,0
go:    dec r16
    brne loop
    sbi portd,7
        ret

 

Hi,

You say "it doesn't work" and "outputting wrong numbers"

A informative error description tells
* test conditions ( schematic, code, timing...)
* what you expect
* and what (results) you see instead

Then you get faster and better forum results.

Klaus
 
Everything is working as expected now! As I said it was just a misplaced carry instruction!
Thank you for all your inputs!
 

I have never coded for AVR in my life so excuse a guess:
'send' seems to loop to send out 8 bits, 'r17' seems to hold the data to be sent.
Code:
ldi r17,$0f  ; low byte to be sent
call send
ldi r17,$f0 ; high byte to be sent
call send
seems to send the four low bits followed by the four high bits, but both as 8 bit transfers.
The size and bit positions of the data don't seem to match the bit placements in the serial output. As the data in the final code only sends zeros it would appear to be correct.

Brian.
 

I have never coded for AVR in my life so excuse a guess:
'send' seems to loop to send out 8 bits, 'r17' seems to hold the data to be sent.
Code:
ldi r17,$0f  ; low byte to be sent
call send
ldi r17,$f0 ; high byte to be sent
call send
Seems to send the four low bits followed by the four high bits, but both as 8 bit transfers.
The size and bit positions of the data don't seem to match the bit placements in the serial output. As the data in the final code only sends zeros it would appear to be correct.

Brian.
Sorry! I didn't get where the 4bits you are talking about come from??? But, I'm going to explain my code and I want to let you know that the code is working fine, and I can output any value I want to 16 Led's on my breadboard attached to my Arduino UNO!
The idea behind the code is:
1-load the first 8 bits in the register r17
2-call the function send which will shift the 8 bits to be sent through the carry into the portb0 pin.
3-load the second 8 bits in the register r17
4-call the send function again

Now, I'm going to explain the send function:


Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
send:  ldi r16,$08    ;number of bits to be sent which is 8bit
     
loop:    lsr  r17 ;  right shift through the carry
    call clock  ; call the clock function
    brcs one  ; branch if carry is 1 to one
    cbi portb,0 ; make portb0 low
    call delay ; call delay
    rjmp go
one:    sbi portb,0 ; make portb0 high
go:    dec r16 ; is 8 bits sent yet?
    brne loop ; no! Continue shift data
    sbi portd,7; clock the last bit
        ret

 

Hi,

May I ask why you do bit banging instead of using the SPI periferal?

BIT BANGING:
* more code
* more complicated code
* consumes 100% processing power
* slow
* unprecise timing
* currently only one way
* when doing full duplex you need to reconsider all the timings
* more power consuming, no chance to use sleep modes during data transfer.

Klaus
 
I was using exclusively Microchip controllers in the past, and I'm learning the AVR from the scratch now! My goal is to learn its architecture from the ground up, this code is not meant to be used in an actual project, just me playing around with assembly language! For my future project I will use SPI that's for sure!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top