Dynamiska variabler Arduino

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
FormerMazda
Inlägg: 6076
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Dynamiska variabler Arduino

Inlägg av FormerMazda »

Aha, ja men det i detta fallet kommer vara 6 rör och inget annat.
Men jag håller med om funktionen bakom det. Trodde det fanns nåt annat.
Användarvisningsbild
hawkan
Inlägg: 2621
Blev medlem: 14 augusti 2011, 10:27:40

Re: Dynamiska variabler Arduino

Inlägg av hawkan »

Kod: Markera allt

for (int i = 0; i < sizeof(pinEnN); i++) {
så behöver du inte tänka på hur många det är. Och deklarera såhär

Kod: Markera allt

int pinEnN[] = {53, 51, 49, 47, 45, 43};
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Dynamiska variabler Arduino

Inlägg av Mr Andersson »

arvidb skrev: 6 augusti 2020, 20:40:14Jo visst är C bristfälligt på det sättet, men vettiga kompilatorer klagar i alla fall om du skriver in fler element än det finns plats för i deklarationen
Jo det stämmer. Men du får ingen varning om du skriver in för få element. De blir satta till 0 istället.

@hawkan:
Det där är ännu värre. sizeof(int) är 2 på AVR. Loopen kommer att gå 12 varv.
Använd i så fall sizeof(pinEnN)/sizeof(*pinEnN) men det ser ut som kod från 1989.
Arduino-IDE:t använder g++, inte gcc. Så varför inte använda range-based for?
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Dynamiska variabler Arduino

Inlägg av arvidb »

Jag brukar ibland göra såhär:

Kod: Markera allt

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x)))

Kod: Markera allt

int pinEnN[] = {53, 51, 49, 47, 45, 43};

Kod: Markera allt

for (int i = 0; i < ARRAY_SIZE(pinEnN); i++) {
... men ärligt talat försöker jag undvika C så mycket det går nuförtiden och använda Rust istället. :)
ToPNoTCH
Inlägg: 4883
Blev medlem: 21 december 2009, 17:59:48

Re: Dynamiska variabler Arduino

Inlägg av ToPNoTCH »

Nuförtiden så är det inte självklart men jag antar att du med "Arduinon" menar en Atmel processor.
Sen fattar jag heller inte om språket du knappar i är C eller Arduino.

Oavsett så kan du ju skriva till portar istället för pinnar.
Någon skrev att det inte gick att få färre rader i C vilket absolut borde gå.
Det är väl i det närmaste så det funkar i de flesta MCU arkitekturerna när man sätter en pinne (man skriver hela porten och maskar de pinnar man ej vill ändra).

I Arduino språk borde det funka genom att sätta porten med assembler
asm volatile ("
; your assembly code here
");


Om pinnarna är spridda över flera portar så blir det tyvärr en rad per port oundvikligen.

Själv hade jag inte brytt mig ett skit. Om man tycker 6 rader extra krånglar till koden så bör man fokusera mer på kommentarer i koden.
Själva exekveringen blir ju inte bättre av en array och for loop, om det är det som är hjärnspöket.
peolah
EF Sponsor
Inlägg: 502
Blev medlem: 22 mars 2010, 02:10:47

Re: Dynamiska variabler Arduino

Inlägg av peolah »

Att blanda in assembler är ingen bra idé i sådana fall. Just att skriva till portar är väldigt speciellt, jag sätter en slant på att TS använder en Mega2560 !
Och pin-numren omfattar då PORTB,PORTG, PORTL. Berorende på IO-addressen på portarna används olika instruktioner för IO-Access. Och två av portarna jag nämer är under 0x1F och den ena över 0x100.

Jag skriver allt i assembler till AVR och har nästan alltid gjort, det ger 100 ggr mer plats och är så snabbt som jag behöver kod att vara.
Och jag känner mig inte alls begränsad av assembler mot C/C++ som jag även använder till mer avancerade processorer som ARM mfl.
, jag bifogar två macros för setbit, clrbit på portar jag gjort vilket är en del av ett stort bibliotek av macros jag gjort under åren.

Mnemonicsen som används vid olika IO i portar är alltså sts/lds , out/in eller optimalt sbi/cbi. Med optimalt menar jag snabbaste (cykeltid).

Kanske lite överkurs, men bara så ni inser problemet. PORTA och PORTG har IO-Address under 0x01F och kan använda sbi/cbi medan den andra måste använda sts/lds.
Finns alltså även ett tredje alternativ. Detta är bara till för att optimera koden, man kan så klart alltid använda lds/sts med då måste 0x20 adderas på IO-Addresser under 0x40,
vilket man gör att man måste veta vilken port och vilken bit en "Aduino-Pinne" är, tex P49 - vilket är Port L bit 0 - vilken man måste använda lds/sts för att ändra IO.
Allt sådant finns i headerfiler såklart som kompilatorn använder, och det är inte omöjligt något gjort ett projekt för detta med flerrads-inline assembler till C koden.
Vilken inte är speciellt lätt att göra, men behövs bara göras en gång!

Edit : Förtydlingande Memory Mappade IO adresser > 0x40

Kod: Markera allt

.macro setbit
	.if @0>0x3F
		#if defined __save_temp__
			push __temp__
		#endif
		lds __temp__, @0
		ori __temp__, (1<<@1)
		sts @0, __temp__
		#if defined __save_temp__
			pop __temp__
		#endif
	.endif
	.if (@0<0x40) && (@0>0x1F)
		#if defined __save_temp__
			push __temp__
		#endif
		in   __temp__, @0
		ori  __temp__, (1<<@1)
		out  @0, __temp__
		#if defined __save_temp__
			pop __temp__
		#endif
	.endif
	.if @0<0x20
		sbi  @0, @1
	.endif
.endm

.macro clrbit
	.if @0>0x03F
		#if defined __save_temp__
			push __temp__
		#endif
		lds  __temp__, @0
		andi __temp__, ~(1<<@1)
		sts @0, __temp__
		#if defined __save_temp__
			pop __temp__
		#endif
	.endif
	.if (@0<0x40) && (@0>0x1F)
		#if defined __save_temp__
			push __temp__
		#endif
		in   __temp__, @0
		andi __temp__, ~(1<<@1)
		out  @0, __temp__
		#if defined __save_temp__
			pop __temp__
		#endif
	.endif
	.if @0<0x020
		cbi  @0, @1
	.endif
.endm
Skriv svar