Well, slow is not really a thing. I remember we used PC COM ports as fast I/O as the speeds of the handshaking bits where faster than LPT ... The PC transmit speeds are limited to 115200 Baud but the control/handshaking lines are faster. Also on MCU you can have even 33 MBaud... Here are some PC based non traditional use for COM RS232 examples:
PWM
the transmitted data can be used as HW PWM generator with 8 or 9 levels. Simply transmit number with number of set bits equal to your wanted level... If you use RC filter or non linear load it will create a sort of DAC.
sound
as others suggested, you can use RS232 as a sound generator, even PCM. As the USART is buffering you can use it more comfortably without the need for accurate timing code making it much more easier and even faster in comparison to in build speaker. Take a look at this:
signal generator
the frequency of RS232 COM port on PC is driven by 16 bit divider from 115200 Hz
. So if you continuously send alternating zeros and ones in binary (start/stop/parity bit included) then you have HW frequency generator...
voltage generator
This is wild stuff but I am using this for programming MCUs. as the RS232 protocol has +/-10V
or +/-15V
voltages you can use them as a source of power in applications that has just single voltage power supply like +5V or +3.3V without the need for voltage multipliers ... Simply use the TxD output from PC as AC power supply, so rectify it by diodes filter with capacitor and you have +/- 10V voltages ... Of course, to be able to work this way you need to be sending data from PC continuously and the load must not be too big. I usually use it for 3.3V/RS232 voltage converters (without MAX232)
For example, today's MCUs have really small power requirements if used properly, so this can be also used to power MCU applications alone without the need for additional power supply. It can get handy time to time ...
The COM port on PC has one big advantage over other interfaces on Windows, and that is it does not require additional drivers for access. You simply open file with name COM1,COM2,...
and that is it ... In comparison with USB LPT the SW implementation is much much much easier, free of charge and comfortable.
If it helps, here is my ancient COM example for MS-DOS in Borland Turbo C++:
//---------------------------------------------------------------------------
//--- Includy: --------------------------------------------------------------
//---------------------------------------------------------------------------
#include <iostream.h>
//----------------------------------------------------------------------------
//--- Global data: -----------------------------------------------------------
//----------------------------------------------------------------------------
typedef unsigned char byte;
typedef unsigned int word;
word far *memw=0x00000000;
byte far *mem=0x00000000;
char key;
word keyhi;
word com;
//----------------------------------------------------------------------------
//--- I/O: -------------------------------------------------------------------
//----------------------------------------------------------------------------
void inkey()
{
key=0;
keyhi=0;
asm {
mov ax,256
int 0x16
jz esc
mov ax,0
int 0x16
mov key,al
mov keyhi,ax
}
esc:
}
//---------------------------------------------------------------------------
void inkeyw()
{
asm {
mov ax,0
int 0x16
mov key,al
mov keyhi,ax
}
}
//---------------------------------------------------------------------------
byte in(word adr)
{
byte x;
asm {
mov dx,adr
in al,dx
mov x,al
}
return x;
}
//---------------------------------------------------------------------------
void out(word adr,byte x)
{
asm {
mov dx,adr
mov al,x
out dx,al
}
}
//---------------------------------------------------------------------------
//--- com: ------------------------------------------------------------------
//---------------------------------------------------------------------------
void com_init(word x)
{
com=memw[(0x400>>1)+x-1]; // adr portu z DOS TAB 0000:0400h
out(com+1,0); // ziadne int
out(com+3,3); // 1 start, 8 data, 1 stop, 0 parity
}
//---------------------------------------------------------------------------
void com_speed(word f)
{
word x,h,l;
x=115200/f;
h=(x >> 8) & 255;
l=x & 255;
x=in(com+3) & 127;
out(com+3,x+128);
out(com+0,l);
out(com+3,x+128);
out(com+1,h);
out(com+3,x);
}
//---------------------------------------------------------------------------
byte com_in()
{
byte s;
// do s=in(com+5); while ((s&1)!=1);
s=in(com+0);
return s;
}
//---------------------------------------------------------------------------
void com_out(byte d)
{
byte s;
do s=in(com+5); while ((s&32)!=32);
out(com+0,d);
}
//---------------------------------------------------------------------------
//--- Subroutines: ----------------------------------------------------------
//---------------------------------------------------------------------------
void couthex(word x)
{
word a,i;
char c;
for (i=0;i<4;i++)
{
a=(x >> 12) & 15;
x=x << 4;
if (a<10) c=a+'0';
if (a>=10) c=a-10+'A';
cout << c;
}
cout << 'h';
}
//---------------------------------------------------------------------------
//--- Main: -----------------------------------------------------------------
//---------------------------------------------------------------------------
void main()
{
asm {
mov ax,3
int 0x10
}
char x=0;
com_init(1);
com_speed(1404); // common i8051 / 24 MHz and PC USART frequency
cout << "COM adress = "; couthex(com); cout << endl;
do {
inkey();
x=com_in();
couthex(x);
cout << endl;
} while (keyhi==0);
cout << "COM adress = "; couthex(com); cout << endl;
inkeyw();
}
//---------------------------------------------------------------------------
//--- End. ------------------------------------------------------------------
//---------------------------------------------------------------------------