PIC -> PIC via RS232 nya frågor..
PIC -> PIC via RS232 nya frågor..
I ett av mina projekt använder jag mig av en PIC16F628A för att samla in data som jag presenterar på en display.
Nu tänkte jag ta detta ett steg längre genom att samla in data som jag gör idag, men istället för att skicka det direkt till displayen så vill jag skicka data via RS232 i ett tiotal meter kabel för att sedan tas emot av en annan PIC som i sin tur presenterar data på displayen.
Har fått ordning på koden i den sändande enheten så att jag kan se resultatet på min PC ett terminalfönster.
Det var lite bakgrund det, nu till min fråga:
Den data jag vill skicka består av värdet hos 14 bitar.
Jag får alltså skicka detta i två byte.
Vad jag inte är med på och inte har hittat något svar på (då jag inte riktigt vet vad jag ska söka på) är hur man ska skicka för att mottagande enhet ska kunna hålla reda på vad som är vad!? Vilken byte som är vilken alltså..
Först tänkte jag skicka 7 bitar i ena byten och 7 i den andra och låta den sista biten som blir över i varje byte vara antingen 1 eller 0 beroende på vilken byte det är. Då kan man ju med lätthet urskilja i mottagaren vilken som är vilken.
Men om jag vill skicka tre eller fler byte framöver så funkar ju inte detta..
Vad säger expertisen? Vart ska jag läsa mig till hur man gör och hur man bör tänka?
Har sökt här och googlat lite planlöst, men vet som sagt inte vad jag ska söka på riktigt, så en liten knuff i rätt riktning är vad jag efterfrågar.
Tack på förhand
EDIT: Ämnesraden.. (2012-03-11)
Nu tänkte jag ta detta ett steg längre genom att samla in data som jag gör idag, men istället för att skicka det direkt till displayen så vill jag skicka data via RS232 i ett tiotal meter kabel för att sedan tas emot av en annan PIC som i sin tur presenterar data på displayen.
Har fått ordning på koden i den sändande enheten så att jag kan se resultatet på min PC ett terminalfönster.
Det var lite bakgrund det, nu till min fråga:
Den data jag vill skicka består av värdet hos 14 bitar.
Jag får alltså skicka detta i två byte.
Vad jag inte är med på och inte har hittat något svar på (då jag inte riktigt vet vad jag ska söka på) är hur man ska skicka för att mottagande enhet ska kunna hålla reda på vad som är vad!? Vilken byte som är vilken alltså..
Först tänkte jag skicka 7 bitar i ena byten och 7 i den andra och låta den sista biten som blir över i varje byte vara antingen 1 eller 0 beroende på vilken byte det är. Då kan man ju med lätthet urskilja i mottagaren vilken som är vilken.
Men om jag vill skicka tre eller fler byte framöver så funkar ju inte detta..
Vad säger expertisen? Vart ska jag läsa mig till hur man gör och hur man bör tänka?
Har sökt här och googlat lite planlöst, men vet som sagt inte vad jag ska söka på riktigt, så en liten knuff i rätt riktning är vad jag efterfrågar.
Tack på förhand
EDIT: Ämnesraden.. (2012-03-11)
Senast redigerad av Variosboy 11 mars 2012, 20:00:13, redigerad totalt 1 gång.
Re: PIC -> PIC via RS232 en enkel fråga..
Det finns ett antal olika sätt att göra detta på, och jag tror inte det finns 'den perfekta lösningen' utan man får anpassa efter hur dina data ser ut , hur ofta det sänds osv...
Din lösning med två bytes var ju smart, så om du inte behöver fler bytes kan du ju göra så till en början.
Annars finns lite varianter som sagt: Enklast är om du alltid har bara 7 bitar i all data. Då kan första byten alltid ha bit7 = etta, och följande bytes har bit7 = nolla. Då är det bara att köra på sen. så länge datan har bit7= nolla så är det bara att räkna bytes.
Om du absolut vill ha åtta-bitars data blir det svårare:
1) tidskritiska: man har en paus på en viss tid (t.ex 1 ms) mellan meddelandena. När meddelandet sedan kommer kan man t.ex skicka ett i förväg bestämt antal bytes (4, 8, 16 ,32 64 eller 128 bytes t.ex beroende på behov) . Mellan dessa får inte gå lägre tid än 0.5 ms.... På så vis vet mottagaren att om det gått mer än 0.75 ms så börjar en ny serie.
2) start-och stopp-bytes med checksumma. Du inleder med en eller två standard-bytes, följt av en byte där antalet databytes anges - sedan kommer data (i rätt antal) och avslutas sedan med en checksummebyte och eventuellt en stoppbyte. Det kan krävas lite klurighet för att få det att fungera. T.ex. kan man köra med 'bytestuffing': Om startbytena är t.ex. tecknen AA så får inte datan innehålla två A i rad. Ett A måste då alltid följas av ett extra byte som inte är ett A och som bara fungerar som utfyllnad.
Enklast är nog att sända allt i ascii-kod. Låt bara vissa tecken vara godkända, t.ex. '0'-'9' samt 'A'-'Z' och kanske komma, kolon, punkt. Då kan man använda ett start-tecken och ett slut-tecken so är unika. Ofta används $-tecknet som start-tecken och 0x0d (carriage return) som stopptecken.
Mottagaren väntar då tills ett $-tecken kommer in. Hur mycket data det än strömmar in före det så ignoreras det.
Men efter $-tecknet läser man in all data ända tills man får in ett 0x0d. Då har man fått in en 'sträng' som sedan kan bearbetas. Fördelen med ascii och 0x0d är ju att man kan kommunicera manuellt via terminal och få 'return'-tangenten att fungera som 'sänd'. Sedan är det fritt valt om man vill skicka siffror som hex-code eller decimalt eller på annat vis. Vill man verifiera att rätt data kommit fram beräknar man en checksumma på alla tecken och skickar med den före return-tecknet i hexadecimal form (två tecken) med en stärna ('*') före. Stjärnan och dollartecknet får då inte förekomma någon annanstans i strängen.
exempel:
$TMP:23:220*A6<cr>
=> sätt temperatur i punkt 23 till 220 grader.
(Checksumman (A6) påhittad - orkade inte räkna ut)
$BATT
3440
3425*D6<cr>
=> skickar spänningsnivåer på fyra battericeller.
Din lösning med två bytes var ju smart, så om du inte behöver fler bytes kan du ju göra så till en början.
Annars finns lite varianter som sagt: Enklast är om du alltid har bara 7 bitar i all data. Då kan första byten alltid ha bit7 = etta, och följande bytes har bit7 = nolla. Då är det bara att köra på sen. så länge datan har bit7= nolla så är det bara att räkna bytes.
Om du absolut vill ha åtta-bitars data blir det svårare:
1) tidskritiska: man har en paus på en viss tid (t.ex 1 ms) mellan meddelandena. När meddelandet sedan kommer kan man t.ex skicka ett i förväg bestämt antal bytes (4, 8, 16 ,32 64 eller 128 bytes t.ex beroende på behov) . Mellan dessa får inte gå lägre tid än 0.5 ms.... På så vis vet mottagaren att om det gått mer än 0.75 ms så börjar en ny serie.
2) start-och stopp-bytes med checksumma. Du inleder med en eller två standard-bytes, följt av en byte där antalet databytes anges - sedan kommer data (i rätt antal) och avslutas sedan med en checksummebyte och eventuellt en stoppbyte. Det kan krävas lite klurighet för att få det att fungera. T.ex. kan man köra med 'bytestuffing': Om startbytena är t.ex. tecknen AA så får inte datan innehålla två A i rad. Ett A måste då alltid följas av ett extra byte som inte är ett A och som bara fungerar som utfyllnad.
Enklast är nog att sända allt i ascii-kod. Låt bara vissa tecken vara godkända, t.ex. '0'-'9' samt 'A'-'Z' och kanske komma, kolon, punkt. Då kan man använda ett start-tecken och ett slut-tecken so är unika. Ofta används $-tecknet som start-tecken och 0x0d (carriage return) som stopptecken.
Mottagaren väntar då tills ett $-tecken kommer in. Hur mycket data det än strömmar in före det så ignoreras det.
Men efter $-tecknet läser man in all data ända tills man får in ett 0x0d. Då har man fått in en 'sträng' som sedan kan bearbetas. Fördelen med ascii och 0x0d är ju att man kan kommunicera manuellt via terminal och få 'return'-tangenten att fungera som 'sänd'. Sedan är det fritt valt om man vill skicka siffror som hex-code eller decimalt eller på annat vis. Vill man verifiera att rätt data kommit fram beräknar man en checksumma på alla tecken och skickar med den före return-tecknet i hexadecimal form (två tecken) med en stärna ('*') före. Stjärnan och dollartecknet får då inte förekomma någon annanstans i strängen.
exempel:
$TMP:23:220*A6<cr>
=> sätt temperatur i punkt 23 till 220 grader.
(Checksumman (A6) påhittad - orkade inte räkna ut)
$BATT
=> skickar spänningsnivåer på fyra battericeller.
Re: PIC -> PIC via RS232 en enkel fråga..
Tack för ett mycket bra svar!
Tror att lösningen med en startbyte stoppbyte och checksumma med ett förutbestämt antal byte kan bli rätt bra i mitt fall Dels för att det verkar enkelt att lägga till en byte om det blir så att jag vill skicka mer data, plus att det blir en säkrare överföring än den jag själv först tänkte..
Återkommer när jag kodat och kört huvudet i väggen ett par gånger!
Tror att lösningen med en startbyte stoppbyte och checksumma med ett förutbestämt antal byte kan bli rätt bra i mitt fall Dels för att det verkar enkelt att lägga till en byte om det blir så att jag vill skicka mer data, plus att det blir en säkrare överföring än den jag själv först tänkte..
Återkommer när jag kodat och kört huvudet i väggen ett par gånger!

