Pratar Assembler. Vill lära mig nytt språk..

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
adent
Inlägg: 4232
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av adent »

Ett vanligt sätt att bygga upp kod för micro-kontrollers är i form av ett litet leksaks-OS t.ex. så här:

Kod: Markera allt

INTERRUPT PortAPin3()
{
    Gör nått tidskritiskt, sätt en lämplig flagga.  
}

INTERRUPT Timer1OverFlow()
{
    Gör nått tidskritiskt, sätt en lämplig flagga.  
}

main()
{
  while(1)
  {
       Hantera otidskritiska saker apropå att Timerflagga satt
       Hantera otidskritiska saker apropå att Pinflagga satt 
  }
}
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

Ok testade att göra såhär

Kod: Markera allt



#include <xc.h>
#include <stdint.h>


#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FOSC = INTRCIO, FCMEN = OFF, MCLRE = OFF, WDTE = OFF, CP = OFF, PWRTE = OFF

#define	_XTAL_FREQ	8000000
#define	LED PORTAbits.RA2
#define	RX	PORTCbits.RC0
	uint16_t	count_100us;
void main()
{
	uint8_t		count;
	uint24_t	adress;



	PORTA = 0;
	TRISA =	0b00000000;
	PORTB = 0;
	TRISB = 0b00000000;
	PORTC = 0;
	TRISC =	0b00000001;

	ANSEL = 0;
	ANSELH = 0;
	ADCON0 = 0;
	ADCON0 = 0;

	OSCCON = 0b01110001;

	OPTION_REG = 0b00001000;
	T2CON = 0;

	INTCON = 0b10100000;
	TMR0 =88;

	for	(;;)
	{
		//Vänta på att RX = 0 i 7mS
		for (count_100us = 0; count_100us <= 7000/100;)
		{
			if (RX == 1)
			count_100us = 0;
		}
		//läs av in signaler spara i adress
		adress = 0;
		for (count = 0; count < 24;	count++)
		{
			adress = adress << 1 ;
			while (RX == 1)
			{
				;
			}
			while (RX == 0)
			{
				;
			}
			for (count_100us = 0; count_100us <= 7;)
			{
				;
			}
			adress = adress ^ RX;
		}
			//Gämför adress med nyckel
			if (adress == 0x405015 || adress == 0x400415 || adress == 0x000015)
			LED = 1;
			if (adress == 0x405014 || adress == 0x400414 || adress == 0x000014)
			LED = 0;		
	}	
}		
void interrupt tc_int(void)
{
	if (T0IE || T0IF)
	{
	T0IF=0;
	++count_100us;
	TMR0 =88;
	return;
	}
 // process other interrupt sources here, if required
}

Men det kändes mer stökigt och tar dessutom mer plats än innan..

men jag gör säkert inte som ni hade tänkt endå :humm:
Användarvisningsbild
Krille Krokodil
Inlägg: 4062
Blev medlem: 9 december 2005, 22:33:11
Ort: Helsingborg

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Krille Krokodil »

Tillståndsmaskin är sätt att lösa det på. Man gör en tabell på hur länge varje tillstånd ska vara och sedan en funktion i avbrottsrutinen som räknar ner och stegar tillstånden. I main har man:

Kod: Markera allt

switch(state){
   case 1: 
      // Vad som ska ske i tillstånd 1
   break;
   case 2:
      // Vad som ska ske i tillstånd 2
   break;
   osv...
}
Edit: Du behöver inte sluta programmera assembler nu för att du har börjat med C, man kan blanda, sk inline assembly, för AVR fungerar det ut såhär: http://www.nongnu.org/avr-libc/user-man ... e_asm.html
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

EDIT: dubblett
Senast redigerad av kvaark 10 mars 2013, 07:59:24, redigerad totalt 1 gång.
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

någon som har bra dokumentation eller vill förklara hur man använder rutiner

kommer att behöva anropa detta flera gånger i min kod

Kod: Markera allt

	tusental = (adc / 1000) + '0';
	adc = adc - (1000*(tusental - '0'));
	hundratal = (adc / 100) + '0';
	adc = adc - (100*(hundratal - '0'));
	tiotal = (adc / 10) + '0';
	adc = adc - (10*(tiotal - '0'));
	ental = adc + '0';
det är hur jag löste att omvandla 10 bitars adc till ascii tal att sända via uart

men jag vill kunna anropa funktionen för att inte behöva skriva detta varje gång jag utför det i koden

i asm hade jag bara skrivit

Kod: Markera allt

call  RUTIN

RUTIN
;rutinen
return
Användarvisningsbild
Walle
Moderator
Inlägg: 7701
Blev medlem: 14 december 2004, 10:32:18
Ort: Stockholm

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Walle »

I C skriver du typ:

Kod: Markera allt

int BitToASCII(int x)
{
    gör saker här;
    return x;
}

Notera att den första datatypsdeklarationen talar om vilken datatyp funktionen returnerar. Inom parentesen är det vilken datatyp som är argument.
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Icecap »

Det ser ut som att du vill omvandla ett värde till siffror (text) och då väljer du en besvärlig väg, iaf. att läsa.

