[BASCOM][M16]Przesylanie wielu zmiennych WORD via UART.
[BASCOM][M16]Przesylanie wielu zmiennych WORD via UART.
Witam,złożyłem sobie pewne urządzenie które świetnie działa ale nie umiem go teraz oprogramować :p Problem jest następujący :
Potrzebuje wysłać kilka danych z przetwornika ADC poprzez UART do drugiej części kontrolera tj zmienne typu WORD.Wszystko jest niby ok kiedy wysyłam jedną zmienna, czyli rozbijam ją na bajty potem wrzucam na UTXC następnie odbieram łącze znowu w WORD i wyświetlam.Problem pojawia się kiedy robię to z dwoma zmiennymi-są kompletne przekłamania.Domyśliłem się że brakuje synchronizacji, tzn kiedy nadchodzi który bajtNiestety nie potrafię jej zrealizować gdyż nie wiem jak odróżnić znak "synchronizacji" od danych.Załóżmy że tym znakiem będzie $ jego kod to 036-i właśnie jak odróżnić że kod 36 nie jest daną tylko znakiem $??
Proszę chociaż o jakieś teoretyczne nakierowanie, jak to napisać.
Pozdrawiam Mictronic!
Potrzebuje wysłać kilka danych z przetwornika ADC poprzez UART do drugiej części kontrolera tj zmienne typu WORD.Wszystko jest niby ok kiedy wysyłam jedną zmienna, czyli rozbijam ją na bajty potem wrzucam na UTXC następnie odbieram łącze znowu w WORD i wyświetlam.Problem pojawia się kiedy robię to z dwoma zmiennymi-są kompletne przekłamania.Domyśliłem się że brakuje synchronizacji, tzn kiedy nadchodzi który bajtNiestety nie potrafię jej zrealizować gdyż nie wiem jak odróżnić znak "synchronizacji" od danych.Załóżmy że tym znakiem będzie $ jego kod to 036-i właśnie jak odróżnić że kod 36 nie jest daną tylko znakiem $??
Proszę chociaż o jakieś teoretyczne nakierowanie, jak to napisać.
Pozdrawiam Mictronic!
No niewiem np tak ... :
Odbiornik:
Nadajnik:
A ze uart wysyła pojedynczo znaki to wiem ale co będzie jeśli bajt ze zmiennej word będzie miał ta sama wartość co znak synchronizacji..?Moze wykrywać ilość wysłanych bitów,tylko jak?
Pozdrawiam Mictronic!
Odbiornik:
Kod: Zaznacz cały
$regfile = "m16def.dat"
$crystal = 12000000
$baud = 19200
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Disconnect , Compare B Pwm = Clear Down , Prescale = 1
Pwm1b = 100
Enable Interrupts
Enable Urxc
On Urxc Uartrx
Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
Config Lcd = 20 * 4
'Open "comd.7:9600,7,E,1" For Input As #1
Cls
Cursor Off
Dim A(4) As Byte
Dim A2(2) As Word
Dim Licznik As Byte
Licznik = 1
Do
A2(1) = Makeint(a(2) , A(1))
A2(2) = Makeint(a(4) , A(3))
Locate 1 , 1
Lcd A2(1)
Locate 2 , 1
Lcd A2(2)
Loop
Uartrx:
Incr Licznik
Udr = A(licznik)
If Licznik = 4 Then Licnzik = 1
ReturnKod: Zaznacz cały
$regfile = "m16def.dat"
$crystal = 7680000
$baud = 19200
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Disconnect , Prescale = 1
Config Adc = Single , Prescaler = Auto , Reference = Off
Start Adc
Enable Interrupts
Enable Utxc
Config Portd.7 = Output
Dim A As Word
Dim B As Word
Do
A = Getadc(1)
B = Getadc(2)
Udr = Low(a)
Udr = High(a)
Udr = Low(b)
Udr = High(b)
LoopPozdrawiam Mictronic!
Ahaaa ok dobra dobra pokombinujemy -nie zwróciłem na to uwagi jak testowałem.
Zaś ja ciągle myślałem ze jak wysyłam liczbę to od razu cały bajt a zakresie od 0 do 255 a nie ze poklei ,każdą cyferkę jak mówisz.
Sprawdzę to i dam później znać!
[ Dodano: 2009-06-22, 01:00 ]
Nie, jednak jest tak jak mówiłem.Gdy ładuje do rejestru UDR liczbę 123 to odbieram obrazu 123 a nie 1,2,3 :/
Wysyłam
Odbieram
Kto mi pomoże
?
Zaś ja ciągle myślałem ze jak wysyłam liczbę to od razu cały bajt a zakresie od 0 do 255 a nie ze poklei ,każdą cyferkę jak mówisz.
Sprawdzę to i dam później znać!
[ Dodano: 2009-06-22, 01:00 ]
Nie, jednak jest tak jak mówiłem.Gdy ładuje do rejestru UDR liczbę 123 to odbieram obrazu 123 a nie 1,2,3 :/
Wysyłam
Kod: Zaznacz cały
a=123
udr=a
wait 1
Kod: Zaznacz cały
a=udr
lcd a
Podejrzewam, że nie jest Ci potrzebny pełny zakres liczb (0-65535), tylko 0-1023.
Ja poradziłbym sobie z Twoim problemem tak:
-biorę siedem bitów niższego bajtu, jako ósmy (MSB) daję jeden -> wysyłam
-przesuwam bity wyższego bajtu w lewo i dorzucam na koniec "zapomniany" bit ->wysyłam
Dlaczego?
Bajty rozróżnisz po tym, czy zaczyna się od 0(wyższy) czy 1(niższy).
Mam nadzieję że zrozumiałem twój problem, a ty moje rozwiązanie
Ja poradziłbym sobie z Twoim problemem tak:
-biorę siedem bitów niższego bajtu, jako ósmy (MSB) daję jeden -> wysyłam
-przesuwam bity wyższego bajtu w lewo i dorzucam na koniec "zapomniany" bit ->wysyłam
Dlaczego?
Bajty rozróżnisz po tym, czy zaczyna się od 0(wyższy) czy 1(niższy).
Mam nadzieję że zrozumiałem twój problem, a ty moje rozwiązanie
Pomysł fajny,ale jeszcze nie wiem jakbym to napisał,może coś prostszego.To przecież nie może być takie trudne jak inni wysyłają wiele zmiennych w swoich programach?MiW pisze:Podejrzewam, że nie jest Ci potrzebny pełny zakres liczb (0-65535), tylko 0-1023.
Ja poradziłbym sobie z Twoim problemem tak:
-biorę siedem bitów niższego bajtu, jako ósmy (MSB) daję jeden -> wysyłam
-przesuwam bity wyższego bajtu w lewo i dorzucam na koniec "zapomniany" bit ->wysyłam
Dlaczego?
Bajty rozróżnisz po tym, czy zaczyna się od 0(wyższy) czy 1(niższy).
Mam nadzieję że zrozumiałem twój problem, a ty moje rozwiązanie
Spróbuje jeszcze bardziej przedstawić co próbuje osiągnąć.Mam jakieś urządzenie które mierzy:
Prad
Napięcie
Obroty silnika
Generuje PWM
Otrzymuje polecenia co jeszcze włączyć od drugiego urządzenia.
Chce wysłać:
Kod: Zaznacz cały
| PradLSB,PradMSB | NapiecieLSB,NapiecieMSB | RpmLSB,RpmMSB | Pwm(od biedy może być jeden bajt) | AdresPolecenia+Dane(2bajty) |Kod: Zaznacz cały
$ PradLSB$PradMSB$NapiecieLSB$NapiecieMSB$RpmLSB$RpmMSB$PWM$
$AdresPolecenia$Dane$Ktoś ma pomysł jak to zrobić?
Moze inaczej zupełnie,bo pomysł z bitami-hmm jeszcze przemyślę.
Witam zrób to na zasadzie tablicy i użyj print bin
w tedy cała tablica jest wysyłana i bez błędów dodaj bufor do UART -ów
może pokaże na przykładzie moim
dobra teraz część odbiorcza :
[ Dodano: 2009-06-22, 20:51 ]
Mój kod działa na 95% na początku jest coś na zasadzie synchronizacji która jest robiona tylko przy starcie programu. Zdarza się ze zgubi jakąś paczkę danych więc będę musiał dodać synchronizacje gdzie jeszcze w trakcje wykonywania programu ale coś mi brak weny twórczej ostatnio.
Zobacz w helpie na:
CONFIG SERIALIN | SERIALIN1 | SERIALIN2 | SERIALIN3 = BUFFERED , SIZE = size [, BYTEMATCH=ALL|BYTE|NONE] [,CTS=pin, RTS=pin , Threshold_full=num , Threshold_empty=num ]
bytematch - może cię dodatkowo zainteresować.
[ Dodano: 2009-06-22, 21:20 ]
Dodatkowo ściągnij sobie ze strony pololu http://www.pololu.com/docs/0J23 mały programik który wysyła paczki bytów idealny do testowania podczas pisania programów.
w tedy cała tablica jest wysyłana i bez błędów dodaj bufor do UART -ów
może pokaże na przykładzie moim
Kod: Zaznacz cały
Nadajnik:
'Sterwoanie przez port szeregowy
'ATmega 128 kwarc 16 MHZ
'by Pawel L. (pikczu)
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'fusy nie zmieniać
$prog &HFF , &HFF , &H99 , &HFF
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'$sim
$regfile = "M128def.dat"
$crystal = 16000000 'Kwarc
$baud = 9600 'predkosc transmisji
'-----------konfiguracjia portów -----------------------------------------------
Config Portd = Input
Config Portb = Output
Portd = 255
Config Portf = Input
'-------------deklaracia zmiennych----------------------------------------------
Dim Flag1 As Bit
Dim Flag2 As Bit
Dim Flag3 As Bit
Dim Osy As Byte 'os y serwa
Dim Osx As Byte 'os x serwa
Dim Os_y As Byte 'Trymowanie Y
Dim Os_x As Byte 'Trymowanie X
Dim Channel As Byte 'Kanal ADC
Dim Przetwornik As Integer 'Wartosc pobrana z przetwornika
Dim Serial_tx(6) As Byte 'tablica do wysłania
Dim Synchro As Byte 'Sychronizacja tylko na poczatku programu
'-------------konfiguracjia przetwornika A/C------------------------------------
'Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Portc.7 , Rs = Portc.6
Config Timer1 = Timer , Prescale = 256
Config Adc = Single , Prescaler = Auto , Reference = Internal
Config Serialout = Buffered , Size = 6
'-------------------- -----------------------------------------------------------
Enable Interrupts
Enable Timer1
Enable Utxc
Start Adc
Echo On
Timer1 = 3036
'*****************************-Synchro-*****************************************
Do
Lcd "czekam na synchro"
Synchro = Waitkey() 'czekaj na 13 ascii
Loop Until Synchro = 13
'************************-end of synchro-***************************************
Flag1 = 0
Flag2 = 0
On Timer1 Dela_y
'**********************'Main loop'**********************************************
Do
Gosub Pomiar:
Gosub Send:
Loop
'*************************'End of Main loop'************************************
'*******************************************************************************
'**************************-Sub's-**********************************************
Pomiar:
For Channel = 0 To 1
Przetwornik = 0
Przetwornik = Getadc(channel) 'pierwszy i drugi pomiar pomijamy
Przetwornik = Getadc(channel)
Przetwornik = 0
Przetwornik = Przetwornik + Getadc(channel) 'pomiar
Przetwornik = Przetwornik + Getadc(channel)
Przetwornik = Przetwornik + Getadc(channel)
Shift Przetwornik , Right , 4
Select Case Channel
Case 0 :
If Osy <> Przetwornik Then
Osy = Przetwornik
Flag1 = 1
Serial_tx(1) , 1 = Osy
End If
Case 1 :
If Osx <> Przetwornik Then
Osx = Przetwornik
Flag2 = 1
Serial_tx(2) , 1 = Osx
End If
End Select
Next Channel
Return
'****************************-Send-*********************************************
Send:
If Flag1 = 1 Or Flag2 = 1 Then
Printbin Serial_tx(1) ; 6
Flag1 = 0
Flag2 = 0
End If
Return
'-----------------------------------------------------------------------------
Dela_y:
Timer1 = 3036 '64286= 20ms'3036=1s
Toggle Portb.7
Return
Enddobra teraz część odbiorcza :
Kod: Zaznacz cały
'---CZĘŚĆ ODBIORCZA-------------------------------------------------------------
'Sterwoanie przez port szeregowy
'ATmega 128 kwarc 16 Mhz
'by Pawel L. (pikczu)
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'Fusy nie zmieniac
$prog &HFF , &HFF , &H99 , &HFF
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$regfile = "M128def.dat"
$crystal = 16000000 'Kwarc
$baud = 9600
'-----------konfiguracjia portu B i C jako wyjscie -----------------------------
Config Portb = Output
Config Portc = Output
'-------------deklaracia zmiennych----------------------------------------------
Dim Flag1 As Bit
Dim Flag2 As Bit
Dim Osy As Byte
Dim Osx As Byte
Dim Channel As Byte
Dim Value As Byte
Dim Serial_flag As Byte
Dim Serial_rx(6) As Byte
'-----------------konfiguracjia serv--------------------------------------------
Config Serialin = Buffered , Size = 60
Config Servos = 2 , Servo1 = Portb.7 , Servo2 = Portb.6 , Reload = 10
Config Timer1 = Timer , Prescale = 256
Enable Interrupts
Enable Timer1
Enable Urxc
Servo(1) = 40 'wartosc poczatkowa
Servo(2) = 40 'wartosc poczatkowa
Flag1 = 0
Flag2 = 0
Cursor Off
'-------------------------------------------------------------------------------
Cls
Lcd "start" 'drukuj na lcd start
Wait 1 'czekaj 1
Cls 'czysc ekran
Lcd "servo test" 'drukuj na lcd
Wait 1 'czekaj
Cls
Lcd "servo max" 'drukuj na lcd
Servo(1) = 180 'ustaw servo na max wartosc dobrana doswiadczalnie
Servo(2) = 180
Wait 1 'czekaj
Cls
Servo(1) = 40 'servo na min
Servo(2) = 40
Lcd "servo MIN"
Wait 1
Cls
Lcd "sending synchro"
Wait 1
Cls
Print Chr(13);
Lcd "System on"
Wait 1
Cls
'-------------------------------------------------------------------------------
Echo On
On Timer1 Dela_y
Do
Serial_flag = Ischarwaiting()
Portb.0 = Serial_flag
If Serial_flag = 1 Then
Inputbin Serial_rx(1) , 6
End If
Osy = Serial_rx(1) , 1
Osx = Serial_rx(2) , 1
Servo(1) = Osy
Servo(2) = Osx
If Serial_flag = 1 Then
If Flag1 = 1 Then
Cls
Lcd "osy " ; Osy
Locate 1 , 10
Lcd "osx " ; Osx
Flag1 = 0
End If
Else
Flag1 = 1
End If
Loop
End
'-------------------------------------------------------------------------------
Dela_y:
Timer1 = 3036 'dioda miga co 1 sek
Toggle Portb.5
Return[ Dodano: 2009-06-22, 20:51 ]
Mój kod działa na 95% na początku jest coś na zasadzie synchronizacji która jest robiona tylko przy starcie programu. Zdarza się ze zgubi jakąś paczkę danych więc będę musiał dodać synchronizacje gdzie jeszcze w trakcje wykonywania programu ale coś mi brak weny twórczej ostatnio.
Zobacz w helpie na:
CONFIG SERIALIN | SERIALIN1 | SERIALIN2 | SERIALIN3 = BUFFERED , SIZE = size [, BYTEMATCH=ALL|BYTE|NONE] [,CTS=pin, RTS=pin , Threshold_full=num , Threshold_empty=num ]
bytematch - może cię dodatkowo zainteresować.
[ Dodano: 2009-06-22, 21:20 ]
Dodatkowo ściągnij sobie ze strony pololu http://www.pololu.com/docs/0J23 mały programik który wysyła paczki bytów idealny do testowania podczas pisania programów.
Ostatnio zmieniony 25 lip 2009, 0:10 przez Pikczu, łącznie zmieniany 1 raz.
Proponuje zrobić to podobnie, jak sterowanie LCD przez magistrale 4bitową.
Przesłane po kolei 4 bajty o takich samych nagłówkach zostaną scalone w liczbę 2 bajtową i sklasyfikowane po nagłówku jako określające pierwszy parametr.
4 młodsze bity będą przenosić dane, a 4 starsze będą pokazywać, o jaką część ramki chodzi.
Oto przykład:
Po tym należy wysłać następną zmienną, ale nadając jej nagłówek 0010, a następnej 0011, i tak dalej...
Oczywiście zmienne 12 bitowe można przesyłać w 3 częściach, a jeśli potrzeba tylko 8 bitów, to w 2 częściach.
Po zakończeniu transmisji wszystkich zmiennych należy wysłać znak synchronizacji np. 1111 0101.
Zadaniem odbiornika było by oczekiwanie na x bajtów o wartościach pomiędzy jednym, a drugim końcem zakresu (dla 0001 xxxx był by to zakres od 16 do 31). Następnie odpowiednie ich scalenie (np. w 2 bajty).
Jeśli nie zostanie odebranych tyle bajtów, ile trzeba, to trzeba wyczyścić zmienne tymczasowe i wywołać przejście do części oczekiwania na synchronizację.
Po odebraniu wszystkich bajtów należy sprawdzić, czy żaden nie zginął, czyli czy bajt synchronizacji występuje dokładnie w tym miejscu co trzeba, a jeśli tak jest, to można przekazać te zmienne dalej programowi.
Przesłane po kolei 4 bajty o takich samych nagłówkach zostaną scalone w liczbę 2 bajtową i sklasyfikowane po nagłówku jako określające pierwszy parametr.
4 młodsze bity będą przenosić dane, a 4 starsze będą pokazywać, o jaką część ramki chodzi.
Oto przykład:
Kod: Zaznacz cały
0001 abcd - 1/4 danych
0001 efgh
0001 ijkl
0001 mnop
-> wynik: LSB: abcdefgh MSB: ijklmnop Oczywiście zmienne 12 bitowe można przesyłać w 3 częściach, a jeśli potrzeba tylko 8 bitów, to w 2 częściach.
Po zakończeniu transmisji wszystkich zmiennych należy wysłać znak synchronizacji np. 1111 0101.
Zadaniem odbiornika było by oczekiwanie na x bajtów o wartościach pomiędzy jednym, a drugim końcem zakresu (dla 0001 xxxx był by to zakres od 16 do 31). Następnie odpowiednie ich scalenie (np. w 2 bajty).
Jeśli nie zostanie odebranych tyle bajtów, ile trzeba, to trzeba wyczyścić zmienne tymczasowe i wywołać przejście do części oczekiwania na synchronizację.
Po odebraniu wszystkich bajtów należy sprawdzić, czy żaden nie zginął, czyli czy bajt synchronizacji występuje dokładnie w tym miejscu co trzeba, a jeśli tak jest, to można przekazać te zmienne dalej programowi.