Re: PIC -> PIC via RS232 en enkel fråga..
> Enklast är nog att sända allt i ascii-kod.
Det är ett väldigt bra tips!
Det hela blir så jäkla mycklet enklare att felsöka, en vanlig
terminalemulator kan enkelt användas för att både lyssna på
sändaren och för att testa mottagaren...
Det är ett väldigt bra tips!
Det hela blir så jäkla mycklet enklare att felsöka, en vanlig
terminalemulator kan enkelt användas för att både lyssna på
sändaren och för att testa mottagaren...
Re: PIC -> PIC via RS232 en enkel fråga..
Ja. När jag var nybörjare på det här så var jag fast bestämd att sända binärt, åtta bitar per byte, för att spara in överförings-tid. Men när jag hållt på ett tag undviker jag det om det inte är helt nödvändigt. Precis som Sodjan säger - det är väldigt bekvämt med ascii! Särskilt om man följer några enkla regler (som mina exempel ovan).
Re: PIC -> PIC via RS232 en enkel fråga..
Nu har testats lite men jag gör något fel...
Har kopplat upp följande:
En 16F628A med en kod i som räknar ner en räknare från 100 till 0 och sen börjar om. Den räknare ner med några sekunders mellanrum och varje gång den räknat ner ett snäpp så skickar den ut detta som seriell data..
Utgången har jag kopplat till en trådlös sändare ER400TS och en bit bort på samma platta sitter en ER400RS, och en MAX232 + en transistor som agerar nivåomvandlare då utgången på ER400RS ger 3,3V som hög.
MAX232:an är i sin tur kopplad till en RS232-port (Eller ja, en RS232 -> USB).
Med programmet Terminal v1,9b kan jag nu se på skärmen att det kommer data och att sändningen av data är korrekt. Den räknar ner från 100 till 0 och börjar sen om på 100 igen...
Men, nu kommer mitt men..
Har ett LOW PIN COUNT DEMO BOARD kopplat till en LCD där jag vill pressentera data. Inkopplingen av detta är gjord så att GND på ER400RS och LOW PIN COUNT kortet är gemensam, sen är datalinjen kopplad parallellt med data in på ER400RS till RB5 på LOW PIN COUNT kortet..
Och det är här mitt problem kommer in.
Har klippt och klistrat ihop Sodjans kod med en kod från piclist.org för att skriva ut datan på en LCD.
Visningen fungerar så tillvida att att jag får ett värde utskrivet på displayen, men det är inte det förväntade värdet (alltså det värde som skickas och som visas på min PC) plus att det inte skrivs ut ett nytt värde varje gång sändaren skickar, utan det kommer ett lite då och då)
Skickar i 19200 BAUD, 8 databitar, 1 stopbit utan paritet.
Allt enligt följande kodsnutt i 16F628A:an
Mottagande kod är som sagt lite klipp och klistra mellan två koder så det är ju skrivet på lika olika vis, men ändå, här kommer ett klipp ur koden för mottagning av data:
Sen delen av koden där mottagningen sker:
Har testat att lägga in följande två rader efter "movwf räknare":
Och då blir utskriften 255 på displayen. (Har även testat med andra värden)
Utskriftstutinen gör om binära tal till BCD och skickar först hundratal, sen tiotal och sist ental till displayen..
Så den delen fungerar också som tänkt.
Gör jag en enkel tankevurpa, eller har jag helt missförstått hur det ska gå till när det gäller att ta emot data??
OSB, mottagaren är en PIC16F690..
Har kopplat upp följande:
En 16F628A med en kod i som räknar ner en räknare från 100 till 0 och sen börjar om. Den räknare ner med några sekunders mellanrum och varje gång den räknat ner ett snäpp så skickar den ut detta som seriell data..
Utgången har jag kopplat till en trådlös sändare ER400TS och en bit bort på samma platta sitter en ER400RS, och en MAX232 + en transistor som agerar nivåomvandlare då utgången på ER400RS ger 3,3V som hög.
MAX232:an är i sin tur kopplad till en RS232-port (Eller ja, en RS232 -> USB).
Med programmet Terminal v1,9b kan jag nu se på skärmen att det kommer data och att sändningen av data är korrekt. Den räknar ner från 100 till 0 och börjar sen om på 100 igen...
Men, nu kommer mitt men..
Har ett LOW PIN COUNT DEMO BOARD kopplat till en LCD där jag vill pressentera data. Inkopplingen av detta är gjord så att GND på ER400RS och LOW PIN COUNT kortet är gemensam, sen är datalinjen kopplad parallellt med data in på ER400RS till RB5 på LOW PIN COUNT kortet..
Och det är här mitt problem kommer in.
Har klippt och klistrat ihop Sodjans kod med en kod från piclist.org för att skriva ut datan på en LCD.
Visningen fungerar så tillvida att att jag får ett värde utskrivet på displayen, men det är inte det förväntade värdet (alltså det värde som skickas och som visas på min PC) plus att det inte skrivs ut ett nytt värde varje gång sändaren skickar, utan det kommer ett lite då och då)
Skickar i 19200 BAUD, 8 databitar, 1 stopbit utan paritet.
Allt enligt följande kodsnutt i 16F628A:an
Kod: Markera allt
; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 19200, No Parity, 1 Stop Bit
;
movlw 0x0C ; (0x19=9600 bps) 0x0C=19200 bps
movwf SPBRG
movlw b'00100100' ; brgh = high (2)
movwf TXSTA ; enable Async Transmission, set brgh
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
movwf RCSTA
Mottagande kod är som sagt lite klipp och klistra mellan två koder så det är ju skrivet på lika olika vis, men ändå, här kommer ett klipp ur koden för mottagning av data:
Kod: Markera allt
; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 19200, No Parity, 1 Stop Bit
;
movlw 0x0C ;( 0x19=9600 bps) 0x0C=19200 bps
movwf SPBRG
movlw 0x00
movwf SPBRGH
bcf BAUDCTL,BRG16 ; Clear BRG16 = 8 BIT mode
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
movwf RCSTA
Kod: Markera allt
receive
nop
btfss PIR1,RCIF ; (5) check for received data
goto receive
movfw RCREG ; save received data in W
movwf räknare ; Sparar mottaget värde i "räknare" som sen i nästa rutin skickas till displayen..
return
Kod: Markera allt
movlw 0xFF
movwf räknare
Utskriftstutinen gör om binära tal till BCD och skickar först hundratal, sen tiotal och sist ental till displayen..
Så den delen fungerar också som tänkt.
Gör jag en enkel tankevurpa, eller har jag helt missförstått hur det ska gå till när det gäller att ta emot data??
OSB, mottagaren är en PIC16F690..
Re: PIC -> PIC via RS232 en enkel fråga..
Mitt tips är att i mottagningsdelen inte använda "goto Recieve" men istället "call Recieve"...
Re: PIC -> PIC via RS232 en enkel fråga..
blir inte det helt fel??
"Receive" är ju en subbrutin som anropas från huvudprogramloopen, och för att slippa lägga in en "loop" raden under receive som man i kontrollen av RCIF kör goto till så antar jaga att författaren (inte jag) tänkt..
Jag tänker att om jag skriver call receive där så kommer det ju att fylla stacken tillslut eftersom man kommer tillbaka till call receive hela tiden om man kör call istället för som nu goto så länge ingen mottagning skett. Eller!?
Det är ju tänkt som en evighetsloop tills dess att data kommer in via serielänken.
"Receive" är ju en subbrutin som anropas från huvudprogramloopen, och för att slippa lägga in en "loop" raden under receive som man i kontrollen av RCIF kör goto till så antar jaga att författaren (inte jag) tänkt..
Jag tänker att om jag skriver call receive där så kommer det ju att fylla stacken tillslut eftersom man kommer tillbaka till call receive hela tiden om man kör call istället för som nu goto så länge ingen mottagning skett. Eller!?
Det är ju tänkt som en evighetsloop tills dess att data kommer in via serielänken.
Re: PIC -> PIC via RS232 en enkel fråga..
Sorry, my bad. Läste lite slarvigt och du har rätt.
Men det är ganska bra klarat att du har svenska tecken i variabelnamnen, det har jag aldrig lyckats med...
Vilken felhantering har du? Ett standardfel är att man inte börjar med att sätta TX-pinnen till '1' och sedan startar UART'en, står den på '0' kommer första tecknet att bli bortkastat pga. att startbit'en missas.
Men det är ganska bra klarat att du har svenska tecken i variabelnamnen, det har jag aldrig lyckats med...
Vilken felhantering har du? Ett standardfel är att man inte börjar med att sätta TX-pinnen till '1' och sedan startar UART'en, står den på '0' kommer första tecknet att bli bortkastat pga. att startbit'en missas.
Senast redigerad av Icecap 4 mars 2012, 19:30:49, redigerad totalt 1 gång.
Re: PIC -> PIC via RS232 en enkel fråga..
För övrigt är det modulerna jag köpte av dig som jag kopplat in, funkade perfekt på en gång!
Sänder förvisso ungefär 10cm bara nu, men som du skrev när jag köpte dom så är det ju bara att "Bryta" upp signalen mellan sändare och mottagare och stoppa in modulerna istället. plus transistorn då för nivån ut ut mottagaren. Men otroligt smidigt som sagt och nu när jag kollade igenom loggen i terminalprogrammet kan jag konstatera att sändningen varit utan avbrott eller felaktigheter i ungefär 4 timmar nu.. Känns också bra!

