Har lite problem med att sända över lite info genom UARTen på en PIC16F877A med en 20Mhz kristall (med 33pF kondingar)...
Till att börja med så har jag programmerat PICen med en HEX fil som är genererad av programmet "ldmicro" (http://cq.cx/ladder.pl)
PICen är sedan kopplad via en MAX232E, (har använt kondingar på 1uF precis som det står i databladet för just den modellen) sedan vidare till en PC där jag kör "Indigo Terminal".
PICen är just nu programmerad så att den ska sända över ett "A" om och om igen (med 500ms mellanrum) det jag får upp i terminalen ser dock inte ut som ett "A" utan såhär:
I "ldmicro" så är det inställt på 2400 och även på 20Mhz kristall, fast är ju å andra sidan inte hundra på att den verkligen sänder i just 2400.
Hur kollar jag det på enklaste sätt? (Är ny på just denna biten som ni kanske har märkt )
Just detta att inte själv ha koll på hur ett program ställer saker och ting kan störa mig något så fruktansvärd! Detta är just anledningen till att jag anser att man ska börja med ASM när man är helt grön.
Nåväl, efter vad jag kan se kommer det något som PC'n uppfattar som 3 tecken, står den på 2400 baud är baudraten från PIC'en alltså runt 1200 baud eller så.
Testa att ändra baudraten på PC'n steg för steg neråt till det kommer en massa 'A'
Har nu kopplat in en helt färdig MAX232 modul mellan PIC och PC för att dubbelkolla så att den biten lirar, och får precis samma tecken som med den andra...
Provade även att sänka och höja baudraten om 10 steg i taget i terminalen, fick då inte helt oväntat andra tecken, vid t.ex. 1200 baud såg det ut så här:
Olika språk är olika omständliga men vilket man än väljer så ska man helst behärska det.
Ex. samma sak kan göras i PICBasic:
SERIN 0, N2400, ["A"]
Som i asm:
buffer = 31 ; String storage.
B2400 = 30 ; Bit delay for 2400 baud.
B1200 = 62 ; Bit delay for 1200 baud.
B600 = 126 ; Bit delay for 600 baud.
B300 = 255 ; Bit delay for 300 baud.
filt_lo = '0' ; Set filter for ASCII
filt_hi = '9' ; chars representing 0-9.
org 8
baud ds 1 ; Baud rate.
pin ds 1 ; Pin number (0-7).
port ds 1 ; Port number (0-2).
bytes ds 1 ; Number of bytes to receive.
temp1 ds 1 ; Temporary counter for Serin.
temp2 ds 1 ; Temporary counter for Serin.
temp3 ds 1 ; Temporary counter for delay.
ser_fl ds 1 ; Flags for serin switches.
polarity = ser_fl.0 ; Polarity: 0=true, 1=inverted.
filter = ser_fl.1 ; Range filter: 0=off, 1=on.
filt_1st = ser_fl.2 ; 1st filter byte passed?: 0=no, 1=yes.
aux = ser_fl.3 ; Temporary flag for filter comparisons.
; Device data and reset vector
device pic16c55,xt_osc,wdt_off,protect_off
reset start
org 0
; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b).
Pinz jmp pc+w
retw 1,2,4,8,16,32,64,128
; Subroutine used by Serin to get a bit and delay for a number of loops
; set by temp3. Jumping into get_bit:loop provides the delay, but ignores the
; input bit.
get_bit mov fsr,port ; Point to port.
mov w,indirect ; IF Polarity = 0 THEN w = Port
snb Polarity ; ELSE w = NOT Port
mov w,/indirect
AND w,pin
snz ; IF w AND pin THEN carry = 1
clc ; ELSE carry = 0.
sz
stc
mov fsr,temp1 ; Point to buffer location.
rr indirect ; Rotate carry into msb of data byte.
:loop jmp $+1 ; Two-cycle nops.
jmp $+1
jmp $+1
jmp $+1
jmp $+1
djnz temp3,:loop
ret
; Main program start. Receives a single byte of data, filtered for numeric
; characters, and displays the data bits on LEDs connected to port RB.
start mov !ra, #15 ; All inputs.
mov !rb,#0 ; All outputs for LEDs.
clr rc ; Clear the LEDs.
clr ser_fl ; Clear serial flags.
mov bytes,#1 ; Receive 1 byte
clrb filter ; not filtered
setb polarity ; inverted polarity
mov baud,#B2400 ; at 2400 baud
mov pin,#2 ; via pin 2
mov port,#0 ; of port ra.
CALL SERIN ; Receive the data.
mov rb,buffer-1 ; Move byte to LEDs on RB.
jmp start ; Endless loop
; Body of the Serin routine. Expects the baud constant in baud, number of
; bytes to receive in bytes, the I/O port (0-2 for RA through RC) in port,
; the pin number (0-7) in pin, and the flag settings in ser_fl
SERIN clr buffer ; Clear buffer counter.
clrb filt_1st
ADD port,#RA ; Add offset for port RA.
mov w,pin
CALL Pinz ; Get bit mask from the table.
mov pin,w ; Put the mask into pin.
mov temp1,#buffer-1 ; Pointer for first data address.
:poll mov fsr,port
mov w,indirect ; IF Polarity = 0 THEN w = Port
snb Polarity ; ELSE w = NOT Port
mov w,/indirect
AND w,pin ; IF pin = 0 THEN receive data
jnz :poll ; ELSE poll
clc
mov w,>>baud ; LET temp3 = baud/2
mov temp3,w ; Set up 1/2 bit time delay.
CALL get_bit:loop ; Jump into delay of get_bit.
mov temp3,baud ; Set up full bit time delay.
CALL get_bit:loop ; Jump into delay of get_bit.
mov temp2,#8 ; Eight data bits.
:rcv mov temp3,baud ; Set up bit delay.
CALL get_bit ; Get the next data bit.
djnz temp2,:rcv ; Eight bits received?
:done mov temp3,baud ; Set up bit delay.
CALL get_bit:loop ; Wait for stop bit.
jnb filter,:skip ; IF filter=0 (off) THEN :skip
clrb aux ; LET aux = 0.
csae indirect,#filt_lo ; IF byte < filt_lo THEN aux=1
setb aux
csbe indirect,#filt_hi ; IF byte > filt_hi THEN aux=1
setb aux
jnb aux,:skip ; If aux = 0 (byte is within
snb filt_1st ; filter range) :skip. If byte is
ret ; out of range, but valid bytes have
jmp :poll ; been received, return. Else poll.
:skip setb filt_1st
DEC temp1 ; Decrement buffer pointer.
inc buffer ; Increment buffer counter.
djnz bytes,:poll ; More bytes to receive: poll.
ret
Hur är det med teckentabeller osv i terminalprogrammet?
Börja med att ställa om det till hex-visning, en byte i stöten, då ser du vad programmet tror det tar emot.
Nästa fråga är handskakning och övriga inställningar.
> PICen är just nu programmerad så att den ska sända över ett "A" om och om igen
> (med 500ms mellanrum) det jag får upp i terminalen ser dock inte ut som ett "A" utan såhär:
Börja med att öka mellanrummet mellan tecken så att du tydligt ser när ett tecken
har sänts och när nästa tecken sents.
Sen, den allra vanligaste orsaken till "konstiga tecken" är att baud rate är olika
mellan sändare och mottagare. Om vi för enkelhets skull antar att sändaren (PIC'en)
i alla fall sänder med en "standard" baud-rate (vilket vi ju inte vet säkert) så kan du
prova med att ändra mottagaren (PC'n) mellan de olika standard baud-raten. Om du
t.ex tror att det ska vara 2400, så prova med 300, 600, 1200, 4800, 9600, 19200 t.ex.
Om inget av dessa verkar fungera så har du sannolikt programmerat baud-rate
generatorn fel i PIC'en. Då kollar du hur det faktiskt ser ut. Ta de inställningar
som koden gör och lägg in dom i de formler som finns i databaldet och se
om det ger 2400 baud.
Verifiera också att processorn går i just 20 MHz som du tror. Om du har en
20 MHz kristall och rätt kondingar (18-22 pF ligger nog mer rätt i och för sig)
så är det osannolikt att den inte går med 20 MHz. Förutsatt att du även har
konfigurerat den till "HS" (extern high-speed crystal), så klart. Det vet ju inte
vi något om, så se till att allt sådan är korrekt.