Programmieren für Fortgeschrittene - Assembler - Teil 3 - AZ-Delivery

After a blink example has already been implemented in the previous part, further examples follow to get to know the central hardware functions of the ATMEGA328P in Assembler and to control them in a targeted manner.

LED bland

The first project is supposed to lighten an LED slowly. The brightness control can be carried out on the ATMEGA328P via the PWM function.

PWM:

This abbreviation stands for "PUlse WIdth MOdulation ”, which can be translated into German with“ pulse width modulation ”. This is a signal that is switched on or off within a fixed period. The ratio between the time switched off (high state) is as Duty cycle (Duty ratio).

In order to be able to effectively regulate the brightness of the luminous diode, the use of this effect is recommended. Because the brightness can be adjusted directly via the tactning ratio, since this corresponds to the duration of how long the LED is switched on.
In order to make the LED appear darker for our eye, only the repeating of the cycles (frequency) has to be increased, so there is no flickering.


In the Arduino IDE, the PWM control would be easy with that Analogwrite () Command possible.
However, since you want to get to know the internal structure of the microcontroller in this tutorial, a look at the data sheet must be taken again.

Program process:


As you already know from the last part, the value in the timer register is increased over time until 255. Two special registers are connected to each timer, the so -called Outter Compar REgister (OCR). As can be concluded from the name, its content is compared with the timer content.
The ATMEGA328P has 3 internal timers, each contain two output compare registers. This OCR are connected to an IO PIN, the so -called OC PIN, which can accept the condition depending on the result of the comparison. This behavior must be in Outter Compar FLAG (OCF) Bits.

If the timer register is at value 0, the digital IO output is switched on (high). The timer value corresponds to the value of the Outter Compar REgister (OCR), the output is switched off to low.
This means that the Duty Cycle can be determined via the OCR.

(Data sheet p.75 p.84)

The frequency of the PWM signal can be determined by the Prescaler.

Example:

For the example, Timer0 is used from the blink example.

.include "m328pdef.inc" ;1

.org 0x0000
rjmp main  ;2

Main:
 
SBI GDRD, PD6; 3

  
ldi r16, (1<<WGM01)|(1<<WGM00)|(1<<COM0A1)
  
out TCCR0A, r16 ;4

  
ldi r16, (1<<CS01)|(1<<CS00)
  
out TCCR0B, r16 ;5

  
ldi r1685
  
out OCR0A, r16 ;6

  
rjmp main

 

First, as usual, the register names are loaded from the included file (1). Afterwards, a jump to the Main label is made at the reset's storage point (2).

Here is the PIN PD6, on which the Output Compare Pin OC0A set in the starting mode through the data direction register (3).
The timer is then configured. In register TCCR0A the PWM functionality is configured (4) and in TCCR0B, as in the last part, the Prescal set (5).
In OCR0A can now be set the Duty Cycle.

The program can here be downloaded.

Result:

Figure 1: PWM Signal with 33% Duty Cycle (example)

 

Figure 2: PWM Signal with 50% Duty Cycle (OCR0A = 127)

 

Bitshifting

This example uses a new command that could occur cryptically at first glance:
LDI R16, (1 << WGM01) | (1 << WGM00) | (1 << com0a1)

 

With the BITSHIFTING command 1 << 6, for example, Bit 1 would be pushed to the left by 6 places, which would lead to the result 00100000. In the example above, the names such as ‘WGM01’ the position of the Bits in the register.
Thus ‘1 << WGM01’ one 1 in the bit WGM01. These positions are saved in the included file.

However, since other bits are to be set, the ‘logical or’ is necessary. This makes a comparison in all three bits and thus generates the register with all set bits.

Example:
00100000 | 00010000 | 10000000  Result: 10110000

 

Diploma

Finally, the program should slowly light up the LED. This means that the Duty Cycle must always be increased.
In order to regulate the speed, the Delay function is used from the blink program of the previous part.

 

 

Hardware:

For the example you need the following components:
ATMEGA328 microcontroller (variants: USB-C or USB-B)

LED (LED range)

Resistance 220𝝮 (Resistance range)

 

Connect an LED to the microcontroller as follows:

Figure 3: circuit diagram


Software:

Compile the following program and load the .hex file to the microcontroller.
Here you can do that Download program.

 

Macros

Since the waiting function is used in almost every example, it should now be changed so that it can be called up like the Delay () function in the Arduino IDE at any time, with the waiting time as a parameter.
For this, the assembler language offers the so -called macro. This can create a program part with several parameters.
The new waiting function should have a parameter, which the waiting time can be specified in milliseconds.

Since the number room in the classic 8-bit registers is very limited, a 16-bit register is now created. The theory for this was already in first part discussed.

 

macro

The definition of a macros is relatively simple:
.macro name

 

The name of the macro is then reused to call it up in the program. Parameters can be set behind the name, of course it is also possible to use several parameters.

 

The content of the parameters after the call can be called up with @ and the number.

For example:
LDI R16, @0

 

Finally, the macro section has to go with:

.endmacro

 

to be ended.

program

To get an efficient program, this is divided into two parts. The first initializes the timer by putting the corresponding bits in the registers.

init_timer0:
    
ldi temp, (1 << CS01) | (1 << CS00) ; Prescaler 64
    
out TCCR0B, temp

    
ldi temp, (1 << TOIE0)
    
sts TIMSK0, temp

    
sei
    
ret

 

The second part is the actual macro, which is called up as a parameter at the waiting time in milliseconds:

.macro delay
   
   
push r24
   
push r25

   
LDI r24, low (@0)
   
LDI r25, High (@0)

    
 clr overflowsL
    
clr overflowsH

  
 wait_loop:
    
cp overflowsL, r24
    
cpc overflowsH, r25
    
brne wait_loop

   
pop r25
   
pop r24
   
.endmacro

The macro uses the RAM to temporarily store the number of overflows that have to pass until the desired waiting time is reached. The process corresponds to the program from part 2.

Due to the Prescaler, the duration of an overflow is set to about one millisecond. However, since the actual duration is about 1.024 ms, there may be little inaccuracies for longer Delay times.

 

The macro can be called up as follows:
Delay 1000

 

You can here download.


Conclusion

In the next part, you will also get to know the Inline Assembler of Arduino IDE, among other things, with which it is possible to integrate individual code sections into the classic Arduino C code.

 

Have fun recovery :)

Projekte für fortgeschrittene

Deja un comentario

Todos los comentarios son moderados antes de ser publicados