Bascom and AVR, Interfacing with USB.


Modern PC and certainly laptops may no longer have an RS-232 or parallel port interface. Instead, they have one or more USB or Firewire interfaces. So, some means of making a connection between a USB port on the PC and your controller project may become necessary. I will not go into Firewire interfaces, but if you want to use USB, you should visit The USB organisation and read at least the USB FAQ and perhaps even the USB-1.1 and USB-2 standard documents, although the last two are quite a challenge!

As far as I know, there are no AVR's in the ATTiny and ATMEGA range with a USB interface. Atmel has the AT43USB series, but they seems to be a bit 'different' and these IC's are not supported in Bascom anyway.
However, there are IC's that provide a USB interface to the PC-side and a serial or parallel interface to the controller. I have used the FTDI FT232BM and FT245BM.

NOTE: the FT232R and FT245R are more modern versions.

The FT232BM is a sort of 'legacy' chip that provides a USB to RS-232 bridge. The FT245BM does USB to eight-bit parallel conversion with four-line handshaking.
Note that the 'BM' series of these IC's is the follow-up to the first 'AM' version. There are differences, if you have the 'AM' version, read the datasheets!
These IC's are particularly easy to use because FTDI provides a Virtual Com Port (VCP) driver. This presents both the FT232BM and the FT245BM as a com port to the PC's operating system. Talking to or listening to the FT's involves no more than using a simple terminal emulator program such as Hyperterminal. FTDI also has a much more advanced D2XX driver, which allows you to interact in a more direct (but also more complicated) manner with the FT232BM or FT245BM.
You can of course use the FTDI IC's in your projects, but I started with the USB-1 and USB-2 modules from Voti. The USB-1 module is a simple kit with the FT232BM and 93C46 EEPROM that is a complete USB-RS232 interface. The USB-2 module has the FT245BM and 93C46 EEPROM but is in essence no more than a 32-pin DIP with all FT245BM pins connected to the DIP pins.

Using the USB-1 kit with the FT232BM.
First, download the latest FTDI VCP driver for your operating system and unzip the files to a directory on your PC. Make sure you read the driver installation instructions .
Build the USB-1 module according to Voti's instructions:


The module has the DTR, DSR, RTS and CTS line for a full hardware RS-232 handshake mode but I used only RxD and TxD. Note that the USB-1 module is powered by the USB bus. It can supply power other circuitry by inserting the jumper. This puts app. 5V on the brown wire.



And this test program:
usb-1-rs232.bas
$regfile = "2313def.dat"
$crystal = 4000000
$baud = 9600

Config Pind.6 = Output

Dim Firstnumber As Integer
Dim Secondnumber As Integer
Dim Sum As Integer

Cls

Do
  Set Portd.6
  Firstnumber = 0
  Secondnumber = 0
  Input "Enter first number : " , Firstnumber
  Cls
  Lcd "frst:" ; Firstnumber ; " "
  Input "Enter second number: " , Secondnumber
  Lcd "scnd:" ; Secondnumber
  Sum = Firstnumber + Secondnumber
  Print "Sum: " ; Sum
  Lowerline
  Lcd "sum: " ; Sum
  Reset Portd.6
  Waitms 100
Loop

End
Default LCD connections are assumed.
The UART is set to a speed of 9600 baud.
The program asks for two numbers and returns the sum. The numbers and the sum are also displayed on the LCD.

Apply power to the breadboard and connect the USB cable to your PC and to the USB-1 module. You should hear the familiar 'ding-dong' sound, indicating a USB connect. On the PC, the 'Found new hardware' wizard starts. Follow the wizard, specify the location where you unzipped the VCP driver files. Once the wizard completes, open the Device Manager (Start\Settings\Control Panel\System\Hardware\Device Manager) and check that your system now has an extra Com port in the Ports section.
Now start Hyperterminal, or any other terminal emulator program that you have, and open a connection to this new com port and set the speed to 9600 baud. Reset the controller and the text "Enter first number: " should appear in the terminal emulator window. Type in a number, after >enter<, the number appears on the LCD. The controller asks for a second number. Enter a number, this number and the sum of the two numbers appears on the LCD. The sum is also reported in the temrinal emulator window.
Note that the USB-1 module has a LED that flashes when there is activity on either the send or receive line.

Using the USB-2 kit with the FT245BM.
The USB-2 module has a FT245BM plus 93C46 EEPROM. The FT245BM has a 128 byte receive Fifo and 384 byte transmit Fifo. Regard the Fifo's as being a small buffer memory with a First-in/First-out structure. The USB-2 module kit is a small pcb arranged as a 32-pin DIP, making it easy to use on a breadboard or on another pcb in a 32-pin IC socket. It requires some external components such as a crystal, crystal capacitors, decoupling capacitors etcetera:


