Funderingar kring USART och PIC16F887

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Hej alla glada.
Jag sitter och försöker lära mig ta emot seriell data med en PIC16F887 (Pickit2 44pin Demo Board).

Tanken är att jag ska ta emot MIDI data (31250bps) från mitt MIDI-kontrollbord.
Kontrollbordet skickar vid knapptryckningen 3 bytes som är t.ex:
Status Byte - 0xBF
Data Byte 1 - 0x50
Data Byte 2 - 0x7F

I debug mode i MPLAB funkar programmet och alla register verkar stämma,
men jag är lite osäker på hur jag ska kunna kolla i realtid om byten lagras i PCREG??

Ta gärna även en titt på koden (tabbarna blev lite skumma när jag klistrade in).
Den kanske är helt åt fanders?

Kod: Markera allt

#include <p16F887.inc>
	__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V	

	
	org 0

Start:

;PORT INITIATE
	CLRF	PORTC					;Clear PORTC
	BSF		STATUS,RP0				;Select bank1
	CLRF	TRISC					;PORTC is out
	BCF		TRISD,0					;PORTD,0 is out
	BSF		TRISC,7					;Set RC7/RX input
	BCF		STATUS,RP0				;Back to bank0

;USART CONFIG
	BSF		STATUS,RP0				;Select bank1
	MOVLW	0x01
	MOVWF	SPBRG					;Init 31250 bauds
	BCF		TXSTA,SYNC
	BCF		STATUS,RP0				;Back to bank0
	BSF		RCSTA,SPEN				;Enable EUSART
	BSF		RCSTA,CREN				;Enable EUSART

;Read MIDI-byte
	BTFSS	PIR1,RCIF				;Check for RX flag
	GOTO	$-1						;Go back to RX flag-check
	BSF		PORTD,0					;Light LED if RX flag-bit is set
	GOTO	Start
	END	
För att se om jag överhuvud taget tog emot data på RX så ville jag att en LED skulle tändas när RCIF-biten blev satt.
Den lyser så fort jag ger PICen spänning på VDD.
Om allt hade stämt så skulle jag väl behöva skicka data från kontrollbordet först?

Ber om ursäkt för att jag kanske ställer dumma frågor, men jag har googlat till tusen på detta och hittar bara massa info om PIC16F84(A) som inte har USART utan emulerar en USART med kod.

//david
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Funderingar kring USART och PIC16F887

Inlägg av sodjan »

Ett "problem" är att du inte säkerställer att RCIF är "0" innan du börjar
polla den efter "1". Den ska vara "0" efter POR, men ta alltid för
vana att alltid sätta register så som du vill ha dom i alla fall.

> MOVLW 0x01, MOVWF SPBRG ;Init 31250 bauds

HUr har du räknat ut att det ska vara just 1 ?
Det är ju ett lite märkligt värde och ger inte intryck av att det
är uträknat korrekt.

> GOTO $-1

En annan god vara är att aldrig göra så där, gör alla hopp
till riktiga labels.

Sen så är det ju lite onödigt att hoppa tillbaka til "Start" varje gång, du
behöver ju inte köra om all uppsättning av register o.s.v.

Sen så kanske du skulle ha ett delay innan du börjar polla RCIF (efter att
ha clearat den först efter delayet) så att allt annat runtikring har hunnit
stabilisera sig. Jag vet inte vad du har för RS232 konverters o.s.v.

Om det fungerar i MPLAB/SIM, så perkar det spontant att det är något i den
aktuella kopplingen som inte är som SIM tänkte sig.

Men men, det är i princip bara att lägga till lite mer kod, ta en sak i sänder
o.s.v tills du har hittat var det går snett.
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

HUr har du räknat ut att det ska vara just 1 ?

Jag följer formeln i databladet.

SPBRG = (FOSC/Desired Baud Rate/64)-1
eller
SPBRG = (4000000/31250/64)-1

Jag får då SPBRG till 1.
Interna oscillatorn är på 4mhz.
Talet 64 gäller då conf. bits SYNC, BRG16 och BRGH är 0 och för 8-bit/Asynchronous BRG/EUSART Mode.

Känns som det ska stämma.
Kan jag ha missat/räknat fel på något här?



En annan god vara är att aldrig göra så där, gör alla hopp
till riktiga labels.


Uppfattat!


Sen så kanske du skulle ha ett delay innan du börjar polla RCIF (efter att
ha clearat den först efter delayet) så att allt annat runtikring har hunnit
stabilisera sig.


Intressant. Ska prova det.
Ska jag använda NOP några gånger?


Jag vet inte vad du har för RS232 konverters o.s.v.

Använder ingen RS232.
MIDI-datan "anländer" med 5V men skiljs åt från RX med en optokopplare.
http://www.tigoe.net/pcomp/code/serial- ... ation/midi