Sänder förvisso ungefär 10cm bara nu, men som du skrev när jag köpte dom så är det ju bara att "Bryta" upp signalen mellan sändare och mottagare och stoppa in modulerna istället. plus transistorn då för nivån ut ut mottagaren. Men otroligt smidigt som sagt och nu när jag kollade igenom loggen i terminalprogrammet kan jag konstatera att sändningen varit utan avbrott eller felaktigheter i ungefär 4 timmar nu.. Känns också bra!
Re: PIC -> PIC via RS232 en enkel fråga..
Nu har jag grejat lite mer med min mottagarkod, men får det inte att fungera som jag vill.
Nedan finns hela mottagarkoden..
Förväntat resultat är att den byte som läses in på RB5 (RX) ska konverteras (via rutin BIN2BCD) och skrivas ut på en LCD.
Sändande enheten är som jag skrev tidigare i tråden en 16F628A, TX på denna är kopplad både till en MAX232 och även till den 16F690 som displayen är kopplad till.
Koden i 16F628A syns i ett av inläggen ovan, och vad den gör är alltså att räkna ner en räknare från 100 till 0 och sen börja om, och för varje gång den räknat ner ett snäpp så skickas denna byten ut via serieinterfacet.
Har denna inkopplad till min PC där jag via terminalfönstret kan verifiera att "rätt/förväntad" data kommer som den ska..
Nu till problemet.
På min display får jag endast dessa utskrifter i decimal form:
252 (skrivs ut när jag i terminalfönstret ser exvis. 7 eller 3 decimalt)
192 (skrivs ut när jag i terminalfönstret ser exvis. 10, 6 eller 2 decimalt)
060 (skrivs ut när jag i terminalfönstret ser exvis. 9, 5 eller 1 decimalt)
000 (skrivs ut när jag i terminalfönstret ser exvis. 8, 4 eller 0 decimalt)
Data sänds med 3 sekunders intervall och först står det alltså 252 på displayen, sen 192, 060, 000 och sen börjar det om med 252..
Samma data in ger alltid samma resultat på displayen, men den alternerar alltså enbart mellan dessa fyra kombinationer..
Terminalprogramet är inställt för att ta emot i 19200 BAUD, 8 bitar, ingen paritet och med en stopp bit. Ingen handskakning..
Och här kommer koden:
Så, har ni några förslag?
Nedan finns hela mottagarkoden..
Förväntat resultat är att den byte som läses in på RB5 (RX) ska konverteras (via rutin BIN2BCD) och skrivas ut på en LCD.
Sändande enheten är som jag skrev tidigare i tråden en 16F628A, TX på denna är kopplad både till en MAX232 och även till den 16F690 som displayen är kopplad till.
Koden i 16F628A syns i ett av inläggen ovan, och vad den gör är alltså att räkna ner en räknare från 100 till 0 och sen börja om, och för varje gång den räknat ner ett snäpp så skickas denna byten ut via serieinterfacet.
Har denna inkopplad till min PC där jag via terminalfönstret kan verifiera att "rätt/förväntad" data kommer som den ska..
Nu till problemet.
På min display får jag endast dessa utskrifter i decimal form:
252 (skrivs ut när jag i terminalfönstret ser exvis. 7 eller 3 decimalt)
192 (skrivs ut när jag i terminalfönstret ser exvis. 10, 6 eller 2 decimalt)
060 (skrivs ut när jag i terminalfönstret ser exvis. 9, 5 eller 1 decimalt)
000 (skrivs ut när jag i terminalfönstret ser exvis. 8, 4 eller 0 decimalt)
Data sänds med 3 sekunders intervall och först står det alltså 252 på displayen, sen 192, 060, 000 och sen börjar det om med 252..
Samma data in ger alltid samma resultat på displayen, men den alternerar alltså enbart mellan dessa fyra kombinationer..
Terminalprogramet är inställt för att ta emot i 19200 BAUD, 8 bitar, ingen paritet och med en stopp bit. Ingen handskakning..
Och här kommer koden:
Kod: Markera allt
;**********************************************************************
; *
; Filnamn: trådlös display.asm
; Datum: 2012-03-01
; Fil Version: 1.0
;
; Skapad av: Morgan
;
;**********************************************************************
;
; Filer som krävs: P16F690.INC
; 16F690.LKR
;
;**********************************************************************
;
; Diverse:
; Använder intosc på 4 Mhz.
;
; E : RC3
; RS: RC2
; D4-D7 : RC4-RC7
; R/W kopplad till GND (d.v.s ingen läsning av Busy-signalen).
; Serielina in : RB5
;**********************************************************************
;
;
;
list p=16f690;
#include <P16F690.INC>
;
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
;
errorlevel -302
;
#define LCD_E PORTC,3
#define LCD_RS PORTC,2
#define LCD_PORT PORTC
;
;**********************************************************************
RESET_VECTOR CODE 0x000
goto start
;
INT_VECTOR CODE 0x004
retfie
;
;
;**********************************************************************
; Macro för att skicka en text till LCD.
;
lcd_text macro text_label
banksel eeadr ; byt till rätt bank...
movlw high text_label ; bit 8-15 av adressen till texten
movwf eeadrh
movlw low text_label ; bit 0-7 av adressen till texten
movwf eeadr
;
; Nu är de två adressregistren laddade med rätt adress.
; Anropa subrutinen för att hämta texten och skriva ut den.
;
call lcd_send_text
banksel porta ; Lämna rutinen i bank 0.
;
endm
;
;**********************************************************************
; Huvudkoden.
; Här hamnar vi vid reset eller power-on (från RESET_VECTOR)
;
;
MAIN CODE
start
;
; Först normal uppstart ej specifik för LCD
;
banksel ansel ; Stäng av alla analoga funktioner
clrf ansel
clrf anselh
banksel trisa ; Alla pinnar utgångar...
clrf trisa
clrf trisb
movlw b'00100000' ; RB5 = ingång (RX = ingång)
movwf trisb
clrf trisc
;
banksel intcon
clrf intcon
banksel porta ; se till att vi är på bank 0.
movlw 0x01 ; Sätter räknare till 1 (decimalt)
movwf räknare
;**********************************************************************
; Inställning av baudrate
;**********************************************************************
; Baud rate = 19200, ingen paritetsbit, 1 stopp Bit
;
movlw 0x0C ;( 0x19=9600 bps) 0x0C=19200 bps
movwf SPBRG
movlw 0x00
movwf SPBRGH
bcf BAUDCTL,BRG16 ; Nollar BRG16 = 8 BIT:s läge
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
movwf RCSTA
;
;**********************************************************************
; PROVIDE A SETTLING TIME FOR START UP
;**********************************************************************
;
clrf dataL
settle decfsz dataL,F
goto settle
movf RCREG,W
movf RCREG,W
movf RCREG,W ; rensar mottagningsbufferten
;**********************************************************************
;
; Så då var grundinställningen av processorn klar.
; Nu går vi vidare med LCD hanteringen...
;
call lcd_init_hd44780 ; Ställ in LCD'n.
;
;Här kommer programloopen:
call standardtext
call print_räknare
program
call ta_emot
call print_räknare
goto program
;
ta_emot
movf RCREG,W
movf RCREG,W
movf RCREG,W ; rensa mottagarbufferten
ta_emot_loop
; clrf räknare
nop
; btfss RCSTA,1 ; Overflow?
; bsf RCSTA,4 ; om ja nollställer vi
btfss PIR1,RCIF ; Kommit någon data? Om ja hoppar vi över nästa rad
goto ta_emot_loop
movfw RCREG ; Flyttar mottagen data till W
movwf räknare ; W till räknare...
; movlw 0xFF ; Test för att se om rutinen för utskrift skriver ut på rätt sätt från "räknare"
; movwf räknare ; Resultat = Ja, testade värden, Ox00, Ox00, Ox0F, Ox1F och OxFF..
return
;-------------------------------------------
;Standardtext
;
;Skriver ut standardtexten på displayen:
;**********************************************************************
;(tre mellanslag) och sen ett %-tecken på översta raden på LCD:en
;-------------------------------------------
standardtext
lcd_text lcd_text1
lcd_text lcd_text2
return
;-----------------------------------------------------
;Skriver ut värdet på räknare med början på possition ett rad ett
;-----------------------------------------------------
Print_Räknare
movfw Räknare ; värdet på räknare till W.
movwf BIN ; Vidare till variabeln BIN.
call BIN2BCD ; Anropar subrutin BIN2BCD som gör om
movlw 0x80 ; värdet i BIN till en byte för vardera hundratal, tiotal och ental.
call lcd_send_cmd ; Kommando till displayen för att sätta markören på rätt ställe
movfw huns
call lcd_send_data ; Överför hundratal
movfw tens
call lcd_send_data ; Överför tiotal
movfw ones
call lcd_send_data ; Överför ental
call delay_1s ; vänta lite...
return
;**********************************************************************
; Variabler
;
; Nägra temp variabler som används av LCD rutinerna.
; Lägger dom i "shared memory" så slipper vi banksel...
;
LCD_VARS UDATA_SHR
LCD_TMP1 RES 1
LCD_TMP2 RES 1
BIN RES 1
huns RES 1
tens RES 1
ones RES 1
COUNT RES 1
Räknare RES 1
datal RES 1
;
;**********************************************************************
;
LCD_CODE CODE
;
lcd_init_hd44780
;
call delay_1s ; Ge LCD'n tid att starta...
bcf LCD_E ; Se till att E och RS är
bcf LCD_RS ; nollade...
;
; Skicka initkoder enligt manual för HD44780.
; För detaljer, se manual för HD44780 eller datablad för en LCD.
;
movlw h'30'
call lcd_send_4_bit
call delay_5ms
movlw h'30'
call lcd_send_4_bit
call delay_5ms
movlw h'30'
call lcd_send_4_bit
call delay_100us
movlw h'20' ; Byt till 4-bitars interface !
;
call lcd_send_4_bit
call delay_100us
;
; Allt härefter sänds som två
; 4-bittars "nibbles". Först
; den höga delen (bit 4-7) sedan
; den låga (bot 0-3).
; Se lcd_send_cmd och lcd_send_data för detaljer.
;
movlw b'00101000' ; Function set
call lcd_send_cmd
movlw b'00010100' ; Display/curs shift
call lcd_send_cmd
movlw b'00001100' ; Display/curs on/off
call lcd_send_cmd
movlw b'00000110' ; Entry mode set
call lcd_send_cmd
movlw b'00000010' ; Display/curs home
call lcd_send_cmd
movlw b'00000001' ; Display clear
call lcd_send_cmd
;
; För detaljer kring varje kommando oven hänvisas till
; manual för HD44780 eller ett datablad för en LCD.
;
return
;
lcd_toggle_E
;
; Toggla E p LCD'n så att data på D4-D7 läses in.
;
banksel lcd_port
bsf lcd_e
nop
bcf lcd_e
nop
return
;
lcd_send_4_bit
; Data i W-reg bit 4-7 överförs till LCD_PORT bit 4-7.
; LCD_PORT bit 0-3 lämnas som de är.
;
banksel lcd_port
movwf lcd_tmp1 ; Spara LCD data...
movlw b'00001111' ; "Mask" för LCD_PORT
andwf lcd_port, w ; Läs av LCD_PORT bit 0-3
iorwf lcd_tmp1, w ; Kombinare med LCD data bit 4-7
movwf lcd_port ; Skriv tillbaka till LCD_PORT.
call lcd_toggle_e ; Och överför till LCD.
return
;
lcd_send_cmd
; Data i W överförs till LCD som ett "kommando".
;
banksel lcd_port
bcf LCD_RS ; RS = "0" för kommando.
call lcd_send_byte ; Skicka
call delay_5ms ; Vänta 5 ms efter ett kommando.
return
;
lcd_send_data
; Data i W överförs till LCD som "data".
;
banksel lcd_port
bsf LCD_RS ; RS = "1" för data
call lcd_send_byte ; Skicka
call delay_100us ; Ge LCD'n tid att bearbeta datat.
return
;
lcd_send_byte
; Data i W överförs till LCD som två 4-bitars bitar.
;
movwf lcd_tmp2 ; Spara W tillfälligt
movlw B'11110000' ; Mask för bit 4-7
andwf lcd_tmp2, w ; Nolla bit 0-3
call lcd_send_4_bit ; Skicka bit 4-7
swapf lcd_tmp2, f ; Byt plats på 0-3 <-> 4-7
movlw B'11110000' ; Mask för bit 4-7 (nu 0-3 !!)
andwf lcd_tmp2, w ; Nolla bit 0-3 (nu 4-7 !!)
call lcd_send_4_bit ; Skicka bit 4-7 (nu 0-3 !!)
return
;
lcd_send_text
; Sänd en fast text till LCD.
; När rutinen anropas ska EEADR och EEADRH vara initierade
; med adressen i flash till text-bufferten. T.ex genom det
; lcd_text macro som finns i detta program.
; Beräkningen av rad/kol -> LCD-pos är just nu anpassad
; till 16x2 LCD'er. Får justeras för att passa andra...
;
; Läs första positionen i texten ("LCD-rad")
;
call read_flash
movwf lcd_tmp1 ; Lagra (radnummer på LCD)
;
; Hämta nästa pos i textraden (pos på LCD raden...)
;
call inc_eeadr
call read_flash
movwf lcd_tmp2 ; Lagra (position på raden på LCD)
;
; Justering av rad/pos väden
;
decf lcd_tmp1, f ; Rad 1-2 => 0-1
bcf status, c
rrf lcd_tmp1, f
rrf lcd_tmp1, f
rrf lcd_tmp1, f ; Nu är lcd_tmp1 h'00' eller h'40'...
decf lcd_tmp2, f ; Pos 1-40 => 0-39
;
; Nu är rad och pos färdiga att addera ihop och skicka till LCD'n...
;
movlw h'80' ; Bas-kommandot för LCD-position.
addwf lcd_tmp1, w ; Lägg till rad (h'00' eller h'40')
addwf lcd_tmp2, w ; Lägg till pos.
call lcd_send_cmd ; Skicka kommandot (i W-reg)
;
; Nu läser vi resten av texten fram till h'00' och skickar
; till LCD'n.
;
send_text_loop
;
; Läs nästa position ("LCD-text") och skicka.
; Avsluta om datat/tecknet = h'00'
;
call inc_eeadr
call read_flash
btfsc status, z ; Var det h'00' (slut på text) ?
goto send_text_end ; Ja, avsluta.
; Nej, fortsätt...
call lcd_send_data ; Skicka tecken med data i W-reg.
goto send_text_loop ; Om igen...
;
send_text_end
; Slut på text...
;
return
;
read_flash
;
; Läs en byte från flash
; EEADR och EEADRH ska redan vara initierade.
;
banksel eecon1
bsf eecon1, eepgd ; Läs från flash...
bsf eecon1, rd ; Sätt läs-flaggan...
nop ; Vänta på att läsning
nop ; ska gå klart...
banksel eedat
movf eedat, w ; Nu har vi värdet i W-reg.
return
;
; Räkna fram eeadr/eeadrh till nästa position
;
inc_eeadr
banksel eeadr
incf eeadrh, f ; öka först eeadrh
incfsz eeadr, f ; öka eeadr, = 0 ?
decf eeadrh, f ; eeadr <> 0, återställ eeadrh...
return
;
;
;**********************************************************************
; Diverse delay rutiner.
; Alla delay rutiner generade med kodgeneratorn här :
; http://www.piclist.com/techref/piclist/codegen/delay.htm
; OBS generatade för 4 Mhz processorhastighet.
;
DLY_VAR UDATA_SHR
d1 RES 1
d2 RES 1
d3 RES 1
;
DLY_CODE CODE
;----------------------------------------------------
; Delay = 0.001 seconds
; Clock frequency = 4 MHz
; korrekt
; Actual delay = 0.001 seconds = 10000 cycles
; Error = 0 %
;----------------------------------------------------
Delay_1ms
;993 cycles
movlw 0xC6
movwf d1
movlw 0x01
movwf d2
Delay_1ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_1ms_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
;----------------------------------------------------
; Delay = 1 sekund
; Clock frequency = 4 MHz
; korrekt
; Actual delay = 1 seconds = 1000000 cycles
; Error = 0 %
;----------------------------------------------------
delay_1s
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_1s_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_1s_0
goto $+1
nop
return
;----------------------------------------------------
; Delay 5 millesekunder
; Delay = 0.005 seconds
; Clock frequency = 4 MHz
; korrekt
; Actual delay = 0.005 seconds = 500000 cycles
; Error = 0 %
;----------------------------------------------------
delay_5ms
movlw 0xE7
movwf d1
movlw 0x04
movwf d2
Delay_5ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_5ms_0
goto $+1
return
;-------------------------------------------------
; Delay 100 mikrosekunder
; Delay = 0.0001 seconds
; Clock frequency = 4 MHz
; korrekt
; Actual delay = 0.0001 seconds = 100 cycles
; Error = 0 %
;-------------------------------------------------
delay_100us
movlw 0x21
movwf d1
Delay_100us_0
decfsz d1, f
goto Delay_100us_0
return
;--------------------------------------------------
; Delay 40 millisekunder
; Delay = 0.04 seconds
; Clock frequency = 4 MHz
; korrekt
; Actual delay = 0.04 seconds = 40000 cycles
; Error = 0 %
;-------------------------------------------------
Delay_40ms
;39993 cycles
movlw 0x3E
movwf d1
movlw 0x20
movwf d2
Delay_40ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_40ms_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
;--------------------------------------------------
BIN2BCD
; Rutin för att göra om från binärt till tre bitar
; med hundratal, tiotal och ental.
;---------------------
;in: BIN
;out huns. tens, ones
;uses ADD-3 algoerthm
movlw 8
movwf count
clrf huns
clrf tens
clrf ones
BCDADD3
movlw 5
subwf huns, 0
btfsc STATUS, C
CALL ADD3HUNS
movlw 5
subwf tens, 0
btfsc STATUS, C
CALL ADD3TENS
movlw 5
subwf ones, 0
btfsc STATUS, C
CALL ADD3ONES
decf count, 1
bcf STATUS, C
rlf BIN, 1
rlf ones, 1
btfsc ones,4 ;
CALL CARRYONES
rlf tens, 1
btfsc tens,4 ;
CALL CARRYTENS
rlf huns,1
bcf STATUS, C
movf count, 0
btfss STATUS, Z
GOTO BCDADD3
movf huns, 0 ; add ASCII Offset
addlw h'30'
movwf huns
movf tens, 0 ; add ASCII Offset
addlw h'30'
movwf tens
movf ones, 0 ; add ASCII Offset
addlw h'30'
movwf ones
RETURN
ADD3HUNS
movlw 3
addwf huns,1
RETURN
ADD3TENS
movlw 3
addwf tens,1
RETURN
ADD3ONES
movlw 3
addwf ones,1
RETURN
CARRYONES
bcf ones, 4
bsf STATUS, C
RETURN
CARRYTENS
bcf tens, 4
bsf STATUS, C
RETURN
;**********************************************************************
LCD_texts CODE
; Fasta texter för LCDn.
; Två första värderna i varje text är rad (1,2,3 eller 4)
; och position (1-40). Resten är text fram till h'00'.
;
lcd_text1 data d'1', d'1', ' ',' ',' ','%',' ',' ',' ',' ',' ', h'00'
lcd_text2 data d'1', d'10', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', ' ', h'00'
;*********************************************************************
end
Re: PIC -> PIC via RS232 nya frågor..
Uppenbart har du något fel i din konvertering mellan det mottagna och det presenterade.
Gör ett litet test-program där du i princip enbart har din konverteringsrutin som du kan
köra med fasta/hårdkodade värden. Sen så kör du detta i MPLAB/SIM och studerar
vad som händer. Sannolikt händer inte det du tror. Jag har inte kollat koden, det
finns ingen större anledning innan du har felsökt lite själv med hjälp av
tillgängliga verktyg och ändå kört fast.
Jag menar, har du ens verifierat att USART'en i din mottagnade PIC över huvudtaget
levererar samma tecken ut som du sänder från den första PIC'en?
Eller har du enbart "verifierat" via det som visas på LCD'n?
Det saknas generellt information om vilken felsökning du redan har gjort.
De delar som är verifierade behöver vi ju inte kolla en gång till på, eller i
alla fall inte börja att kolla på.
> ; Skapad av: Morgan
Inte för att det har någon jättestor betydelse, men en stor del av koden är "skapad" av mig.
Gör ett litet test-program där du i princip enbart har din konverteringsrutin som du kan
köra med fasta/hårdkodade värden. Sen så kör du detta i MPLAB/SIM och studerar
vad som händer. Sannolikt händer inte det du tror. Jag har inte kollat koden, det
finns ingen större anledning innan du har felsökt lite själv med hjälp av
tillgängliga verktyg och ändå kört fast.
Jag menar, har du ens verifierat att USART'en i din mottagnade PIC över huvudtaget
levererar samma tecken ut som du sänder från den första PIC'en?
Eller har du enbart "verifierat" via det som visas på LCD'n?
Det saknas generellt information om vilken felsökning du redan har gjort.
De delar som är verifierade behöver vi ju inte kolla en gång till på, eller i
alla fall inte börja att kolla på.

