PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AVR und Umstieg von Assembler auf C Programmierung



hegewald
08.02.2015, 18:47
Auweia....da hab ich mir in meinem betagten Alter ja was vorgenommen.
Seit Jahren programmiere ich die AVR-Familie hobbymäßig in Assembler.
Ortungspieper für Modell-Flächenmodelle, Kransteuerungen für Modelleisenbahn usw.
Was mir keine Ruhe lässt, wäre ein Roboter-Bausatz von der Fa. Reichelt.
Auf dem Sockel sitzt ein Atmega16.
Zur Zeit habe ich Studio4 von Atmel auf dem Nootebok.
Ein Kollege meinte heute, ich solle mich auf C konzentrieren und nicht C++.
Ein Anfängerbuch liegt hier vor mir.
Ich solle die Entwicklungsumgebung winAVR "Programmers Notepad 2
Version v.2.0.5.32" mit dem GNU - Compiler Vers. 3.4.1. aus dem Internet
runter laden.
Das Buch ist schon älter, wäre diese Version noch aktuell?
Mit meinen Studio4 kann ich mit C wahrscheinlich nichts anfangen, oder?
Innerlich bin ich gegen C etwas voreingenommen, wenn ich öfters mal das "IF" sehe.
Das erinnert mich so an die 70er Jahre, wo das GFA-Basic aktuell war.
Auf der anderen Seite ist es mit Assembler ein Zeilenaufwand, um eine Zeitschleife
von 5 Sekunden aufzubauen.

Grüße

Rolf

markusj
08.02.2015, 20:50
Hallo Rolf,

inzwischen ist WinAVR Geschichte, die Toolchain gibt es jetzt direkt von Atmel (http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx).
Die Version von Programmers Notepad ist ziemlich egal und AVR Studio 4 sollte auch mit der AVR Toolchain funktionieren.

mfG
Markus

Peter(TOO)
08.02.2015, 22:00
Hallo Rolf,

Da gehe ich mit deinem Kollegen einig, C++ ist nicht wirklich ideal auf µC, das braucht schnell ml zu viel Code.

Was hast du gegen "if"?
"CMP" braucht man in Assembler auch jede Menge oder halt die ganzen "BRx".

Der C-Compiler hat übrigens eine Option welche dir ein Listing mit deinem C-Code erzeugt und zusätzlich das was er als Assembler daraus gestrickt hat ;-)
Wenn du einen Compiler mit guter Optimierung hast, wirst du dich als Assembler-Programmiere oft erst einmal etwas wundern; da kommt oft recht genialer Code dabei raus!

MfG Peter(TOO)

hegewald
09.02.2015, 08:48
danke für Eure Antworten! Peter hat schon Recht, wenn ich in Assembler 20 Pseudobefehle brxx entdecke,
die unterschiedlich auf das Register "SREG" mit seinen Bits Carry, Zero usw. zugreifen.
Ich könnte ja mal ganz einfach mit meinen Studio4 beginnen, indem ich eine LED zum blinken bewege.
Das Buch ist von Günter Schmitt (5.Auflage Oldenburg). Programmieren in Assembler und C
Schaltungen und Anwendungen. Ist empfehlenswert.

Grüße

Rolf
halte Euch auf den Laufenden!

oberallgeier
09.02.2015, 14:34
... in meinem betagten Alter ja was vorgenommen ... Zur Zeit habe ich Studio4 von Atmel auf dem Nootebok ...Hallo Rolf,

du bist nicht der einzige Grauhaardackel oder UHU (Unter HUndert) hier im Forum. Ich habe übrigens vor ein paar Jahren mit Assembler auf AVRs angefangen (mit Blick auf alte Z80-Erfahrungen mit Assembler und FORTRAN), bin aber nach ein, zwei Jahren auf C übergegangen. Das ist bei mir immer noch eine Art sehr persönlicher Dialekt, sprich "Cäh" *ggg* aber es geht so.

Zu Studio4 kann ich nur sagen, dass ich nach Ausflügen in die Version AVRStudio5 und -6 wieder zu Version vier zurückkam (Version 4.18 Build 700 auf WIN7pro64). Gerade die Version 6 hat einen hübsch großen Overhead, der für richtig große Projekte bestimmt sinnvoll ist. Bei meinem aktuell größten Projekt, einem Roboter mit aktuell sieben (Controller-)Platinen, dazu MOtortreiberplatine etc., insgesamt vermutlich irgendwo bei dreissig- bis vierzigtausend Zeilen C, ist das für mich immer noch übersichtlich genug. Andererseits findet sich ein junger Programmierer aus meinem Umfeld (19J, Jugend-forscht-Team) prächtig wohl mit der 6er-Version auf nem Notebook für ein mega328er Projekt und an die dreitausend Codezeilen.

Nun mal ein kleiner Appetithappen. Peter hat schon davon geschrieben: "...C-Compiler ... Option ... C-Code erzeugt und zusätzlich ... Assembler ...".

Beispiel ist hier der so genannte *.lls-file aus einem meiner Projektchen als Teil des Compilats aus dem Studio4; vollständig und ohne Änderungen. Darin findest Du einiges an Assemblermnemonics und verteilt darin die originalen C-Sequenzen. Durch diese eingestreuten Quellzeilen ist eine perfekte Navigation von Deinem C-Code aus durch die maschinenlauffähige Programmversion möglich - siehe rot markierte Zeile "int main(void) //. " in beiden Beispielen.


