Skriva ut en byte på valfri pinne?
Skriva ut en byte på valfri pinne?
Hur gör man för att skriva ut en byte på en pinne? Använder AVR och GCC...
tex.
Jag vill skriva ut 0x51 (10001010 binärt),
det är ju lite omständigt att köra:
sbi(PORTD, PD0);
cbi(PORTD, PD0);
cbi(PORTD, PD0);
cbi(PORTD, PD0);
sbi(PORTD, PD0);
cbi(PORTD, PD0);
sbi(PORTD, PD0);
cbi(PORTD, PD0);
Hur gör man en snygg slinga som plockar rätt bit och sätter pinnen till 1 eller 0?
tex.
Jag vill skriva ut 0x51 (10001010 binärt),
det är ju lite omständigt att köra:
sbi(PORTD, PD0);
cbi(PORTD, PD0);
cbi(PORTD, PD0);
cbi(PORTD, PD0);
sbi(PORTD, PD0);
cbi(PORTD, PD0);
sbi(PORTD, PD0);
cbi(PORTD, PD0);
Hur gör man en snygg slinga som plockar rätt bit och sätter pinnen till 1 eller 0?
Om man kör en cyklus om 8 steg:
Blandning av C och Assembler?
Kod: Markera allt
for(Räknare = 0;Räknare < 8;Räknare++)
{ // Utföras 8 gg.
if(Data & 0x80) sbi(PORTD, PD0); // Om MSB är satt settas porten
else cbi(PORTD, PD0); // Annars cleares den
Data <<= 1; // Betyder skifta 'Data' till vänster 1 steg
}
Kod: Markera allt
char tmp = 0x51;
int i;
for(i=0;i<8;i++)
{
if(tmp&0x80) sbi(PORTD,PD0);
else cbi(PORTD,PD0);
tmp<<=1;
}
edit: ja idag var man ju snabb...
Vad jag minns så används inte cbi och sbi längre i gcc, utan man får skriva i ANSI-C(?) instället (sbi och cbi är "depricated").
Eller lägga till tex:
Eller lägga till tex:
Kod: Markera allt
#define cbi(port, bitnum) port &= ~(1 << bitnum)
#define sbi(port, bitnum) port |= (1 << bitnum)Tack! Om man vill göra det motsatta, dvs läsa in 8 bitar till en byte. Vad använder man då?Icecap skrev:Om man kör en cyklus om 8 steg:Blandning av C och Assembler?Kod: Markera allt
for(Räknare = 0;Räknare < 8;Räknare++) { // Utföras 8 gg. if(Data & 0x80) sbi(PORTD, PD0); // Om MSB är satt settas porten else cbi(PORTD, PD0); // Annars cleares den Data <<= 1; // Betyder skifta 'Data' till vänster 1 steg }
I båda fallen (in och ut) måste det läggas till en klocka!
För varje hög (eller låg) flank på klockan så läser man värdet på data-in-pinnen och skiftar in det i en byte. Typ såhär, åsså får man se till att göra det åtta gånger bara:
Sånna här bit-skift in och ut går att göra mycket effektivare i asm genom att använda carry-biten. HAr tyvärr inget exempel såhär på kvällskvisten.. läggdags nu.. 
För varje hög (eller låg) flank på klockan så läser man värdet på data-in-pinnen och skiftar in det i en byte. Typ såhär, åsså får man se till att göra det åtta gånger bara:
Kod: Markera allt
if(PIND & PD0)
Data |= 0x01;
Data <<= 1;
Man kan göra det utan några extra klocka (asynkront), en vanlig serieport är ju exempel på det. Fast om man gör det måste förstås både sändare och mottagare vara överens om exakt hur snabbt data skickas och man måste ha någon metod för att återsynka då och då (t.ex. startbit/stopbit som på serieporten).
Hej!
Detta är en kod som fungerar när man ska skriva en byte på en pinne.
Den var för en LCD styrning med ett 8bitars parallelt shiftregister.
//Emil
Detta är en kod som fungerar när man ska skriva en byte på en pinne.
Kod: Markera allt
void send_data(uint8_t mybyte)
{
for(int i = 0; i < 8; i++)
{
if (mybyte & 0x80)
LCD_PORT |= (1<<LCD_DATA_PIN);
else
LCD_PORT &= ~(1<<LCD_DATA_PIN);
mybyte <<= 1;
}
}//Emil
Håller på att kommunicera med en temperatur sensor. Så SPI/UART känns lite overkill, eller? Vad är standard sättet för att kommunicera med dylika externa enheter? Jag klockar ju bara ut bitarna en efter en, finns det nåt bättre sätt?
Hur är det med dessa timing kraven som finns i databladen? Måste man leva i en perfekt värld för att uppnå dem? Jag har lött på virkablar på den ytmonterade kretsen som sedan sitter i en labbplatta. Detta borde väl inte vara bra alls, men att gå från de specade ~100ns till att vara tvungen att lägga in delays på 40us känns lite väl hårt, eller?
Dessutom ger sensorn ett värde som är 4 grader celsius för högt, vad beror detta på? Enligt databladet ska den vara bra mycket bättre än så...
Datablad för DS1626:
http://pdfserv.maxim-ic.com/en/ds/DS1626-DS1726.pdf
Kod:
wait() ger ett avbrott på ca 40us...
Ska man ha något annat upplägg på koden? Det blir ju en del kod...
Edit: Kod uppdaterad, hastighetsproblem löst...
Hur är det med dessa timing kraven som finns i databladen? Måste man leva i en perfekt värld för att uppnå dem? Jag har lött på virkablar på den ytmonterade kretsen som sedan sitter i en labbplatta. Detta borde väl inte vara bra alls, men att gå från de specade ~100ns till att vara tvungen att lägga in delays på 40us känns lite väl hårt, eller?
Dessutom ger sensorn ett värde som är 4 grader celsius för högt, vad beror detta på? Enligt databladet ska den vara bra mycket bättre än så...
Datablad för DS1626:
http://pdfserv.maxim-ic.com/en/ds/DS1626-DS1726.pdf
Kod:
Kod: Markera allt
#define F_CPU 1000000
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define TEMP PORTD
#define RST PD0
#define CLK PD1
#define DQ PD2
#include <avr/io.h>
#include <util/delay.h>
int i, data;
void wait()
{
sbi(PORTA, PA0);
sbi(PORTA, PA0);
sbi(PORTA, PA0);
sbi(PORTA, PA0);
sbi(PORTA, PA0);
}
void read_temp(void)
{
// start temperature conversion, send 0x51 LSb first...
DDRD = 0xFF; // DQ pin as output
data = 0x51;
sbi(TEMP, RST); // RST high
for(i = 0; i < 8; i++)
{
cbi(TEMP, CLK); // clock low
if(data & 0x01)
sbi(TEMP, DQ);
else
cbi(TEMP, DQ);
data >>= 1; // shift data right
sbi(TEMP, CLK); // clock high
}
cbi(TEMP, RST); // RST low
// wait 800ms for temperature conversion to complete
for(i = 0; i < 4; i++)
_delay_ms(200);
// read temperature
// send 0xAA LSb first...
data = 0xAA;
sbi(TEMP, RST); // RST high
for(i = 0; i < 8; i++)
{
cbi(TEMP, CLK); // clock low
if(data & 0x01)
sbi(TEMP, DQ);
else
cbi(TEMP, DQ);
data >>= 1; // shift data right
sbi(TEMP, CLK); // clock high
}
// ...then read temperature register
DDRD = 0xFB; // DQ pin as input
for(i = 0; i < 12; i++)
{
data >>= 1; // shift data right
cbi(TEMP, CLK); // clock low
if(PIND & (1 << DQ))
data |= 0x80;
sbi(TEMP, CLK); // clock high
}
cbi(TEMP, RST); // RST low
}
int main(void)
{
DDRA = 0xFF; // PORTA output
while(1)
{
read_temp();
PORTA = data;
}
}
Ska man ha något annat upplägg på koden? Det blir ju en del kod...
Edit: Kod uppdaterad, hastighetsproblem löst...
Senast redigerad av FS 30 juli 2006, 00:27:51, redigerad totalt 2 gånger.
Egentligen borde jag inte behöva några delayer alls då kretsen går i 1MHz...
Om jag kör tex:
Får jag en periodtid på ca 10us (uppmätt med oscilloskop). Så varför behöver jag delayer öht? Är det pga. den kassa uppkopplingen med virtråd och labbplatta?
Edit: Hmm var tog björn:s inlägg som jag svarade på vägen?
Om jag kör tex:
Kod: Markera allt
while(1)
{
cbi(PORTA, PA0);
sbi(PORTA, PA0);
}
Edit: Hmm var tog björn:s inlägg som jag svarade på vägen?
Trevlig tråd och ett bra exempel på en fullständigt felaktigt ställd första fråga.
Istället för "Hur gör man för att skriva ut en byte på en pinne?" skulle det
naturligtsvis ha varit "Hur kommunicaerar jag enklast/bäst med en DS1626 ?"
Och så en länk till databladet i *FÖRSTA* inlägget !
Då hade alla svar antagligen sett annorlunda ut.
Det framgår t.ex inte förrens ganska sent att du faktiskt även
*har* en CLK-linje.
> Så SPI/UART känns lite overkill, eller?
> Vad är standard sättet för att kommunicera med dylika externa enheter?
SPI kanske ? Varför är det "overkill" ? Du tycker ju själv att det "Det blir ju en del kod...".
Jo visst, det är därför man bygger in olika hårdvaruenheter för kommunikation.
Men å andra sidan, inte är det där speciellt mycket kod för att bitbanga en seriell temp sensor !
Jag tror att, om man inte vill köra hårdvaru-SPI, så är det nog enklare
att skriva en ASM rutin och anropa från C-koden...
> Dessutom ger sensorn ett värde som är 4 grader celsius för högt,...
Eller så visar det du jämför med 4 grader för lågt...
En annan liten detalj, var växlar du data pinnen mellan ingång och utgång ?
Istället för "Hur gör man för att skriva ut en byte på en pinne?" skulle det
naturligtsvis ha varit "Hur kommunicaerar jag enklast/bäst med en DS1626 ?"
Och så en länk till databladet i *FÖRSTA* inlägget !
Då hade alla svar antagligen sett annorlunda ut.
Det framgår t.ex inte förrens ganska sent att du faktiskt även
*har* en CLK-linje.
> Så SPI/UART känns lite overkill, eller?
> Vad är standard sättet för att kommunicera med dylika externa enheter?
SPI kanske ? Varför är det "overkill" ? Du tycker ju själv att det "Det blir ju en del kod...".
Jo visst, det är därför man bygger in olika hårdvaruenheter för kommunikation.
Men å andra sidan, inte är det där speciellt mycket kod för att bitbanga en seriell temp sensor !
Jag tror att, om man inte vill köra hårdvaru-SPI, så är det nog enklare
att skriva en ASM rutin och anropa från C-koden...
> Dessutom ger sensorn ett värde som är 4 grader celsius för högt,...
Eller så visar det du jämför med 4 grader för lågt...
En annan liten detalj, var växlar du data pinnen mellan ingång och utgång ?