Jag är lite osäker på hur jag ska koppla optokopplaren i förhållande till PICen.
I nuläget låter jag Pickit2 mata PICen med 5V.
Optokopplaren har fått 5V från mitt labbagg.
Både PIC och optokoppling är jordat tillsammans. Rätt?

//David
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Funderingar kring USART och PIC16F887

Inlägg av sodjan »

> Kan jag ha missat/räknat fel på något här?

Nja, jag sa bara att det *såg* lite märkligt ut. Det är mycket möjligt
att det råkar vara just SPBRG = 1 som ger rätt baudrate.

> Ska jag använda NOP några gånger?

Jag tänkte mig mer en sekund eller så... :-)
Någon liten delay loop som du anropar eller liknande.

Det där med optokopplaren var något nytt. Var kom den ifrån ?
Det fanns inget om det förrut.

Har du mätt på optokopplaren för att se att du har rätt nivåer
när linjen är "idle" ? D.v.s innan du börjar sända ?

Och ja, optokopplaren och PIC'en måste ha gemensam GND, annars blir
det väldigt förvirrat. Vad är "5V" o.s.v.... :-)
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Det är mycket möjligt
att det råkar vara just SPBRG = 1 som ger rätt baudrate.


Hur yttrar det sig ifall man har angett fel?
Tar man emot någon data alls?


Har du mätt på optokopplaren för att se att du har rätt nivåer
när linjen är "idle" ? D.v.s innan du börjar sända ?


Här har jag lite dålig koll på hur det funkar. :doh:
PICen läser ju skillnader i ström och inte spänning va?
Saxat från http://www.pykett.org.uk/a_midi_pedalboard_encoder.htm
"MIDI uses a serial digital current loop controlled from the transmitting end of the link to operate an opto-isolator at the receiving end."

- Då ska det alltså ligga 5V hela tiden på RX?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Funderingar kring USART och PIC16F887

Inlägg av sodjan »

> PICen läser ju skillnader i ström och inte spänning va?

Nej. Det är optokopplaren som gör det. PIC'en förväntar sig normala
logiska nivåer (i princip 5V och GND). Optokopplaren kan man säga
omvandlar mellan "ström"/"inte ström" till spänningsnivåer.

> Hur yttrar det sig ifall man har angett fel [SPBRG] ?
> Tar man emot någon data alls?

Sannolikt inte.
Men just nu vet du väl inte om du tar emot något eller inte, eller hur ?

> Då ska det alltså ligga 5V hela tiden på RX?

Eller 0V (GND), bara det är "rätt". Jag frågade bara om du hade kollat
att det var "rätt", jag har inte funderat på vad som är rätt eller fel... :-)
Man om jag gör det så är det väl så att UART ingången ska vara hög (5V)
när det inte sänds någonting på linjen.
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Nu så!
Som jag nästan anade så hade jag inte riktigt kläm på optokopplaren.
Jag får nu ett värde på RCREG när jag trycker på någon knapp på pedalbordet.

Konstigt nog får jag 0x7E (126) då jag är ganska säker på att sista byten som skickas ska vara 0x7F (127)
Läser USARTen fel?

För om det skickas tre bytes efter varann till RCREG så kommer sista att ligga kvar i registret va?
De första två skrivs väl över?
Om så är fallet så är jag helt säker på att värdet ska va 0x7F.

0x7E = '01111110'
0x7F = '01111111'

Missar han sista biten tro?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Funderingar kring USART och PIC16F887

Inlägg av sodjan »

Det mest sannolikt är kanske att du har fel helt enkelt. :-)
Ger de andra två byten vettiga värden ?
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Det mest sannolikt är kanske att du har fel helt enkelt. :-)

Ja i detta fallet hoppas jag det! :D


Ger de andra två byten vettiga värden ?

Det är det jag inte riktigt vet hur jag ska kolla.
Jag kan ju bara se den sista byten i RCREG.
Jag vet inte hur jag ska skriva kod för att "fånga" upp varje byte.

Jag provade att definera 3 st register med hjälp av "cblock" i General Purpose Register 0x20.
Så här:

Kod: Markera allt

   cblock 0x20
StatusByte
DataByteOne
DataByteTwo
	endc
Tanken var att jag skulle lägga en byte i varje register för att kunna läsa av dem i MPLABS debugger.
Dvs för att se att jag tar emot rätt data.
Men jag vet inte riktigt hur jag ska skriva kod för att lägga varje byte jag tar emot i var sitt register.
Kanske du har nån synpunkt eller nåt förslag?
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Uppdaterar lite:
Jag kan se att biten FERR på RCSTA blir satt när jag tar emot data.
Detta är ju framing error och FERR blir satt när Stop-biten inte är läst.