> ; Skapad av: Morgan
Inte för att det har någon jättestor betydelse, men en stor del av koden är "skapad" av mig.
Re: PIC -> PIC via RS232 nya frågor..
Vad det gäller koden så här du såklart helt rätt i att det mesta är ditt verk! Och det skriver jag ju i ett av mina inlägg i tråden.
Varför jag valt att skriva mitt namn nu är att jag ändrat en del, och jag vill givetvis inte att någon annan ska få skit för mina fel!
Utskriftsrutinen och omvandlingen av en byte till tre byte med vardera hundra, tio och ental fungerar perfekt. Har, som syns i koden, testat med fasta värden i den variabel som normalt skrivs till efter mottagning, och då blir utskriften rätt.

Utskriftsrutinen och omvandlingen av en byte till tre byte med vardera hundra, tio och ental fungerar perfekt. Har, som syns i koden, testat med fasta värden i den variabel som normalt skrivs till efter mottagning, och då blir utskriften rätt.
Re: PIC -> PIC via RS232 nya frågor..
Va bra ! 
Då kan vi alltså vara ganska säkra på att konverteringen och visningen på
LCD'n fungerar OK, bara de har korrekta invärden att jobba med, så att säga.
Har du på något sätt verifierat vad som kommer från USART'en i PIC nr 2?
Du kan t.ex loopa det du mottar till sänd-delen på PIC nr 2 och skicka det
till samma terminalfönster där du verifierade att PIC nr 1 sänder korrekt.
Om jag inte minns fel så har 16F628A resp 16F690 USART av olika "generation".
AUSART resp EUSART med en del skillnader. Jag är inte säker på att man kan
plocka init koden rakt av mellan dom, därmed inte sagt att du har gjort det,
så klart, bara en notering...
Det "luktar" baud-rate fel...