Nu beror det lite på hur du ska använda resultatet men EN lösning är att sända varje tecken eftersom med högsta värdet först:

ADC_Value är ingångsvärdet.
Send_Byte() är rutinen för att sända en byte.

Kod: Markera allt

void Send_Value(unsigned int Value)
  {
  unsigned char X[5]; // Max. 5 char's
  x[4] = (Value % 10) + '0';
  Value /= 10;
  x[3] = (Value % 10) + '0';
  Value /= 10;
  x[2] = (Value % 10) + '0';
  Value /= 10;
  x[1] = (Value % 10) + '0';
  Value /= 10; // Behövs för 10.000 siffran
  x[0] = (Value % 10) + '0'; // Behövs för 10.000 siffran
  Send_Byte(X[0]); // Behövs för 10.000 siffran
  Send_Byte(X[1]); // Skickar 1.000 siffran
  Send_Byte(X[2]); // Skickar 100 siffran
  Send_Byte(X[3]); // Skickar 10 siffran
  Send_Byte(X[4]); // Skickar 1 siffran
  }
När du sedan ska sända ett värde skriver du bara:
Send_Value(ADC_Value);
och värdet blir omvandlat till text och sänd via Send_Byte()-rutinen.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Wedge »

Icecap, modulo och division är fruktansvärt "dyra" operatorer även på processorer med inbyggda instruktioner för sånt. Jag skulle tippa på att TS kod är ganska mycket snabbare.

Läsbarheten vinner du i alla fall, men inte med några hästlängder. :)
TS kod lägger till och drar ifrån "0" lite för ofta. Den kunde bli aningen mer effektiv om presentationsdata skiljs från beräkningsdata.
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Icecap »

Wedge: jag brukar lösa detta på ett ganska annat sätt. Sedan är modulo inte mer krävande än en vanlig division.

kvaark's sätt är ganska krävande med multiplikationer och divisioner också så jag tror att det går ung. jämt ut.

Men jag håller med om att det går att lösa snyggare och snabbare, men utifrån den ganska svaga beskrivning som finns är det svårt att komma närmre.

Sedan var det själva funktionsanropet som var det viktiga och jag är osäker på om kvaark fick nog på benet med det.
sodjan
EF Sponsor
Inlägg: 43231
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av sodjan »

> någon som har bra dokumentation eller vill förklara hur man använder rutiner

Nu är jag inte riktigt med här.
Varför inte använda de länkar och andra tips som du redan har fått?

T.ex "2.3 Funktioner"p å sidan 21 i
http://www.it.uu.se/edu/course/homepage ... C-kurs.pdf
som det länkades till redan i ett av de första svaren. Vad jag kan se så
är det rellativt vettigt skrivet.
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

Tack grabbar...
Mycket bra hjälp här.

Jag kom på att programmet jag kommunicerar med även kan tolka hex värden skrivna i ascii, alltså för 0x3F så skickar man '3' och 'F', och det tyckte jag borde vara både snabbare och mindre resurskrävande att omvandla till ..

Kod: Markera allt

void send (uint16_t value)
{
	uint8_t X[4];

	const uint8_t patHex [16] =
	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

	X[0] = patHex [value & 0x0F];
	X[1] = patHex [((value >> 4) & 0x0F)];
	X[2] = patHex [((value >> 8) & 0x0F)];
	X[3] = patHex [((value >> 12) & 0x0F)];

	while(!TXIF);
	TXREG = X[3];
	while(!TXIF);
	TXREG = X[2];
	while(!TXIF);
	TXREG = X[1];
	while(!TXIF);
	TXREG = X[0];
}
Detta va vad jag kom fram till då..

Ps: Dessutom så behöver jag bara skicka 4 bytes för ett 16bitars tal istället för 5bytes..
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

Hur gör jag för att kolla om en specifik bit i ett register är lika med 0?

det jag försöker göra är en IF där jag testar om en bit i ett register är lika med 0 men jag lyckas inte
Användarvisningsbild
Walle
Moderator
Inlägg: 7701
Blev medlem: 14 december 2004, 10:32:18
Ort: Stockholm

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av Walle »

Vad har du försökt?

Nåt i stil med:

If (!register.bit)

eller

If (register.bit == 0)

borde funka.

Edit: jag minns inte säkert om man kan köra typ "register.bit", men annars har ju nästan alla bitar inregistrens ett eget "namn", t.ex. "ADCON0" som är en kontrollbit för ADCn i 12F-familjen. Normalt används namnen som står i databladet i programmeringsmiljön.
kvaark
Inlägg: 256
Blev medlem: 1 september 2010, 22:19:39

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av kvaark »

Ok då förklarade jag lite fel

För det jag menar är ett eget 8bitars variabelt tal

Men det kanske är samma där?

If (tal.8 == 0)
ElectricNooB
Inlägg: 600
Blev medlem: 26 juli 2011, 20:58:06

Re: Pratar Assembler. Vill lära mig nytt språk..

Inlägg av ElectricNooB »

Jag skulle göra såhär: if((talet&bitten)==0)

Ex: För att kolla bit nr 3 så skall bitten ha värdet 8 i decimal eller 00001000 i binär form.
Skriv svar