Is it possible to use a PIC18F2550 as a USB to RS232 adapter with PBP by using the CDC mode?
Is it possible to use a PIC18F2550 as a USB to RS232 adapter with PBP by using the CDC mode?
the microchip site has firmware to make a USB PIC into a serial convertor. It is fairly well documented. somewhere on the site
www.microchip.com
it is one of the first things i learned about when i began investigating PIC USB
-R
Or, if you wanted to stick with PicBasic, you could try the usbcdc.bas example in the USB18 folder.
DT
I have looked at booth but they are incomplete.
I have tried to capture data from the RS232 port on the pic and output it to the USB and also from the USB to the RS232 with no sucess.
All examples are just on how to emulate the CDC.
I basically need a USB to RS232 adapter like those you can buy in any store.
I have tons of these 18F2550 chips and would rather use them to convert my exsisting projects instead of going and buying some.
Ok, I got it to go from USB to the RS232 but I still cannot get the RS232 to USB to work. Here is the code I have so far.
Code:DEFINE OSC 48 INCLUDE "modedefs.bas" Buffer VAR BYTE[16] Cnt VAR BYTE B0 VAR BYTE PIC_TX VAR PORTC.6 ' Transmit Pin PIC_RX VAR PORTC.7 ' Receive Pin ADCON1 = 15 ' Set all I/Os to Digital INTCON2.7 = 1 ' Disable PortB Pullups CMCON = 7 ' Disable Comparators USBInit ' Main Program Loop MainLoop: USBService ' Must service USB regularly cnt = 16 USBIn 3, Buffer, Cnt, MainLoop SEROUT2 PIC_TX,84,[STR Buffer\Cnt] Get_RS232_Data: SERIN PIC_RX,T9600,100,Get_RS232_Data_Timeout,B0 Buffer[0] = B0 Cnt = 1 GOTO OutLoop Get_RS232_Data_Timeout: Buffer[0] = 0 Cnt = 0 OutLoop: USBService ' Must service USB regularly IF Cnt > 0 Then USBOut 3, Buffer, Cnt, OutLoop ENDIF GOTO Mainloop
Using a MAX232 type chip in the circuit?
Depending, you might have to use N9600 instead of T9600
Yes, I am using the MAX232 between the PIC18F2550 and the RS232 port.
At a quick glace, there's a couple problems. Maybe more, but haven't tested it yet.
With the first USBIN, if there isn't any incoming data from USB, it just loops back to MainLoop. It never makes it to SERIN, unless it receives data from USB at the same time.
You really should use HSERIN. The RS232 data may start while the program is sending or receiving USB data, in which case you would not be able to catch it with SERIN.
Added: And the 100ms timeout on the SERIN will cause it to lose the USB connection, since it isn't servicing it anymore.
DT
Ok, I got it all working now. I took Darrel's advice and switched to using HSERIN and HSEROUT but added the use of hardware interrupts to capture the RS232 data.
Here's the new code:
Code:DEFINE OSC 48 DEFINE HSER_RCSTA 90h DEFINE HSER_TXSTA 20h DEFINE HSER_BAUD 9600 DEFINE HSER_CLROERR 1 INCLUDE "modedefs.bas" Buffer VAR BYTE[16] Cnt VAR BYTE B0 VAR BYTE PIC_TX VAR PORTC.6 ' Transmit Pin PIC_RX VAR PORTC.7 ' Receive Pin LED1A VAR PORTB.0 ' 2 Color LED #1 LED1B VAR PORTB.1 LED2A VAR PORTB.2 ' 2 Color LED #2 LED2B VAR PORTB.3 ADCON1 = 15 ' Set all I/Os to Digital INTCON2.7 = 1 ' Disable PortB Pullups CMCON = 7 ' Disable Comparators '------------------------------------------------------------------------------- ' Interrupt Settings '------------------------------------------------------------------------------- RCON.7 = 0 ' Disable Priority Interrupts, 1 to Enable ' Enable/Disable Interrupts INTCON.4 = 0 ' Disable INT0 (PORTB.0) INTCON3.3 = 0 ' Disable INT1 (PORTB.1) INTCON3.4 = 0 ' Disable INT2 (PORTB.2) INTCON.5 = 0 ' Disable TMR0 (Timmer 0) INTCON.6 = 1 ' Enable Peripheral Interrupts INTCON.7 = 1 ' Enable Global Interrupt Handler PIE1.4 = 0 ' Disable USART Transmit Interrupt PIE1.5 = 1 ' Enable USART Receive Interrupt PIE2.5 = 0 ' Disable USB Interrupt LOW LED1A ' Turn LED #1 Green HIGH LED1B LOW LED2A ' Turn LED #2 Off LOW LED2B PAUSE 500 USBInit ON INTERRUPT GOTO Main_Interrupt_Handler ENABLE INTERRUPT ' Main Program Loop MainLoop: USBService ' Must service USB regularly Cnt = 16 USBIn 3, Buffer, Cnt, MainLoop HIGH LED2A PAUSE 25 HSEROUT [STR Buffer\Cnt] LOW LED2A GOTO Mainloop '------------------------------------------------------------------------------- ' Interrupt Handler '------------------------------------------------------------------------------- DISABLE INTERRUPT ' No Interrupts past this point Main_Interrupt_Handler: '--------------------------------------------------------------------------- ' USART Transmit Interrupt '--------------------------------------------------------------------------- IF PIR1.4 = 1 THEN PIR1.4 = 0 ENDIF '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- ' USART Receive Interrupt '--------------------------------------------------------------------------- IF PIR1.5 = 1 THEN HIGH LED2B PAUSE 25 HSERIN [B0] Buffer[0] = B0 Cnt = 1 OutLoop: USBService ' Must service USB regularly USBOut 3, Buffer, Cnt, OutLoop LOW LED2B PIR1.5 = 0 ENDIF '--------------------------------------------------------------------------- IntDone: RESUME ' Return to main program ENABLE INTERRUPT '------------------------------------------------------------------------------- END
That was pretty quick!
I've been playing with the program here and can say that the two PAUSE 25 statements, have to GO.
Of course that messes up the LED's, but with the pauses in there, it only picks up every 7 or 8th character when sending continuous data.
Without them, it works pretty good, but it's still a bit slow.
Test data of about 1500 bytes takes nearly 3 times as long as it should. Around 1.2 sec.
I think circular buffers would help speed it up, since it has to wait till it's finished sending the HSEROUT before in can receive more data from the USB. But I guess that depends on how fast you need it to be.
DT
Thanks Darrel. I have eliminated the LEDs all together because there is really no need for them. I was testing it by just using a terminal program on 2 computers so I never noticed the speed problem till now. How do I impliment the circular buffers you mentioned?
Me and my big mouth.
I wish I had time to work something up, but I've got too many things going on already.
You might take a look at this post by Joe S.
http://www.picbasic.co.uk/forum/showthread.php?p=28233
He's got a buffer in there for serial RX. Should give you a start.
But you really need to buffer both RX and TX.
busy busy,
DT
Hi Guys I've been working on the same - I can get a Half duplex data communication going but not full duplex (rs232-> usb and vice versa).
This program seems to do the trick, but even with the pauses removed I still only achieve a stable data rate at 9600 when sending large text files.
I'll try using the DT method (DT_int_18) interrupts and see if this speeds things up.
Circular buffers? The mind boggles!
Cheers
i doubt it would be if you used the EUSART but may worth to try..
PicMultiCalc gaves me...
mixing INT_18 and asm would certainly have some great effect.Code:DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1 DEFINE HSER_CLROERR 1 ' Clear overflow automatically DEFINE HSER_SPBRG 225 ' 9600 Baud @ 48MHz, 0.0% SPBRGH = 4 BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
Last edited by mister_e; - 26th February 2007 at 04:33.
Steve
It's not a bug, it's a random feature.
There's no problem, only learning opportunities.
USB is a Half-Duplex protocol. There's no way to have TRUE full-duplex. 2-wires, differential levels, can only do one thing at a time.I can get a Half duplex data communication going but not full duplex
However, with the proper buffers in place, you can make it seem like it's "FULL", in that you can send and receive at the same time from the USART. But it never truely will be Full-duplex for the USB.
DT
Yeah your right,
I guess what I should have said was this.
I can transmit in only one direction usb->usart, or usart->usb, not in the same program. Never mind now. I'm confused... ;(
Using Int_18 has def. sped things up!
Now I can transfer from USB->Usart successfully at 57600 baud, however Usart->Usb still only good enough at 9600 when sending text file. (Sending single key strokes is fine both directions at any speed).
I figure that the usart buffer needs to be increased as this is the bottle neck.
Cheers
I think you'll find that while from USB to USART works fine. It's massively buffered by the PC. If you were to send the same text file directly to a com port at 57600, it would take 1/3 as long to transmit.
This is because the PIC waits untill the last buffer full of data is sent via HSEROUT, before allowing it to receive more from the USB. The PC does the buffering, instead of the PIC.
And on the other side of it. This program is only sending 1 byte at a time to the USB. You can send up to 64. If it were buffered at the PIC, it could save incomming 232 data while it's busy sending to USB, then send a larger packet on the next time around. I think this would greatly improve the overall speed.
Theoretically, you should be able to run quasi-full-duplex at 250kbaud, without any problems.
DT
Squibcakes: Is it possible to get a copy of the source you have working with the DT interrupts? I greatly apreciate all the help you guys are giving me.
Thanks.
Sure thing brother,
Play around with the baud rates and see what max data speed you get. 250K would be awesome! but I think some sought of hardware hand shaking is needed to get up to those speeds. Hahaha
Anyway, first step I think is to increase the buffer size form 1 char to as DT said, about 64 Chars.
CheersCode:'**************************************************************** INCLUDE "DT_INTS-18.bas" ; Base Interrupt System INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts ' USB sample program for PIC18F4550 CDC serial port emulation ' Compilation of this program requires that specific support files be ' available in the SOURCE DIRECTORY!! ' 18F*.BAS Device header files that use the USB libraries ' CDCDESC.ASM Descriptor file for CDC serial demo ' JADESC.ASM Descriptor file for Jan Axelson demo ' MOUSDESC.ASM Descriptor file for mouse demo ' PBPCDC.INF INF file for the CDC serial driver ' USB.TXT This file ' USB18.ASM USB assembler file ' USB18.INC USB definitions file ' USB18MEM.ASM USB memory allocation file ' USBCDC.BAS CDC serial demo BASIC program file ' USBDESC.ASM Include file for descriptor file ' You WILL also need to modify the ' file USBDESC.ASM so that the only line used is -> include "CDCDESC.ASM" ' MUST use the 4 MHz xtal for this. ' this program receives data via usb virtual port then sends out via serial ' usart. ' USART module ' ------------ Define OSC 48 DEFINE HSER_RCSTA 90h DEFINE HSER_TXSTA 20h DEFINE HSER_BAUD 4800 DEFINE HSER_CLROERR 1 ' USB module ' ---------- UCFG var byte EXT ' include UCFG register... Yeah Melabs didn't :o( ucfg = %00010100 ' enable internal USB pull-up, Full speed USB ' ANALOG I/O CONFIG ' ----------------- ADCON1 = 15 ' Set all I/Os to Digital CMCON = 7 ' Disable Comparator Buffer VAR BYTE[16] Cnt VAR BYTE B0 VAR BYTE ASM INT_LIST macro ; IntSource,Label,Type,ResetFlag? INT_Handler RX_INT,_SendUsB,PBP,yes endm INT_CREATE ; Creates the interrupt processor INT_ENABLE RX_INT ; enable external (RX) interrupts ENDASM USBInit ' Main Program Loop MainLoop: USBService ' Must service USB regularly Cnt = 16 USBIn 3, Buffer, Cnt, MainLoop HSEROUT [STR Buffer\Cnt] GOTO Mainloop '---[RX_INT - interrupt handler]------------------------------------------------ ' PROGRAM COMES HERE WHEN DATA ENTERS THE USART PORT SendUsB: HSERIN [B0] Buffer[0] = b0 cnt = 1 OutLoop: USBService ' Must service USB regularly USBOut 3, Buffer, Cnt, OutLoop @ INT_RETURN
Data of hserin is ok
............
USBService ' Must service USB regularly
Cnt = 10
USBIn 3, Buffer, Cnt, MainLoop
' Send to pc data recived from pc
GOTO OutLoop <---------not work, not send buffer
GOTO Mainloop
.........
Code:INCLUDE "modedefs.bas" ' Configuração asm __CONFIG _CONFIG1L, _PLLDIV_1_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L ; ; ; USB clock source comes from the 96 MHz PLL divided by 2 ; ; [OSC1/OSC2 Src: /1][96 MHz PLL Src: /2] ; No prescale (4 MHz oscillator input drives PLL directly) __CONFIG _CONFIG1H, _FOSC_XTPLL_XT_1H & _FCMEN_OFF_1H & _IESO_OFF_1H ; ; ; Oscillator Switchover mode disabled ; ; Fail-Safe Clock Monitor disabled ; XT oscillator, PLL enabled, XT used by USB __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_ON_2L & _BORV_2_2L & _VREGEN_ON_2L __CONFIG _CONFIG2H, _WDT_OFF_2H __CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_ON_3H __CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L __CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L & _CP2_ON_5L & _CP3_ON_5L __CONFIG _CONFIG5H, _CPB_ON_5H endasm DEFINE OSC 48 DEFINE HSER_RCSTA 90h DEFINE HSER_TXSTA 20h DEFINE HSER_BAUD 9600 DEFINE HSER_CLROERR 1 Buffer VAR BYTE[16] Cnt VAR BYTE A VAR BYTE B VAR BYTE C VAR BYTE PIC_TX VAR PORTC.6 ' Transmit Pin PIC_RX VAR PORTC.7 ' Receive Pin ADCON1 = 15 ' Set all I/Os to Digital INTCON2.7 = 1 ' Disable PortB Pullups CMCON = 7 ' Disable Comparators ' Interrupt Settings RCON.7 = 0 ' Disable Priority Interrupts, 1 to Enable ' Enable/Disable Interrupts INTCON.4 = 0 ' Disable INT0 (PORTB.0) INTCON3.3 = 0 ' Disable INT1 (PORTB.1) INTCON3.4 = 0 ' Disable INT2 (PORTB.2) INTCON.5 = 0 ' Disable TMR0 (Timmer 0) INTCON.6 = 1 ' Enable Peripheral Interrupts INTCON.7 = 1 ' Enable Global Interrupt Handler PIE1.4 = 0 ' Disable USART Transmit Interrupt PIE1.5 = 1 ' Enable USART Receive Interrupt PIE2.5 = 0 ' Disable USB Interrupt PAUSE 1000 USBInit ON INTERRUPT GOTO Main_Interrupt_Handler ENABLE INTERRUPT ' Main Program Loop MainLoop: USBService ' Must service USB regularly Cnt = 10 USBIn 3, Buffer, Cnt, MainLoop ' Send to pc data recived from pc GOTO OutLoop GOTO Mainloop ' Interrupt Handler '------------------------------------------------------------------------------- DISABLE INTERRUPT ' No Interrupts past this point Main_Interrupt_Handler: ' USART Transmit Interrupt IF PIR1.4 = 1 THEN PIR1.4 = 0 ENDIF ' USART Receive Interrupt IF PIR1.5 = 1 THEN HSERIN [A, B, C] Buffer[0] = A Buffer[1] = B Buffer[2] = C Buffer[3] = 13 Buffer[4] = 10 Cnt = 4 OutLoop: USBService ' Must service USB regularly USBOut 3, Buffer, Cnt, OutLoop PIR1.5 = 0 ENDIF '------------------------------------------------------------------------------- IntDone: RESUME ' Return to main program ENABLE INTERRUPT '------------------------------------------------------------------------------- END
..: Don't worry, be happy :..
Bookmarks