Close
0%
0%

Serial Transmitter Using Discrete Parts

An asynchronous serial transmitter using only mosfets, resistors, capacitors, and diodes as building blocks.

Similar projects worth following
This is an attempt to make a project without using any integrated circuits that would transmit data using the commonly used "serial" protocol. This protocol is sometimes referred to as Async Serial, UART, TTL Serial, or Logic Level RS-232.

I've had the desire to do the old "build a computer with transistors" project for a bit now. After getting the design of a binary to seven segment decoder working I decided that I wanted to do something a bit more complicated. I ended up thinking I should do something like a stripped down UART module. Due to the complexity I decided to just work on the transmitter as I was making faster progress on that part.

To give some details the transmitter takes in 8 bits and has a one byte buffer that can loaded while transmitting. The transmitter will run until the buffer is empty. It's hardwired to run at 4800Hz and uses its own built in clock. There are 1 start bit and 1 stop bit. No parity bit and LSB is first.

The Results:

Here's a short video of the transmitter running. You may need to full screen the video to see the LCD screens at the bottom. I had a hard time getting the screens to show up on video. When the LCD backlight was on the camera had trouble with the contrast of the text. I'll have to come back to this and make a new video when I can get things to show up better on video.

An Arduino on the left side controls the transmitter. It loops over a short list of strings and sends one of them when a button is clicked. The Arduino on the right side is set up to receive data on the Rx pin through the standard UART interface and display whatever it receives on the LCD screen.

DSView Logic Analyzer Screenshot

Here's a screenshot from DSView showing a live test where I sent the string "Hello". D0-D7 and Send(aka. Load) are the important inputs and Tx is the serial output. The DSView software is able to automatically decode the Tx signal that was generated by the project as what was intended. 

The Design:

I came up with the design by messing around in Paul Falstad's CircuitJS. I kept adding parts to and refining the simulation until I had something I liked. To start, I knew I needed a Parralel-In-Serial-Out shift register to structure the output signal. From there I added a state counter and clock input. About halfway through the design I decided that it would be a good idea to include a buffer that was at least one byte. The 

Whenever I added something new to the design I would stop working on the simulation and come up with an NMOS solution that worked as a real world circuit to match what I needed.

I heavily relied on dynamic logic to reduce the parts count of any sequential circuits. The only time I used the static logic version of a circuit was with the SR Latches as they only took 5 transistors to implement anyway. 

Check the Project Logs for more details about sub-sections of the project.

The Construction:

I wanted to maintain a sort of an IC layout sort of feel to the project and so I avoided using air wires or using point-to-point wiring. I made an exception for straight wires on the top layer as I couldn't find a double sided perfboard at this size. Everything is connected only on the top and bottom layer.

I used solder bridging on the backside to connect components together. In the beginning I used thin wires to make it easier to bridge between pads but I would recommend against it. The embedded wire made it difficult to desolder when I had to go back and make a few changes.

I ended up using nearly an entire 100g roll of solder for this project. The solder contracting after cooling actually caused the entire board to warp slightly.

Screenshot of GIMP workspace.

I quickly realized that I would have to come up with a way to preplan the layout on the board. I didn't know how large subsections of the circuit would be and how they would all fit together. I wanted a way to be able to move components around so that I could experiment with finding the most space efficient layouts that I could come up with.

I started off in Microsoft PowerPoint since I could draw and move around shapes easily. With the number of shapes growing quickly for just the first D Flip-Flop in the counter, PowerPoint was acting unwieldy. I needed to switch to another solution. I didn't end up finding a perfect fit of some kind of perfboard layout tool and I went back to my fall back option. GIMP. I could drag around shapes but layers and groups let me organize things while allowing me to easily move parts around. 

I made a grid of dots to represent the grid of holes in the perfboard and drew a few components to match the size on the real board. GIMP was able to handle a huge number of layers without getting laggy to user input but did use a large amount of memory by the time I was finished the layout. The only big drawback was drawing the wires. If I wanted to make a big change to...

Read more »

UART_Transmitter_CircuitJS_Final_02_28_2022.txt

CircuitJS file for the logical overview of the project. This one takes a bit of processing power so you may have to slow down the simulation speed if it runs choppy.

plain - 8.18 kB - 02/28/2022 at 06:03

Download

UART_Transmitter.zip

KiCad Schematic

x-zip-compressed - 99.37 kB - 02/28/2022 at 06:01

Download

  • 230 × 2N7000 NMOS MOSFET Transistor
  • 13 × Resistor 1K
  • 6 × Resistor 4.7K
  • 107 × Resistor 10K
  • 4 × Resistor 100K