tstu.elf: file format elf32-avr

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000290 00000000 00000000 00000074 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000022 00800060 00000290 00000304 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .debug_aranges 00000020 00000000 00000000 00000326 2**0
CONTENTS, READONLY, DEBUGGING
3 .debug_pubnames 000000ae 00000000 00000000 00000346 2**0
CONTENTS, READONLY, DEBUGGING
4 .debug_info 000007f8 00000000 00000000 000003f4 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_abbrev 0000017b 00000000 00000000 00000bec 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_line 000004bf 00000000 00000000 00000d67 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_frame 000000c0 00000000 00000000 00001228 2**2
CONTENTS, READONLY, DEBUGGING
8 .debug_str 0000014f 00000000 00000000 000012e8 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_loc 000002b7 00000000 00000000 00001437 2**0
CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
0: 0c 94 2a 00 jmp 0x54 ; 0x54 <__ctors_end>
4: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
8: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
c: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
10: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
14: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
18: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
1c: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
20: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
24: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
28: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
2c: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
30: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
34: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
38: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
3c: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
40: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
44: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
48: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
4c: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>
50: 0c 94 3f 00 jmp 0x7e ; 0x7e <__bad_interrupt>

00000054 <__ctors_end>:
54: 11 24 eor r1, r1
56: 1f be out 0x3f, r1 ; 63
58: cf e5 ldi r28, 0x5F ; 95
5a: d8 e0 ldi r29, 0x08 ; 8
5c: de bf out 0x3e, r29 ; 62
5e: cd bf out 0x3d, r28 ; 61

00000060 <__do_copy_data>:
60: 10 e0 ldi r17, 0x00 ; 0
62: a0 e6 ldi r26, 0x60 ; 96
64: b0 e0 ldi r27, 0x00 ; 0
66: e0 e9 ldi r30, 0x90 ; 144
68: f2 e0 ldi r31, 0x02 ; 2
6a: 02 c0 rjmp .+4 ; 0x70 <.do_copy_data_start>

0000006c <.do_copy_data_loop>:
6c: 05 90 lpm r0, Z+
6e: 0d 92 st X+, r0

00000070 <.do_copy_data_start>:
70: a2 38 cpi r26, 0x82 ; 130
72: b1 07 cpc r27, r17
74: d9 f7 brne .-10 ; 0x6c <.do_copy_data_loop>
76: 0e 94 ee 00 call 0x1dc ; 0x1dc <main>
7a: 0c 94 46 01 jmp 0x28c ; 0x28c <_exit>

0000007e <__bad_interrupt>:
7e: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

00000082 <lcd_send>:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//Eigentliche LCD-Zugriffs-Funktion; 4-Bit-Modus
void lcd_send(unsigned char data) {
// oberes Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | ((data >> 4) & 0x0F);
82: 98 b3 in r25, 0x18 ; 24
84: 28 2f mov r18, r24
86: 22 95 swap r18
88: 2f 70 andi r18, 0x0F ; 15
8a: 90 7f andi r25, 0xF0 ; 240
8c: 29 2b or r18, r25
8e: 28 bb out 0x18, r18 ; 24
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
90: 31 e0 ldi r19, 0x01 ; 1
92: 93 2f mov r25, r19
94: 9a 95 dec r25
96: f1 f7 brne .-4 ; 0x94 <lcd_send+0x12>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
98: c5 9a sbi 0x18, 5 ; 24
9a: 23 e0 ldi r18, 0x03 ; 3
9c: 92 2f mov r25, r18
9e: 9a 95 dec r25
a0: f1 f7 brne .-4 ; 0x9e <lcd_send+0x1c>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
a2: c5 98 cbi 0x18, 5 ; 24
// oberes Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | ((data >> 4) & 0x0F);
_delay_us(5);
lcd_enable();
// unteres Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | (data & 0x0F);
a4: 98 b3 in r25, 0x18 ; 24
a6: 8f 70 andi r24, 0x0F ; 15
a8: 90 7f andi r25, 0xF0 ; 240
aa: 98 2b or r25, r24
ac: 98 bb out 0x18, r25 ; 24
ae: 3a 95 dec r19
b0: f1 f7 brne .-4 ; 0xae <lcd_send+0x2c>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
b2: c5 9a sbi 0x18, 5 ; 24
b4: 2a 95 dec r18
b6: f1 f7 brne .-4 ; 0xb4 <lcd_send+0x32>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
b8: c5 98 cbi 0x18, 5 ; 24
ba: 84 e1 ldi r24, 0x14 ; 20
bc: 8a 95 dec r24
be: f1 f7 brne .-4 ; 0xbc <lcd_send+0x3a>
// unteres Nibble setzen
LCD_PORT = (LCD_PORT & 0xF0) | (data & 0x0F);
_delay_us(5);
lcd_enable();
_delay_us(60);
LCD_PORT &= 0xF0;
c0: 88 b3 in r24, 0x18 ; 24
c2: 80 7f andi r24, 0xF0 ; 240
c4: 88 bb out 0x18, r24 ; 24
}
c6: 08 95 ret

000000c8 <lcd_command>:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// sendet einen Befehl an das LCD

void lcd_command(unsigned char temp1)
{
LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
c8: c4 98 cbi 0x18, 4 ; 24
lcd_send(temp1);
ca: 0e 94 41 00 call 0x82 ; 0x82 <lcd_send>
}
ce: 08 95 ret

000000d0 <lcd_data>:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// sendet ein Datenbyte an das LCD

void lcd_data(unsigned char temp1)
{
LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
d0: c4 9a sbi 0x18, 4 ; 24
lcd_send(temp1);
d2: 0e 94 41 00 call 0x82 ; 0x82 <lcd_send>
}
d6: 08 95 ret

000000d8 <lcd_enable>:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
d8: c5 9a sbi 0x18, 5 ; 24
da: 83 e0 ldi r24, 0x03 ; 3
dc: 8a 95 dec r24
de: f1 f7 brne .-4 ; 0xdc <lcd_enable+0x4>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
e0: c5 98 cbi 0x18, 5 ; 24
}
e2: 08 95 ret

000000e4 <lcd_clear>:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Sendet den Befehl zur Löschung des Displays

