loading...

SoftwareSerial Implementation with mbed & STM32

yuseiito profile image Yusei Ito ・5 min read

Important Notice : This is a mirror of an article which is posted on Qiita: STM32F303K8 & mbedでSoftwareSerialを実装する 【TX編】.
The newest release would be on Qiita. Qiita has priority about this post.


You love UART,don't you?

Hello,guys. I'm Yusei,a Japanese High school student,software developer,and RoboCupper.

In this article,I introduce my playing on UART,a serial communication pheripheral.

This article starts with basic introduction about UART.
If you wanna read only the result of my softwareserial implementation,
jump to Implement TX.

Basis of UART

What is UART?

A universal asynchronous receiver-transmitter (UART /ˈjuːɑːrt/) is a computer hardware device for asynchronous serial communication in which the data format and transmission speeds are configurable.
https://en.wikipedia.org/wiki/UART

Dr.Wikipedia taught us perfectly.
This end of this section----No way.
UART is a Serial commounication pheripheral.

UART is a kind of asynchronous communication.

Bacause of that,it has characteristics like follows:

  • Both Transimitter and Receiver has each CLOCK** . It works basing on the clock which is set for same frequency in Receiver and transmitter.
  • With just One signal line(and GND connection),a one-way communication getsavailable.
  • It has no role like Master and Slave.

I show you a rough sketch of connection setup of UART.
TX(transmitter) and RX(Receiver) pins crosses. It's important to understand how UART works.
IMG_B6CFDD40EDE4-1.jpeg

With this strange crossing connection,Transmitted signal from one client goes to Receiver of another one. And the opposite is also.

Then,what is the signal in the TX-RX line like?

UART signal(pulse)

To understand contents as same as this section,you can also read following articles . They're much better than my writig.

NOTE: They're all in Japanese.

以下が、基本的なUART通信の信号です。 デジタル信号ですので、TTLレベル/CMOSレベルのいずれかに揃えて,HIGH/LOWの2値でやり取りします。

First of this section,I show you basic UART signel which is sending 'A'.
As you know,they are a digital signal. They communicate in HIGH & LOW.
HIGH level depends on each circuit. TTL level(5v) and CMOS level(3.3v) is usually used.

UART signal.

  1. Communication starts with fall of the signal line.
  2. From that point,keep signal low for 1 bit long time. This bit is called start bit. 3.Then,data sending gets started. Unit of sending is 1Byte. According to the order of Big-endian of the byte's binary 1/0,set signal pulse HIGH/LOW. Keep 1 bit long time for each bits.
  3. (If you use parity,DB7 is used as parity.)
  4. Set HIGH for 1 bit long time or longer. This will be the stopbit.

1 bit long time

As I told you before,UART is a kind of asyncronous communication.
It means each client counts the time for 1 bit and does sampling basing on it.

The common rated clock frequency is called "baudrate".
Higher baudrate is as same as faster communication. Unit for baudrate is bps. Generally,9600,115200,and some others are used.

And we can calculate the 1 bit long time from the baudrate.

bps means bit per second. 
We wanna caluculate seconds per bit. So just get reciprocal number of baudrate.

(1 bit long time)= 1 / (baudrate).

Error range of 1bit long time

To be honest,the value accepts a range of error.
If there's now more than 1 bit long time after 10bit,the error will be accepted.

SoftwareSerial

Sorry for my too long introducation.
My playing which I wanna introduce here is Implement UART with GPIOs.
Normaly, to use UART with any microcontroler,a spesific UART chip is contained on SoC,and we can only use specific pins which is connected to the chip.

The number of available UART is limited because of that.
However, as I showed you by the last section,UART signal is actually easy.
Therefore,I tried to generate UART signal with software using GPIO.

I tried on STM32F303k8t6 by STmicro, using mbed framework.

Implement TX

This is a basic code sending 1 byte 'A' polling.

#include <mbed.h>
#define UART_DELAY 104 //  1/9600
Serial pc(USBTX,USBRX);
DigitalOut RX(D4);
DigitalOut TX(D5);


int main() {
TX=1;
pc.baud(230400);
pc.printf("Boot");

  while(1) {

    TX=0;//START
    wait_us(UART_DELAY);

    TX=1;//DB0
    wait_us(UART_DELAY);

    TX=0;//DB1
    wait_us(UART_DELAY);

    TX=0;//DB2
    wait_us(UART_DELAY);

    TX=0;//DB3
    wait_us(UART_DELAY);

     TX=0;//DB4
    wait_us(UART_DELAY);

     TX=0;//DB5
    wait_us(UART_DELAY);

     TX=1;//DB6
    wait_us(UART_DELAY);

     TX=0;//DB7
    wait_us(UART_DELAY);

     TX=1;//Stop
    wait(1);

  }
}

Just do it .
You will be able to realize 1 byte 'A' sending , accrording to theory.

To check the UART,I used FTDI usb-serial adapter.
Connection is like following table.

STM32 FTDI
D4 TX
D5 RX
GND GND

High level must be set as 3.3v(CMOS level).

Communication setup is 9600 8-N-1 (9600bps,8bit data bits, No parity、stopbit 1).

Toubled point: 1 bit long time

In this program , 1bit long time with defiend value UART_DELAY. Unit is μs.This valuse is originaly 1/baudrate (seconds). When the baudrate is 9600bps, it should be 1/9600≒104μs. However,when I tried,I couldn't check its work.Instead, in range of 91<UART_DELAY<102,It workded completely.

Why the time is shorter than theroritical value.

Setting GPIO takes time.

Actually,I mesured the time setting GPIO takes.

#include <mbed.h>
#define UART_DELAY 97//101Max,92 Min(104 in theory)
Serial pc(USBTX,USBRX);
DigitalOut RX(D4);
DigitalOut TX(D5);

Timer t;

int main() {

  // put your setup code here, to run once:
    TX=1;
    pc.baud(230400);
    pc.printf("Boot");

    while(1) {

        TX=1;//START
        t.reset();
        t.start();
        TX=0;//START
        t.stop();
        pc.printf("Time:%d useconds.\n",t.read_us());
        wait_ms(300);
  }
}

Serial monitor showed like follows.

Time:8 useconds.
Time:7 useconds.
Time:7 useconds.
Time:8 useconds.
Time:7 useconds.
Time:8 useconds.
      :
      :

According to this, it takes about 7.5μs.

104μs-7.5μs=96.5μs. It's comepelely same as center of range of UART_DELAY:96.5μs.

Therefore,to use mbed softwareSerial in actual usage, you had better to set 7.5μs less than theoritical value. Or,you migiht use Ticker.

I'm satisfied about TX as my experiment.
So I'll refeactor it,implement putc printf and RxIrq.
I'll maybe publish the code in my github.

To Be continued for "RX" !

Imeplementing FIFO buffer is do fun :)

Discussion

markdown guide