Kan det ha något med baudraten att göra?
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9127
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: Funderingar kring USART och PIC16F887

Inlägg av AndersG »

Om du har fel baudrate så kommer du att få massvis med "framing errors". Ett enkelt sätt att kolla är att köra en loop som matar ut samma, kända tal på USARTen och titta på signalen i ett oscilloskop. Där kan du kolla ett pulserna har rätt längd. Jämför sedan med signalen från den pryl du vill kommunicera med.

Kolla även polariteten. Dvs skall en etta vara hög eller låg? Kolla "SCKP: Synchronous Clock Polarity Select bit", sid 164 i manualen.
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Funderingar kring USART och PIC16F887

Inlägg av Icecap »

Det kan det mycket väl.

Och att ta emot fler bytes är knappast ett problem.
Allokera (reservera) ett antal bytes som motsvarar det högsta antal bytes du kan motta:
#define BUFFER_SIZE 10
Buffer .res BUFFER_SIZE; Själva buffern
B_Index .res 1; Indexpekaren

När du börjar nollar du B_Index, sedan använder du INDF & FSR till att indexera:
; Utgår ifrån att RCREG innehåller den mottagna byte
MOVF B_Index, W ; Hämta index
ADDLW Buffer, W ; Lägg till adressen på buffern
MOVWF FSR ; Peta in i indexeringsregister
MOVF RCREG, W ; Hämta den mottagna byte
MOVWF INDF ; Spara i buffern
INCF B_INDEX, F ; Stega upp och peka på nästa plats i buffern

OBS: programmet BÖR säkra mot buffer overflow osv. Och avkänna när en block har mottagits osv.

Och på vanlig asynkron kommunikation ska det vara '1' vid "tomgång", startbit'en är alltså '0' varför stoppbit'en måste vara '1'.
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Re: Funderingar kring USART och PIC16F887

Inlägg av spufuz »

Hur mycket jag än vill sitta och försöka lära mig detta och försöka lösa detta så känns det som att jag saknar tiden just nu.
Har t.ex en son på ett år som tar ganska mycket tid bara han! :D

Skulle någon här vara intresserad av att skriva en färdig kod för min applikation? Givetvis mot betalning!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Funderingar kring USART och PIC16F887

Inlägg av sodjan »

Det beror ju helt på vad "min applikation" är för något.
spufuz
Inlägg: 704
Blev medlem: 15 september 2006, 00:00:39
Ort: Tanum

Hjälp

Inlägg av spufuz »

Absolut. Jag tänkte jag skulle förklara det om någon var intresserad.

Så här är det tänkt:

Jag har en sån här:
http://www.voodoolab.com/gcontrolpro.htm
Den kan via 8 st knappar sända ut var sin MIDI Control Change till den här enheten:
http://www.voodoolab.com/gcx.htm
Det är alltså en replika på en GCX Audio Switcher som jag tänkt bygga.

När jag trycker på t.ex knapp 1 på min Ground Control Pro så ska loop1 på GCXen aktiveras (tex. RD0 på PICen ska bli hög om vi nu sätter den som utgång).
Trycker jag på knapp 1 igen så stängs loop1 av (RD0 blir låg igen).

Ground Control´en skickar tre bytes till GCXen för att styra detta:

1 . Först en Status Byte som talar om att det är en Control Change på kanal 16 (GCXen lyssnar bara på kanal 16 och det ska även min applikation göra).
Status Byte = 0xBF
där B anger att det är ett CC kommando och F är kanalen.


2. Andra Byten är Data Byte 1 som anger vilken controller GCXen ska låta Ground Controlen styra.
Data Byte 1 = 0x50 - 0x57

Controller #80 (0x50) styr relä 1 (tex. RD0).
Controller #81 (0x51) styr relä 2 (tex. RD1).
Controller #82 (0x52) styr relä 3 (tex. RD2).
osv...

3. Tredje byten avgör nu om Controller #xx ska vara på eller av (RDx hög eller låg).
Data Byte 2 = 0x00-0x3F eller 0x40-0x7F (0-63 eller 64-127 decimalt).

Lite sammanfattat:
- Om GCXen får värdet 0xBF på första byten
- 0x52 på andra byten
- Samt värdet 64-127 på tredje byten
Så sätts RD2 hög. Tredje relät slås på.

- Om GCXen får värdet 0xBF på första byten
- 0x52 på andra byten
- Samt värdet 0-63 på tredje byten
Så sätts RD2 låg igen. Tredje relät slås av igen.

Hoppas jag inte rör till allt mer än nödvändigt.
Men detta bör ge er en hint om hur det är tänkt.

//david
Senast redigerad av spufuz 26 december 2009, 09:45:40, redigerad totalt 1 gång.
Skriv svar