void lcd_clear(void)
{
lcd_command(CLEAR_DISPLAY);
e4: 81 e0 ldi r24, 0x01 ; 1
e6: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>
milliseconds can be achieved.
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
ea: 82 ee ldi r24, 0xE2 ; 226
ec: 94 e0 ldi r25, 0x04 ; 4
ee: 01 97 sbiw r24, 0x01 ; 1
f0: f1 f7 brne .-4 ; 0xee <lcd_clear+0xa>
_delay_ms(5);
}
f2: 08 95 ret

000000f4 <lcd_init>:
// Initialisierung:
// Muss ganz am Anfang des Programms aufgerufen werden.

void lcd_init(void)
{
LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN1); // Port auf Ausgang schalten
f4: 87 b3 in r24, 0x17 ; 23
f6: 8f 63 ori r24, 0x3F ; 63
f8: 87 bb out 0x17, r24 ; 23
fa: 8c e4 ldi r24, 0x4C ; 76
fc: 9d e1 ldi r25, 0x1D ; 29
fe: 01 97 sbiw r24, 0x01 ; 1
100: f1 f7 brne .-4 ; 0xfe <lcd_init+0xa>
// muss 3mal hintereinander gesendet werden zur Initialisierung
_delay_ms(30);
LCD_PORT = (LCD_PORT & 0xF0 & ~(1<<LCD_RS)) | 0x03;
102: 88 b3 in r24, 0x18 ; 24
104: 80 7e andi r24, 0xE0 ; 224
106: 83 60 ori r24, 0x03 ; 3
108: 88 bb out 0x18, r24 ; 24

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
10a: c5 9a sbi 0x18, 5 ; 24
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
10c: 93 e0 ldi r25, 0x03 ; 3
10e: 89 2f mov r24, r25
110: 8a 95 dec r24
112: f1 f7 brne .-4 ; 0x110 <lcd_init+0x1c>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
114: c5 98 cbi 0x18, 5 ; 24
milliseconds can be achieved.
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
116: e2 ee ldi r30, 0xE2 ; 226
118: f4 e0 ldi r31, 0x04 ; 4
11a: 31 97 sbiw r30, 0x01 ; 1
11c: f1 f7 brne .-4 ; 0x11a <lcd_init+0x26>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
11e: c5 9a sbi 0x18, 5 ; 24
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
120: 89 2f mov r24, r25
122: 8a 95 dec r24
124: f1 f7 brne .-4 ; 0x122 <lcd_init+0x2e>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
126: c5 98 cbi 0x18, 5 ; 24
milliseconds can be achieved.
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
128: 2a ef ldi r18, 0xFA ; 250
12a: 30 e0 ldi r19, 0x00 ; 0
12c: f9 01 movw r30, r18
12e: 31 97 sbiw r30, 0x01 ; 1
130: f1 f7 brne .-4 ; 0x12e <lcd_init+0x3a>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
132: c5 9a sbi 0x18, 5 ; 24
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
134: 89 2f mov r24, r25
136: 8a 95 dec r24
138: f1 f7 brne .-4 ; 0x136 <lcd_init+0x42>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
13a: c5 98 cbi 0x18, 5 ; 24
milliseconds can be achieved.
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
13c: f9 01 movw r30, r18
13e: 31 97 sbiw r30, 0x01 ; 1
140: f1 f7 brne .-4 ; 0x13e <lcd_init+0x4a>
lcd_enable();

_delay_ms(1);
lcd_enable();
_delay_ms(1);
LCD_PORT = (LCD_PORT & 0xF0 & ~(1<<LCD_RS)) | 0x02;
142: 88 b3 in r24, 0x18 ; 24
144: 80 7e andi r24, 0xE0 ; 224
146: 82 60 ori r24, 0x02 ; 2
148: 88 bb out 0x18, r24 ; 24
14a: f9 01 movw r30, r18
14c: 31 97 sbiw r30, 0x01 ; 1
14e: f1 f7 brne .-4 ; 0x14c <lcd_init+0x58>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// erzeugt den Enable-Puls
void lcd_enable(void)
{
LCD_PORT |= (1<<LCD_EN1);
150: c5 9a sbi 0x18, 5 ; 24
can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
152: 9a 95 dec r25
154: f1 f7 brne .-4 ; 0x152 <lcd_init+0x5e>
_delay_us(10); // kurze Pause
// Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
// http://www.mikrocontroller.net/topic/80900
LCD_PORT &= ~(1<<LCD_EN1);
156: c5 98 cbi 0x18, 5 ; 24
milliseconds can be achieved.
*/
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
158: c9 01 movw r24, r18
15a: 01 97 sbiw r24, 0x01 ; 1
15c: f1 f7 brne .-4 ; 0x15a <lcd_init+0x66>
_delay_ms(1);
lcd_enable();
_delay_ms(1);

// 4Bit / 2 Zeilen / 5x7
lcd_command(CMD_SetIFOptions | 0x08);
15e: 88 e2 ldi r24, 0x28 ; 40
160: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>

// Display ein / Cursor aus / kein Blinken
lcd_command(CMD_SetDisplayAndCursor | 0x04);
164: 8c e0 ldi r24, 0x0C ; 12
166: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>

// inkrement / kein Scrollen
lcd_command(CMD_SetEntryMode | 0x02);
16a: 86 e0 ldi r24, 0x06 ; 6
16c: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>
lcd_clear();
170: 0e 94 72 00 call 0xe4 ; 0xe4 <lcd_clear>
}
174: 08 95 ret

00000176 <lcd_string>:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Schreibt einen String auf das LCD