Då kan vi alltså vara ganska säkra på att konverteringen och visningen på
LCD'n fungerar OK, bara de har korrekta invärden att jobba med, så att säga.
Har du på något sätt verifierat vad som kommer från USART'en i PIC nr 2?
Du kan t.ex loopa det du mottar till sänd-delen på PIC nr 2 och skicka det
till samma terminalfönster där du verifierade att PIC nr 1 sänder korrekt.
Om jag inte minns fel så har 16F628A resp 16F690 USART av olika "generation".
AUSART resp EUSART med en del skillnader. Jag är inte säker på att man kan
plocka init koden rakt av mellan dom, därmed inte sagt att du har gjort det,
så klart, bara en notering...

Det "luktar" baud-rate fel...
Re: PIC -> PIC via RS232 nya frågor..
Det där får jag ju helt klart testa. Att jag inte tänkte på det!! Att loopa det som kommer in alltså.
Då serj ag ju rätt snart vad som kommer in -förhoppningsvis-.
En annan fråga när det gäller terminalprogram i allmänhet, om det nu går att fråga allmänt om det..
Första gången jag testade programmet i 16F628A:an så var det inställt för 9600 baud och detsamma var porten inställd på i enhetshanteraren. Så långt allt bra, men så ändrade jag baudrate i sändaren för att det skulle passa med inställningen som var i de trådlösa modulerna, vilket är 19200 baud.
För att det då skulle fungera i PC:n så ändrade jag i terminalprogrammet till 19200 baud, och då fungerade mottagningen som det var tänkt. Men kollar jag i enhetshanteraren så spelar det ingen roll om jag sätter 9600 eller 19200 baud där. Det blir rätt i terminalprogrammet i alla fall..
Så frågan är, överrider inställningen i terminalprogrammet de inställningar som är gjorda i enhetshanteraren, eller hur fungerar det generellt?
Då serj ag ju rätt snart vad som kommer in -förhoppningsvis-.
En annan fråga när det gäller terminalprogram i allmänhet, om det nu går att fråga allmänt om det..
Första gången jag testade programmet i 16F628A:an så var det inställt för 9600 baud och detsamma var porten inställd på i enhetshanteraren. Så långt allt bra, men så ändrade jag baudrate i sändaren för att det skulle passa med inställningen som var i de trådlösa modulerna, vilket är 19200 baud.
För att det då skulle fungera i PC:n så ändrade jag i terminalprogrammet till 19200 baud, och då fungerade mottagningen som det var tänkt. Men kollar jag i enhetshanteraren så spelar det ingen roll om jag sätter 9600 eller 19200 baud där. Det blir rätt i terminalprogrammet i alla fall..
Så frågan är, överrider inställningen i terminalprogrammet de inställningar som är gjorda i enhetshanteraren, eller hur fungerar det generellt?