Sida 1 av 2
Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 13:38:25
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
Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 15:12:20
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.
Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 15:44:18
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
Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 16:04:40
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....

Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 18:29:44
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.
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?
Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 19:02:46
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.
Re: Funderingar kring USART och PIC16F887
Postat: 23 december 2009, 22:58:15
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?
Re: Funderingar kring USART och PIC16F887
Postat: 24 december 2009, 12:47:11
av sodjan
Det mest sannolikt är kanske att du har fel helt enkelt.

Ger de andra två byten vettiga värden ?
Re: Funderingar kring USART och PIC16F887
Postat: 24 december 2009, 13:56:32
av spufuz
Det mest sannolikt är kanske att du har fel helt enkelt.
Ja i detta fallet hoppas jag det!
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?
Re: Funderingar kring USART och PIC16F887
Postat: 24 december 2009, 20:56:51
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?
Re: Funderingar kring USART och PIC16F887
Postat: 24 december 2009, 21:07:34
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.
Re: Funderingar kring USART och PIC16F887
Postat: 24 december 2009, 21:14:23
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'.
Re: Funderingar kring USART och PIC16F887
Postat: 25 december 2009, 12:09:31
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!
Skulle någon här vara intresserad av att skriva en färdig kod för min applikation? Givetvis mot betalning!
Re: Funderingar kring USART och PIC16F887
Postat: 25 december 2009, 12:22:02
av sodjan
Det beror ju helt på vad "min applikation" är för något.
Hjälp
Postat: 25 december 2009, 13:27:23
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