void lcd_string(char *data)
{
176: cf 93 push r28
178: df 93 push r29
17a: ec 01 movw r28, r24
17c: 03 c0 rjmp .+6 ; 0x184 <lcd_string+0xe>
while(*data) {
lcd_data(*data);
17e: 0e 94 68 00 call 0xd0 ; 0xd0 <lcd_data>
data++;
182: 21 96 adiw r28, 0x01 ; 1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Schreibt einen String auf das LCD

void lcd_string(char *data)
{
while(*data) {
184: 88 81 ld r24, Y
186: 88 23 and r24, r24
188: d1 f7 brne .-12 ; 0x17e <lcd_string+0x8>
lcd_data(*data);
data++;
}
}
18a: df 91 pop r29
18c: cf 91 pop r28
18e: 08 95 ret

00000190 <lcd_generatechar>:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im RAM
void lcd_generatechar(uint8_t code, const uint8_t *data)
{ //
190: 0f 93 push r16
192: 1f 93 push r17
194: cf 93 push r28
196: df 93 push r29
198: 8b 01 movw r16, r22
lcd_command(LCD_SET_CGADR|(code<<3)); // Startposition des Zeichens einstellen
19a: 88 0f add r24, r24
19c: 88 0f add r24, r24
19e: 88 0f add r24, r24
1a0: 80 64 ori r24, 0x40 ; 64
1a2: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>
1a6: c0 e0 ldi r28, 0x00 ; 0
1a8: d0 e0 ldi r29, 0x00 ; 0
for (uint8_t i=0; i<8; i++) // Bitmuster übertragen
{ //
lcd_data(data[i]); //
1aa: f8 01 movw r30, r16
1ac: ec 0f add r30, r28
1ae: fd 1f adc r31, r29
1b0: 80 81 ld r24, Z
1b2: 0e 94 68 00 call 0xd0 ; 0xd0 <lcd_data>
1b6: 21 96 adiw r28, 0x01 ; 1
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im RAM
void lcd_generatechar(uint8_t code, const uint8_t *data)
{ //
lcd_command(LCD_SET_CGADR|(code<<3)); // Startposition des Zeichens einstellen
for (uint8_t i=0; i<8; i++) // Bitmuster übertragen
1b8: c8 30 cpi r28, 0x08 ; 8
1ba: d1 05 cpc r29, r1
1bc: b1 f7 brne .-20 ; 0x1aa <lcd_generatechar+0x1a>
{ //
lcd_data(data[i]); //
} //
} // Ende void lcd_generatechar(uint8_t code,
1be: df 91 pop r29
1c0: cf 91 pop r28
1c2: 1f 91 pop r17
1c4: 0f 91 pop r16
1c6: 08 95 ret

000001c8 <wms>:
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
1c8: 20 e4 ldi r18, 0x40 ; 64
1ca: 36 e0 ldi r19, 0x06 ; 6
1cc: 04 c0 rjmp .+8 ; 0x1d6 <wms+0xe>
1ce: f9 01 movw r30, r18
1d0: 31 97 sbiw r30, 0x01 ; 1
1d2: f1 f7 brne .-4 ; 0x1d0 <wms+0x8>
// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
1d4: 01 97 sbiw r24, 0x01 ; 1
1d6: 00 97 sbiw r24, 0x00 ; 0
1d8: d1 f7 brne .-12 ; 0x1ce <wms+0x6>
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
1da: 08 95 ret

000001dc <main>:
// === HAUPTProgramm ================================================== ======== =
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int main(void) //
{ //
// - - - - - - - - - - - - - - -
DDRA = 0b00000000; // Alles auf Eingang mit (0)
1dc: 1a ba out 0x1a, r1 ; 26
PORTA = 0b11111111; // mit PullUp (1)
1de: 8f ef ldi r24, 0xFF ; 255
1e0: 8b bb out 0x1b, r24 ; 27
//
DDRB = 0b11111111; // Ausgänge mit (1)
1e2: 87 bb out 0x17, r24 ; 23
PORTB = 0b00000000; //
1e4: 18 ba out 0x18, r1 ; 24
//
DDRC = 0b11000000; //
1e6: 90 ec ldi r25, 0xC0 ; 192
1e8: 94 bb out 0x14, r25 ; 20
PORTC = 0b00111111; //
1ea: 9f e3 ldi r25, 0x3F ; 63
1ec: 95 bb out 0x15, r25 ; 21
//
DDRD = 0b00000000; //
1ee: 11 ba out 0x11, r1 ; 17
PORTD = 0b11111111; //
1f0: 82 bb out 0x12, r24 ; 18
1f2: 88 ee ldi r24, 0xE8 ; 232
1f4: 93 e0 ldi r25, 0x03 ; 3
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
1f6: 20 e4 ldi r18, 0x40 ; 64
1f8: 36 e0 ldi r19, 0x06 ; 6
1fa: f9 01 movw r30, r18
1fc: 31 97 sbiw r30, 0x01 ; 1
1fe: f1 f7 brne .-4 ; 0x1fc <main+0x20>
// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
200: 01 97 sbiw r24, 0x01 ; 1
202: d9 f7 brne .-10 ; 0x1fa <main+0x1e>
// NC (TasteC) SCK, PB7 NC Pin8 |___________________________
// GND Pin9
// Vcc Pn10 | Anmerkg: ENABLE line !
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wms( 1000 ); // Wait
lcd_init(); //
204: 0e 94 7a 00 call 0xf4 ; 0xf4 <lcd_init>
208: 88 ee ldi r24, 0xE8 ; 232
20a: 93 e0 ldi r25, 0x03 ; 3
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
20c: 20 e4 ldi r18, 0x40 ; 64
20e: 36 e0 ldi r19, 0x06 ; 6
210: f9 01 movw r30, r18
212: 31 97 sbiw r30, 0x01 ; 1
214: f1 f7 brne .-4 ; 0x212 <main+0x36>
// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
216: 01 97 sbiw r24, 0x01 ; 1
218: d9 f7 brne .-10 ; 0x210 <main+0x34>
// Vcc Pn10 | Anmerkg: ENABLE line !
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wms( 1000 ); // Wait
lcd_init(); //
wms( 1000 ); // Wait
lcd_clear(); // Vor LCD-Ausgabe Display leeren
21a: 0e 94 72 00 call 0xe4 ; 0xe4 <lcd_clear>
21e: 88 ee ldi r24, 0xE8 ; 232
220: 93 e0 ldi r25, 0x03 ; 3
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
222: 20 e4 ldi r18, 0x40 ; 64
224: 36 e0 ldi r19, 0x06 ; 6
226: f9 01 movw r30, r18
228: 31 97 sbiw r30, 0x01 ; 1
22a: f1 f7 brne .-4 ; 0x228 <main+0x4c>
// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
22c: 01 97 sbiw r24, 0x01 ; 1
22e: d9 f7 brne .-10 ; 0x226 <main+0x4a>
wms( 1000 ); // Wait

// - - - - - - - - - - - - - - -
//lcd_string("Grußoberallgeier");
//lcd_string("Gruss 18.9.19:23");
lcd_string("ABCDefghIJKLmnop");
230: 80 e6 ldi r24, 0x60 ; 96
232: 90 e0 ldi r25, 0x00 ; 0
234: 0e 94 bb 00 call 0x176 ; 0x176 <lcd_string>
238: 88 ee ldi r24, 0xE8 ; 232
23a: 93 e0 ldi r25, 0x03 ; 3
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
23c: 20 e4 ldi r18, 0x40 ; 64
23e: 36 e0 ldi r19, 0x06 ; 6
240: f9 01 movw r30, r18
242: 31 97 sbiw r30, 0x01 ; 1
244: f1 f7 brne .-4 ; 0x242 <main+0x66>
// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
246: 01 97 sbiw r24, 0x01 ; 1
248: d9 f7 brne .-10 ; 0x240 <main+0x64>
// - - - - - - - - - - - - - - -
//void wms(uint16_t ms) // Waitroutine
wms( 1000 ); // Wait

// - - - - - - - - - - - - - - -
Line2(); // An den Anfang der 2. Zeile springen
24a: 80 ec ldi r24, 0xC0 ; 192
24c: 0e 94 64 00 call 0xc8 ; 0xc8 <lcd_command>
lcd_string(" So gehts ;-) "); // Zeile löschen
250: 81 e7 ldi r24, 0x71 ; 113
252: 90 e0 ldi r25, 0x00 ; 0
254: 0e 94 bb 00 call 0x176 ; 0x176 <lcd_string>

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return 0; //
} //
258: 80 e0 ldi r24, 0x00 ; 0
25a: 90 e0 ldi r25, 0x00 ; 0
25c: 08 95 ret

0000025e <lcd_eep_string>:
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//String aus EEPROM laden und an LCD senden
void lcd_eep_string(const unsigned char *data)
{ //
25e: cf 93 push r28
260: df 93 push r29
262: ec 01 movw r28, r24
unsigned char c;
while(1) //
{ //
c = eeprom_read_byte(data); //
264: ce 01 movw r24, r28
266: 0e 94 3e 01 call 0x27c ; 0x27c <__eerd_byte_m32>
if(c==0) return; //
26a: 88 23 and r24, r24
26c: 21 f0 breq .+8 ; 0x276 <lcd_eep_string+0x18>
lcd_data(c); //
26e: 0e 94 68 00 call 0xd0 ; 0xd0 <lcd_data>
data++; //
272: 21 96 adiw r28, 0x01 ; 1
274: f7 cf rjmp .-18 ; 0x264 <lcd_eep_string+0x6>
}
} // Ende void lcd_eep_string(const
276: df 91 pop r29
278: cf 91 pop r28
27a: 08 95 ret

0000027c <__eerd_byte_m32>:
27c: e1 99 sbic 0x1c, 1 ; 28
27e: fe cf rjmp .-4 ; 0x27c <__eerd_byte_m32>
280: 9f bb out 0x1f, r25 ; 31
282: 8e bb out 0x1e, r24 ; 30
284: e0 9a sbi 0x1c, 0 ; 28
286: 99 27 eor r25, r25
288: 8d b3 in r24, 0x1d ; 29
28a: 08 95 ret

0000028c <_exit>:
28c: f8 94 cli

0000028e <__stop_program>:
28e: ff cf rjmp .-2 ; 0x28e <__stop_program>

Ach so - noch eben das Mainmodul dazu:

/* >>
Stand ..\C3\tstu\tstu_mega32.c
================================================== ============================= =
*** Aufgabenstellung : LCD auf Port B !!! des mega644/8 MHz int. Osc.
================================================== ============================ */
#define F_CPU 1e6
// - - - - - - - - - - - - - - - -
#include <lcd_162_xta.c> // LCD-Lib ähnlich Tr-Tester, akt. PORTB, PB0..7
//#include <lcd_162_mini-no-wait.c> // LCD-Lib ähnl Tr-Tester, PORTB, PB0..7
// ================================================== =========================== =


// ================================================== =========================== =
// ================================================== =========================== =
//### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms) //
{
for(; ms>0; ms--)
{
uint16_t __c = 1600;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
// ================================================== =========================== =


// ================================================== =========================== =
// === HAUPTProgramm ================================================== ======== =
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int main(void) //
{ //
// - - - - - - - - - - - - - - -
DDRA = 0b00000000; // Alles auf Eingang mit (0)
PORTA = 0b11111111; // mit PullUp (1)
//
DDRB = 0b11111111; // Ausgänge mit (1)
PORTB = 0b00000000; //
//
DDRC = 0b11000000; //
PORTC = 0b00111111; //
//
DDRD = 0b00000000; //
PORTD = 0b11111111; //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - -
// ####>>>> Initialisierung/Anschlüsse von PORT B für LCD DEM 16x2
// data bit 4 PB0 0 A WS Pin1 |
// data bit 5 PB1 1 A Pin2 | -- Der 10-polige Wannenstecker
// data bit 6 PB2 2 A Pin3 | ist an die Belegung
// data bit 7 SCK, PB3 3 A Pin4 | des Transitortester angepasst
// RS line PB4 RS Pin5 | es kommen noch
// ENABLE line MOSI, PB5 EN1 Pin6 | Pin 9 GND und
// R/W (offen) MISO, PB6 R/W Pin7 | Pin 10 Vcc dazu
// NC (TasteC) SCK, PB7 NC Pin8 |___________________________
// GND Pin9
// Vcc Pn10 | Anmerkg: ENABLE line !
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wms( 1000 ); // Wait
lcd_init(); //
wms( 1000 ); // Wait
lcd_clear(); // Vor LCD-Ausgabe Display leeren
// - - - - - - - - - - - - - - -
wms( 1000 ); // Wait

// - - - - - - - - - - - - - - -
lcd_string("ABCDefghIJKLmnop");

// - - - - - - - - - - - - - - -
//void wms(uint16_t ms) // Waitroutine
wms( 1000 ); // Wait

// - - - - - - - - - - - - - - -
Line2(); // An den Anfang der 2. Zeile springen
lcd_string(" So gehts ;-) "); // Zeile löschen

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return 0; //
} //
// ===== Ende des Testabschnittes, er kann aus mehreren Abschnitten bestehen ====
// ================================================== =============================
/* Übersetzungskommentar (tstu) Programsize Datasize
Build 20.1.2014 at 11:50:13 11224 bytes (34.3% Full) 1960 bytes (95.7% Full)

================================================== ========== */

askazo
09.02.2015, 15:13
Da gehe ich mit deinem Kollegen einig, C++ ist nicht wirklich ideal auf µC, das braucht schnell ml zu viel Code.
Das würde ich nicht grundsätzlich so sagen. Wenn man nicht gerade sehr zeitkritisch arbeiten oder stark mit dem Speicherplatz knausern muss, ist C++ eine enorme Erleichterung beim µC programmieren.
Viele Dinge sind ja im µC mehrfach vorhanden (ADCs, UARTs, SPIs etc.) - da bietet es sich wirklich an, für jedes Peripherie-Modul eine Klasse zu schreiben.
Die Wiederverwendbarkeit und Übersichtlichkeit des Codes wächst damit ungemein.

Gruß,
askazo

Besserwessi
09.02.2015, 17:20
Auch wenn man später ggf. doch lieber C++ nutzt, schadet es nichts wenn man auch C kennt. Vieles ist da noch gleich und ordentlicher C Code ist meistens auch noch gültiger C++ Code.

Man sollte sich aber schon vom ASM Code lösen - den ASM Code schaut man sich eigentlich nur an, wenn man Zweifel hat (ob man C richtig verstanden hat), oder sehr zeitkritischen Code hat. Vieles geht in C schon einfacher als in ASM - vor allem Sachen mit Vergleichen und 16/32 Bit Zahlen.

oberallgeier
09.02.2015, 17:34
... den ASM Code schaut man sich eigentlich nur an, wenn man Zweifel hat (ob man C richtig verstanden hat), oder sehr zeitkritischen Code ...Genau. So prüfe ich z.B. bei einigen interrupt"verseuchten" Programmen die theoretisch mögliche Laufzeit wenn alle Interrupts nacheinander ablaufen
anhand der aus der *.lls-Datei gefundenen Summe aller ISR-Taktzeiten. Wenn ich dann unterhalb der kürzesten Interruptfrequenz (eigentlich unterhalb der kürzesten ISR-pause) bin, habe ich beste Chancen, dass das Programm sich nicht aufhängt. Wenn die gesamt mögliche Laufzeit aller ISR zu lang ist, konnte schon mal ein nested Interrupt einer (längeren) ISR helfen.

hegewald
12.02.2015, 09:51
Hallo Leute,
mir raucht der Kopf! Hab ein kleines Programm aus dem Buch von Günter Schmitt
im Editor von Atmel Studio4 geschrieben.
Das Projekt "mega8test" im Studio 4 angelegt, aber noch nicht zum laufen gebracht.
Der Programmer AVR ISP mkII steht mir zur Verfügung.


// Projekt: mega8test 11.02.2015

// Datei: mega8test02.c

// PORTB Output PB7...PB0 = 8x LED
// PORTC Output PC5...PC0 = 6x LED
// PORTD Input PD7...PD0 = 8x Schalter

// Konfiguration: interner Oszillator 1MHz, ext. Reset-Signal

#include <avr/io.h>
#define Takt 1000000 // Systemtakt 1 MHz intern
void main (void) // Hauptfunktion, was ist das?

{ // Anfang der Hauptfunktion

DDRB = 0xFF; // PORTB = Output (Warum ; ?)
DDRC = 0xFF; // PORTC = Output

// Testschleife PC0 gemessen 70,7 KHz

while (1) // unendliche Schleife

{ // Anfang des Schleifenblocks

PORTB = PIND; // Eingabe PORTD nach Ausgabe PORTB

PORTC++; // Dualzähler auf PORTC um 1 erhöhen

} // Ende der while-Schleife
} // Ende der Hauptfuktion main

Frage hierzu:
// muß ich doch vor einem Kommentar setzen.

Aber was ist das denn..//#include <lcd_162_mini-no-wait.c> auch ein Kommentar?

Oder while (1) unendliche Schleife?? Und die (1)

Ich muß mir erst mal einige kurze einfache Programme anschaun, um die vielen Zeichen kennen zulernen.

Grüße

Rolf

oberallgeier
12.02.2015, 10:49
Hallo Rolf!


... mir raucht der Kopf! ...
// muß ich doch vor einem Kommentar setzen.
Aber was ist das denn..//#include <lcd_162_mini-no-wait.c> auch ein Kommentar?
Rauchen ist beim Kopf zulässig, beim IC bedeutet es meist nix Gutes.

Doppel-Schrägstrich beginnt einen Kommentar bis zum Zeilenende - auch wenns im Prinzip Code ist.
/* (Schrägstrich Stern) beginnt einen Kommentar - der kann mehrzeilig sein und wird mit */ beendet.

A) Bitte schreibe das nächste Mal Deinen Code ins Codefenster. Das bekommst Du im Editor mit dem Button [#] - wenn Du den nicht siehst, dann drücke bitte auf "Erweiterte Ansicht". Im Editor sieht das dann so aus: [.CODE][./CODE] . Im Editor steht aber kein Leerzeichen nach der ersten Klammer. Und das Fenster ist dann erstmal leer. Nun die Schreibweise mit "nix" zwischen [ und C bzw. [ und /:


.Dieses Beispiel ist tricky, funktioniert "normalerweise" nicht *gggg*.

B) Schau mal nach meinem Posting vom 09.02.2015, 14:34, bei "main Modul".
Bei Dir könnte das etwa so aussehen:


// Jetzt fängt der Code an mit Einschluss von Bibliotheken und
// Definitionen
#include <avr/io.h>
#include <util/delay.h> // Hier ist eine "Wartefunktion" enthalten
#define Takt 1000000 // Systemtakt 1 MHz intern

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void main (void) // Hauptfunktion, was ist das?
// Das ist das eigentliche Hauptprogramm,
// die Unterprogramme müssen vorher schon
// geschrieben sein oder includierte werden
// siehe dazu z.B. die o.g. Bibliotheken io.h etc
// - - - - - - - - - - - - - - - -
// Nun werden mal die Ports konfiguriert
// Ports+Pins als Ein- (0) od. Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
// - - - - - - - - - - - - - - - -
DDRA = 0b00000000; // Alle Pins auf Eingang
PORTA = 0b11100101; // Pinn 0, 2 sowie fünf bis sieben mit Pullup
//
DDRB = 0b11111111; // Alle Pins auf Ausgang
PORTB = 0b00001111; // Pinn 0-3 high => LEDs an, 4-7 auf low => LEDs aus
//
DDRC = 0b00111111; // Pinn 0-5 auf Ausgang, 2 Eingänge
PORTC = 0b11000000; // Ausgänge 0-4 auf low, 5 auf high, PullUp für 6+7
//
DDRD = 0b00000000; // Alles Eingänge
PORTD = 0b00001111; // Pullups einschalten (Schalter schaltet gegen GND)
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Wir bewundern mal die LEDs - an oder aus
_delay_ms( 1000); // ... ne ganze Sekunde
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
for ( uint8_t i=0; i< 100; i++) // LEDs 100 mal blinken lassen
{ // Schleifenanfang
// - - - - - - - - - - - -
PORTB |= (1<<PB6}; // LED auf PB6 einschalten
PORTB &= ~(1<<PB1); // LED auf PB1 ausschalten
_delay_ms( 500); // Nun warten wir ne halbe Sekunde (LED bewundern)

PORTB &= ~(1<<PB6}; // LED auf PB6 ausschalten
PORTB |= (1<<PB1); // LED auf PB1 einschalten
_delay_ms( 500); // Nun warten wir ne halbe Sekunde (LED bewundern)
} // Ende von for ( uint8_t i=0; i< 100; i++)

// - - - - - - - - - - - -
return 0; // Ende des Programms
/* und zum Schluss noch ein mehrzeiliger Kommentar:
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse ...
*/

Wenn ich ausreichend gefrühstückt habe müsstesollte das funktionieren. Ohne Tastendruck und nur hundert Blinkies.

hegewald
12.02.2015, 18:36
Hallo Oberallgeier,
meinen Dank für Deinen zurecht gerückten Code.
Hab ihn ins Studio4 rüber kopiert und ausgedruckt. Das muß ich jetzt erst mal verarbeiten.
Die vielen Zeichen die hier ihre Bedeutung haben, gab es natürlich in Assembler nicht.
Auch z.B. DDRB = 0b00000000 wurden mit 0xFF erledigt...oder geht das in C nicht?
Klar waren hier 2 Zeilen notwendig...wie
ldi akku,0xFF ;alle Bits in r16 = 1
out DDRB,Akku ;Datenrichtung = Output

Aber ich habs mir nun vorgenommen und muß da durch.

Das Wetter ist im Norden besch....

Viele Grüße

Rolf

- - - Aktualisiert - - -

Sorry, wollte nur sehen, ob ich das hinbekomme!


DDRA = 0b00000000; // Alle Pins auf Eingang
PORTA = 0b11100101; // Pinn 0, 2 sowie fünf bis sieben mit Pullup
//
DDRB = 0b11111111; // Alle Pins auf Ausgang
PORTB = 0b00001111; // Pinn 0-3 high => LEDs an, 4-7 auf low => LEDs aus
//
DDRC = 0b00111111; // Pinn 0-5 auf Ausgang, 2 Eingänge

oberallgeier
12.02.2015, 19:13
... Die vielen Zeichen ... gab es natürlich in Assembler nicht.
Auch z.B. DDRB = 0b00000000 wurden mit 0xFF erledigt...oder geht das in C nicht?Hallo Rolf, natürlich gabs in Assembler nicht die vielen kryptischen Zeichen. Dem Assembler wird auch nicht nachgesagt dass er von seinen Autoren im reichlich eingetrübten Zustand (auf Deutsch heisst das "Suff") erstellt worden wäre. Manche sagen das den Jungs Kernighan & Ritchie aber nach . . .

Ok, man kann in C natürlich statt
DDRB = 0b00000000; auch
DDRB = 0xFF;
schreiben - also in hex. Es geht aber auch einfach
DDRB = 255;
eben dezimal. Und wenn Du Deinen Code weniger leserlich willst, dann schreibste
DDRB = 0377;
also oktal *ggg* - erkennbar an der führenden Null. Und wenns noch hyroglyphischer werden soll, ginge (mal zur Abwechslung - und wegen ASCII -) für die Ziffer 116 dezimal auch ein
DDRB = 't';
also das ASCII-Zeichen. MEINE Vorliebe ist >>bei Portdefinitionen<< die binäre Darstellung "DDRC = 0b00111111;" - erkennbar an dem Vorspann "0b"- da sehe ich nämlich sofort, welche Pinne Eingang und welche Ausgang sind - das ist bei der gleichWERTigen Darstellung 0x3F für meine Augen nicht der Fall. Wenn ich dagegen, z.B. beim Empfang eines UART-Befehls (ähnlich EIA232) einen bestimmten ASCII-Wert abfrage, dann schreibe ich z.B. if ( eingabe == 't' ) ... - das liest sich eben besser als if ( eingabe == 116 ) ... Wie gesagt, irgendwann waren irgendwo bei C vermutlichvielleicht doch ein paar fl.oz.-chen Alk im Spiel, oder gar ein Gallönchen.

Bravo zum Codefenstertest!




Wetter . . . heute lag ich nach dem mittäglichen Kaffee mehr als eine Stunde auf meiner Südterrasse. Im Schatten rund 0°C, im Sonnenschein auf der Terrasse bei blauem Himmel . . . wars einfach warm - weil dazu auch windstill.

Klebwax
12.02.2015, 22:08
C sollte man eigentlich anhand eines Buches oder eines der verfügbaren Tutorials auf einem PC lernen. Da liefert einem der Rechner alles, was man braucht: die Tastatur als Input, den Bildschirm als Output sowie Tools, wie einen Debugger, ohne Ende. Unter Linux sind die erforderlichen Programme sowieso frei und unter Windows gibt es Visual Studio Express ebenfalls kostenlos. Da gibt es dann online Syntax-Checks, Single Step, die komplette Sicht auf alle Variablen und eine Menge andere Hilfe. Wenn man dann mit der Sprache einigermaßen klar kommt, kann man auf (irgend)einen µC umsteigen.

Und man sollte garnicht erst versuchen, die Sichtweise des Assenblerprogrammierers auf den Rechner in C nachzuvollziehen. Und sich von Prozessorregistern, Carryflag oder Stackpointer zu lösen, gelingt einem leichter auf einem PC. Danach spielt es dann auch keine Rolle mehr, ob man für AVR, PIC, ARM oder X86 programmiert.


Hallo Rolf, natürlich gabs in Assembler nicht die vielen kryptischen Zeichen
Aber selbstverständlich gibt es die, eher noch mehr. Und natürlich kann jeder Assembler Zahlen in jeder nur denkbaren Schreibweise verarbeiten, von binär bis oktal und natürlich auch als ASCII Zeichen. Dafür schleppt er aber das alte Fortran-Lochkartenformat mit sich rum, und es hat ziemlich lange gedauert, bis Labels mit mehr als 8 Zeichen zulässig waren. Und moderne Assembler benutzen sogar den C-Präprozessor weils einfach praktisch ist.

MfG Klebwax

hegewald
13.02.2015, 09:51
danke für Eure Antworten!

Mit meinen AVR Studio4 aus dem Jahre 2011 werde ich nichts. Hatte erst mal versucht das Fenster zu öffnen,
um ein neues Projekt zu installieren. Umgestellt von Assembler auf Cxxx...Projektname eingegeben,
den Mega8 ausgesucht und ok. Dann den Code von Oberallgeier im Editor und nochmal abgespeichert.
Jetzt wie gewohnt auf "BUILD" aber es tut sich wie sonst gewohnt (kurz laufender Balken) gar nichts.
Google sagt mir, ich müsse bei Studio4 vorab das WINAVR installieren.
Ich habe das Studio4 noch nicht runter geschmissen.

Oder gleich das Studio5 nehmen?

Grüße

Rolf

oberallgeier
13.02.2015, 11:44
... Mit meinen AVR Studio4 aus dem Jahre 2011 werde ich nichts ... ich müsse bei Studio4 vorab das WINAVR installieren ... gleich das Studio5 ...Hallo Rolf.

Wie weiter oben geschrieben, war MIR bei den Versionen 5 und - wohl besser - 6 zuviel Overhead. Für meine Arbeiten reicht allemal das 4er und für mich ist dies ein typischer Fall wo weniger (Overhead) gleich mehr (einfacher, übersichtlicher, schneller) ist. Andererseits nutzen andere selbst für kleinere Projekte die 6er Version, die gleich den Compiler mitbringt.

Ich habe auf meinem aktuellen Rechner, Win7pro64 zuerst den Compiler installiert - WinAVR-20100110 - wenn ich mich recht entsinne. Danach das AVRStudio4. Von der letzten Installation auf WinXP hatte ich diese ?notwendige? Reihenfolge - erst Compiler, dann Studio4 - noch im Kopf.

Danach ging alles "ganz normal". Wenn Du magst dann versuchs mal so. Zuerst Dein AVRStudio löschen (Systemsteuerung, Programme löschen), Neustart, WinAVR-20100110 holen

http://sourceforge.net/projects/winavr/files/

dazu dann gleich das Studio 4; hier gibts direkte Links zu den verschiedenen Versionen, neuen und alten:
http://www.mikrocontroller.net/articles/Atmel_Studio#Direktlinks_Installer
Wenn ich Dich richtig verstehe, liegt bei Dir der Installationsfile dafür aber schon irgendwo auf Deinem Rechner. Bei der Version 4-18 gibts wohl mehrere Servicepacks, die sind im 4-19 vermutlich schon drin.

Nun zuerst den Compiler installieren (WinAVR-20100110-install.exe). Ich mach das wohl (immer? notwendig?) mit dem Trick mit der "Rechte Maustaste" und "Als Administrator ausführen".

Danach das Studio 4 installieren - gleiche Tricks wie oben.

Danach sollte "es" eigentlich laufen . . . (ohne Gewähr, ohne Haftung wofür auch immer ...)