I tested the USB-2 module in combination with an ATMEGA32. This is a 40-pin DIP IC, having plenty of I/O, memory etc. (read more on using the larger AVR's if you need to)
Try this schematic:



(The 'thick' lines in the schematic is a way of drawing groups of lines as one. For example, the Reset, SCK, MISO and MOSI line from the ATMega32 to the connector header is drawn as one line)

First, let us try to read data from the FT245BM Fifo with this program:
usb-read-fifo.bas
'The ATmega32 is used.
$regfile = "m32def.dat"
$crystal = 4000000

Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5

Config Portd.2 = Input
Config Portd.6 = Output
Config Portb.6 = Output
Config Portc = Input

Rxf Alias Pind.2
Rd Alias Portd.6
Led Alias Portb.6

Dim Usbin As Byte

Set Rd

Cls
Lcd "reading..."
Lowerline
Set Led
Waitms 500
Reset Led
Waitms 500

Do
  If Rxf = 0 Then
    Reset Rd
    Usbin = Pinc
    Set Rd
    'apparently hyperterm sends characters
    'with upper bit random on or off...
    Usbin = Usbin And &B01111111
    Lcd Chr(usbin)
  End If
Loop

End
Portc is configured as input to read the FT245BM eight-bit data.
The Rxf line is monitored, once is goes low there is data in the receive Fifo. The data is read by making Rd low. This data is displayed on the LCD. When I send regular characters with Hyperterm it appears that sometimes the upper bit is high. I do not know why this is so. I would think that the upper bit is only used the 'extended ascii character set. Anyway, the upper bit is masked out by 'anding' Usbin with 0111.111.

If you tested the USB-1 module or a seperate schematic with the FT232BM first, you already have the VCP driver installed on your PC. Otherwise you must do this after the first USB connect following the 'Found new hardware' wizard directions.
Start Hyperterminal or another terminal emulator program and select the com port just added to your system. You may have to select a baud-rate in Hyperterminal but it is ignored by the driver since it will communicate with the FT245BM at the maximum possible speed. Type a character and observe that this character is shown on the LCD. Monitor the RXF# line (pin 12) on the USB-2 module with an oscilloscope. Every time you enter a character this line goes low. After the character is read, the receive Fifo is empty and the line goes high. The character is placed on the data bus when RD# goes low.

Now, let us try sending characters from the FT245BM to the PC with this program:
usb-write-fifo.bas
'The ATmega32 is used.
$regfile = "m32def.dat"
$crystal = 4000000

Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5

Config Portd.2 = Input
Config Portd.6 = Output
Config Portd.5 = Input
Config Portd.7 = Output
Config Portc = Output

Rxf Alias Pind.2
Rd Alias Portd.6
Txe Alias Pind.5
Wr Alias Portd.7
Led Alias Portb.6

Dim Usbin As Byte

Set Rd

Cls
Lcd "sending..."
Lowerline
Set Led
Waitms 500
Reset Led
Waitms 500

Do
  If Txe = 0 Then
    Reset Wr
    Portc = Asc( "a")
    Set Wr
  End If
Loop

End
Portc is configured as output to send characters to the FT245BM data port.
In the Do Loop, the character "a" is sent to the FT245 data port by making Wr low, then high again. The character is not sent until the Txe line is low, indicating there is room in the transmit Fifo.

Start Hyperterminal and select the com port just added to your system. Observe that the controller just sends a stream of "a"'s to your PC. Monitor the TXE# line with an oscilloscope. If you click somewhere in the Hyperterminal window the flow of "a"'s will stop and almost immediately thereafter, the TXE# line will go high indicating that the transmit Fifo is full and the FT245BM cannot accept more characters. Click outside the Hyperterminal window and the stream of "a"'s will resume and the TXE# line will go low again. On a slower PC, the TXE# line may go high regularly, indicating that the PC cannot keep up with receiving characters and the FT245BM transmit Fifo is full.

As a last example, the following program uses an interrupt to receive a character from the receive Fifo and then send it back to the transmit Fifo:
usb-readonint-write-fifo.bas
'The ATmega32 is used.
$regfile = "m32def.dat"
$crystal = 4000000

Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
Config Int0 = Falling

Config Portd.2 = Input
Config Portd.6 = Output
Config Portd.5 = Input
Config Portd.7 = Output
Config Portb.6 = Output


Rxf Alias Pind.2
Rd Alias Portd.6
Txe Alias Pind.5
Wr Alias Portd.7
Led Alias Portb.6

Dim Usbin As Byte
Dim Readusbfifoflag As Bit

Set Rd
Reset Wr

On Int0 Setreadusbfifoflag

Enable Interrupts
Enable Int0


Cls
Lcd "readonint/wrt..."
Lowerline
Set Led
Waitms 500
Reset Led
Waitms 500

Do

  Set Led
  Waitms 1000
  Reset Led
  Waitms 1000
  If Readusbfifoflag = 1 Then
    Reset Readusbfifoflag
    Do
      Config Portc = Input
      Do
      Loop Until Rxf = 0
      Reset Rd
      Usbin = Pinc
      Set Rd
      'apparently hyperterm sends characters
      'with upper bit random on or off...
      Usbin = Usbin And &B01111111
      Lcd Chr(usbin)

      Config Portc = Output
      Do
      Loop Until Txe = 0
      Set Wr
      Portc = Asc(usbin)
      Reset Wr
      Lcd Chr(usbin)
    Loop Until Rxf = 1
  End If

Loop

Setreadusbfifoflag:
  Set Readusbfifoflag
Return

End
In the interrupt routine, only the flag Readusbfifoflag is set.
The main program is sometimes 'busy' (simulated by using long wait times when flashing the Led), if the Readusbfifoflag is set, Portc is configured as input and one character is read from the receive Fifo. It is displayed on the LCD, then Portc is configured as output and the character is written back into the transmit Fifo and again displayed on the LCD.

I have not found out yet how to program the EEPROM on the USB-1 and USB-2 modules to take advantage of custom VID, PID, serial number, power descriptor etc.

TOC