View all 14 components

  • Basic Building Blocks

    Eric Ljungquist02/21/2022 at 07:31 0 comments

    NMOS-Resistor Logic, Dynamic Logic

    This log goes over what I call the basic building blocks of the circuit.

    I chose NMOS logic as it seemed very straight forward to design with. I've also seen a lot of designs using  BJT Transistor-Transistor Logic to build discrete component circuits and I wanted to do something a bit different.

    Basic Logic Gates

    Basic NMOS Logic Gates

    NMOS Inverters in CircuitJS

    Basic NMOS Gates in CircuitJS

    D Latch

    Data Latch in CircuitJS

    SR Latch

    The SR latch is a simple way save a state. e.g. "Do I have data in the buffer I need to send?" or "Am I currently sending out a data packet?". I used the typical two cross coupled NOR gates to implement mine. At power up the latch will start in an unknown state. I've added an additional pull down mosfet to the "Set" side of the latch to act as an additional input for the power-on-reset circuit.

    The transistor level diagram:

    SR Latch in CircuitJS

    D Flip-Flop

    For the D Flip-Flop we are just doubling up the D Latch shown above in a master-slave configuration but with a slight change to the Load input. This prevents the flip-flop from being "transparent" while clocking in the data signal.

    D Flip-Flop in CircuitJS

    Edge Detector

    Edge Detector in CircuitJS

  • Control Logic

    Eric Ljungquist02/21/2022 at 07:30 0 comments

    temp

  • 4 Bit Counter

    Eric Ljungquist02/21/2022 at 07:29 0 comments

    The above video show to early testing of the counter. I have it hooked up to a 555 timer and the outputs of each counter stage are connected to an LED. The LED's show the circuit count up in binary as expected.

    4 Bit Counter in CircuitJS

    kl;kj;

    jk;kj;

  • 8 Bit Buffer

    Eric Ljungquist02/21/2022 at 07:28 0 comments

    I don't have much to say for this section. I only included it as I had taken the above picture showing some early testing. In the image I am testing that each latch was holding data correctly. I didn't have any issues with using dynamic logic to store the data. In testing I found that the value would only bleed off or on through the transistor switch after two to five minutes. Much longer than what was needed for correct operation.

    The 8 bit data buffer is implemented the same as what is outlined in the project log "Basic Building Blocks" under the Data Latch heading. The circuit is just copied and pasted eight times over.

  • Parallel In Serial Out Shift Register

    Eric Ljungquist02/21/2022 at 07:26 0 comments

    Shift Register Transistor Level Circuit



    Parallel-In-Serial-Out Shift Register in CircuitJS

    The Parallel-In-Serial-Out Shift Register is the heart of the project. Most of the other circuits are there to control the state of the shift register.

    I implemented the shift register as the standard D Flip-Flop chain. I added a D Flip-Flop for every bit I needed to send, plus one flip-flop for the Start bit, and one more flip-flop as an output stage. The Stop bit doesn't get its own flip-flop, once the last bit is sent out of the shift register, any further clocks output a High signal. The state counter just runs for an extra cycle past the last data bit sent.

    To implement a loadable D Flip-Flop I took the basic D Flip-Flop outlined in the "Basic Building Blocks" project log and added a mosfet switch leading to the capacitor on the slave side of the flip-flop. This allows the charge of the capacitor to be set independently of the clock. The outputs of the 1 bit data buffer feed directly into the transistor switches of each shift register stage. The output stage holds the last value that was clocked in so that the output of the shift register does not automatically change when loading the rest of the flip-flops. Not shown in the above diagram is that I added a mosfet controlled pull-up on the output stage to act as a "Set Pin". This set pin is pulled high when the transmitter is not running so that the output is held at the "Idle" State.

  • Clock Generator

    Eric Ljungquist02/21/2022 at 07:09 0 comments

    Clock Generator in CircuitJS

    I wanted the board to generate it's own clock. I felt like the board would be a more complete package if included and didn't seem to be much of an issue to add. I came across Fairchild's Application Note 118 quickly in my search. The application note details a Ring Oscillator that is slowed by an RC circuit on the feedback line. It looked like exactly like what I needed, low parts count and can fit the NMOS logic theme. 

    To allow calibration I've added a multi-turn potentiometer on the right side of the feedback line so that adjustment to the output frequency can be made.

    I breadboarded it up and it seemed to work just fine looking at the signal on the oscilloscope. I just had to add an inverter to the end to help square up the output waveform. At the time I wasn't sure what frequency I would end up using. I was planning for 9800Hz but wasn't sure if everything would work at that speed. To test the rest of the circuit before settling on a clock I used either a button to single step or my signal generator. This ended up being a bit of a problem for me as I thought that the clock would work perfectly when dropped in. I designed the rest of the layout while only leaving myself just enough room to add what I had already came up with for the clock.

    I had everything working correctly while using the external clock from a signal generator. I then rebuilt the clock circuit on a breadboard and fed the output into the rest of the project and it did not run at all. I hooked the project back up to the signal generator to help debug and determined that a DC offset on the low voltage state of the clock was causing some major issues. I found that if the low side of the clock was above about 160mV then the rest of the project would not change state correctly. The low voltage portion of the clock signal was fluctuating between 180mV to 250mV. I was able to squeeze in a coupling capacitor on the output which got the offset down to about 10-30mV. After this addition, things started working correctly.

    The clock signal still has some pretty bad ringing on it that I think are causing some minor issues but for the most part it works.

View all 6 project logs

Enjoy this project?

Share

Discussions

zpekic wrote 07/17/2022 at 18:50 point

Very cool project, lot to learn from about discrete implementation of logic gates! I am just wondering, given that the 8-bit output word needs to only be stored during the time to send (which is short even for slow baud rates), if 8 capacitors could be used as "memory cells" - first tied to bus, and then to output mux (I used mux instead of shift register to generate TXD, see here: https://hackaday.io/project/181664-intel-hex-files-for-fpgas-no-embedded-cpus/log/197809-par2ser-a-novel-uart-transmitter-counter-driven-mux-approach ). 9th capacitor (same as other 8) with some "level sense" circuit could be used to signal to host CPU when 8 others are charged (like /WAIT signal at writing to output port). At the moment of sending the bit (mux selection to TXD) the capacitors would be also discharged. 

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates