Demo of the usage USBDevice library with Blue Pill STM32F103C8T6 board.

Dependencies:   USBDevice

STM32F103C8T6 USBSerial Demo

This project contains demo of the USB serial usage for a cheap developer board Blue Pill with STM32F103C8T6 mcu.

/media/uploads/vznncv/stm32f103c8_usbserial.jpg

The USB serial port provides a good communication channel between PC and microcontroller. Especially it can be useful for a debug purposes.

Notes

  • by the specifications this board has only 64KB of the flash, but actually it can have 128KB, that will be useful for a debug builds as it requires about 100KB of the flash for this demo.
  • the board can have some problems with an USB because it has wrong value of the pull-up resistor
  • for steady reading of data from a serial port, the project contains python script serial_reader.py (it requires PySerial and six python libraries), that is steady to the board reloading
  • the project depends on the fork of the USBDevice library. This fork contains some fixes and support of the BLUE_PILL_STM32F103C8 target.
  • the mbed-os now contains correct code for a clock initialization of the BLUE_PILL_STM32F103C8 target, so you don't need to adjust the board clocks separately
Committer:
Konstantin Kochin
Date:
Fri Aug 04 18:41:22 2017 +0300
Revision:
0:24604e97c40c
Initial release

The project contains autogenerated makefile for a debug build,
the program itself (main.cpp) and the helper python script
'serial_reader.py' to read a data from a serial port.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Konstantin Kochin 0:24604e97c40c 1 #!/usr/bin/env python
Konstantin Kochin 0:24604e97c40c 2 from __future__ import print_function
Konstantin Kochin 0:24604e97c40c 3
Konstantin Kochin 0:24604e97c40c 4 import argparse
Konstantin Kochin 0:24604e97c40c 5 import sys
Konstantin Kochin 0:24604e97c40c 6 from time import sleep
Konstantin Kochin 0:24604e97c40c 7
Konstantin Kochin 0:24604e97c40c 8 import serial
Konstantin Kochin 0:24604e97c40c 9 from serial.tools.list_ports import comports
Konstantin Kochin 0:24604e97c40c 10 from six import binary_type
Konstantin Kochin 0:24604e97c40c 11
Konstantin Kochin 0:24604e97c40c 12 _DEFAULT_BAUD_RATE = 115200
Konstantin Kochin 0:24604e97c40c 13
Konstantin Kochin 0:24604e97c40c 14
Konstantin Kochin 0:24604e97c40c 15 def _reset_baud_drate(serial):
Konstantin Kochin 0:24604e97c40c 16 original_baudrate = serial.baudrate
Konstantin Kochin 0:24604e97c40c 17 i = serial.BAUDRATES.index(original_baudrate)
Konstantin Kochin 0:24604e97c40c 18 if i == -1:
Konstantin Kochin 0:24604e97c40c 19 raise ValueError("Unknown baudrate {}".format(original_baudrate))
Konstantin Kochin 0:24604e97c40c 20
Konstantin Kochin 0:24604e97c40c 21 if i > 1:
Konstantin Kochin 0:24604e97c40c 22 tmp_baud_rate = serial.BAUDRATES[i - 1]
Konstantin Kochin 0:24604e97c40c 23 elif len(serial.BAUDRATES) > 1:
Konstantin Kochin 0:24604e97c40c 24 tmp_baud_rate = serial.BAUDRATES[i + 1]
Konstantin Kochin 0:24604e97c40c 25 else:
Konstantin Kochin 0:24604e97c40c 26 raise ValueError("Only one baudreate is available")
Konstantin Kochin 0:24604e97c40c 27
Konstantin Kochin 0:24604e97c40c 28 serial.baudrate = tmp_baud_rate
Konstantin Kochin 0:24604e97c40c 29 serial.baudrate = original_baudrate
Konstantin Kochin 0:24604e97c40c 30
Konstantin Kochin 0:24604e97c40c 31
Konstantin Kochin 0:24604e97c40c 32 def _read_from_serial_device(port, out=sys.stdout, reconnect_on_error=True, repeat_delay=2, **port_params):
Konstantin Kochin 0:24604e97c40c 33 print('Read from the serial port "{}" (use Ctrl+C to exit)'.format(port))
Konstantin Kochin 0:24604e97c40c 34 while True:
Konstantin Kochin 0:24604e97c40c 35 try:
Konstantin Kochin 0:24604e97c40c 36 with serial.Serial(port=port, **port_params) as com_port:
Konstantin Kochin 0:24604e97c40c 37 # hack:
Konstantin Kochin 0:24604e97c40c 38 # when you connect usb-com port of the stm32f1 first time, it will work
Konstantin Kochin 0:24604e97c40c 39 # but if you reconnect it, then it stop working, although com port readers doesn't show
Konstantin Kochin 0:24604e97c40c 40 # any error.
Konstantin Kochin 0:24604e97c40c 41 # However I found that it can be solved by 2 ways:
Konstantin Kochin 0:24604e97c40c 42 # - host rebooting (but it's very inconvenient)
Konstantin Kochin 0:24604e97c40c 43 # - changing baudrate. The new value doesn't matter, it should only be different than previous.
Konstantin Kochin 0:24604e97c40c 44 # Moreover the old values without any problems can be reverted without any problems.
Konstantin Kochin 0:24604e97c40c 45 # TODO: find reason of such strange behavior
Konstantin Kochin 0:24604e97c40c 46 _reset_baud_drate(com_port)
Konstantin Kochin 0:24604e97c40c 47 for line in com_port:
Konstantin Kochin 0:24604e97c40c 48 if isinstance(line, binary_type):
Konstantin Kochin 0:24604e97c40c 49 line = line.decode('utf-8')
Konstantin Kochin 0:24604e97c40c 50 out.write(line)
Konstantin Kochin 0:24604e97c40c 51 out.flush()
Konstantin Kochin 0:24604e97c40c 52
Konstantin Kochin 0:24604e97c40c 53 except serial.SerialException as e:
Konstantin Kochin 0:24604e97c40c 54 print("Error: {}".format(e))
Konstantin Kochin 0:24604e97c40c 55 if not reconnect_on_error:
Konstantin Kochin 0:24604e97c40c 56 break
Konstantin Kochin 0:24604e97c40c 57 sleep(repeat_delay)
Konstantin Kochin 0:24604e97c40c 58
Konstantin Kochin 0:24604e97c40c 59
Konstantin Kochin 0:24604e97c40c 60 def _guess_serial_device_name():
Konstantin Kochin 0:24604e97c40c 61 ports = list(comports())
Konstantin Kochin 0:24604e97c40c 62 if len(ports) == 1:
Konstantin Kochin 0:24604e97c40c 63 port = ports[0].device
Konstantin Kochin 0:24604e97c40c 64 elif len(ports) == 0:
Konstantin Kochin 0:24604e97c40c 65 raise ValueError("No serial devices found")
Konstantin Kochin 0:24604e97c40c 66 else:
Konstantin Kochin 0:24604e97c40c 67 print("Several serial devices are found. Please specify one of them explicitly:")
Konstantin Kochin 0:24604e97c40c 68 for port_info in ports:
Konstantin Kochin 0:24604e97c40c 69 print("- {}".format(port_info.device))
Konstantin Kochin 0:24604e97c40c 70 raise ValueError("Multiple serial devices are found.")
Konstantin Kochin 0:24604e97c40c 71
Konstantin Kochin 0:24604e97c40c 72 return port
Konstantin Kochin 0:24604e97c40c 73
Konstantin Kochin 0:24604e97c40c 74
Konstantin Kochin 0:24604e97c40c 75 def main(args=None):
Konstantin Kochin 0:24604e97c40c 76 parser = argparse.ArgumentParser(prog='serial_reader',
Konstantin Kochin 0:24604e97c40c 77 description='Helper program that read text from a serial port. '
Konstantin Kochin 0:24604e97c40c 78 'Unlike other com programs it automatically reconnect '
Konstantin Kochin 0:24604e97c40c 79 'to serial port if any error occurs. It is useful for '
Konstantin Kochin 0:24604e97c40c 80 'microcntrollers debugging when you want to reboot it and'
Konstantin Kochin 0:24604e97c40c 81 'the connection will be lost for some time.')
Konstantin Kochin 0:24604e97c40c 82 parser.add_argument('port', nargs='?', help='Serial port device name. It it is not specifies, then'
Konstantin Kochin 0:24604e97c40c 83 'it will be found automatically if it is possible')
Konstantin Kochin 0:24604e97c40c 84 parser.add_argument('--baudrate', default=_DEFAULT_BAUD_RATE,
Konstantin Kochin 0:24604e97c40c 85 help="baud rate. Default: {}".format(_DEFAULT_BAUD_RATE))
Konstantin Kochin 0:24604e97c40c 86 parsed_args = parser.parse_args(args)
Konstantin Kochin 0:24604e97c40c 87
Konstantin Kochin 0:24604e97c40c 88 if parsed_args.port is None:
Konstantin Kochin 0:24604e97c40c 89 try:
Konstantin Kochin 0:24604e97c40c 90 port = _guess_serial_device_name()
Konstantin Kochin 0:24604e97c40c 91 except Exception as e:
Konstantin Kochin 0:24604e97c40c 92 print(e)
Konstantin Kochin 0:24604e97c40c 93 sys.exit(1)
Konstantin Kochin 0:24604e97c40c 94 else:
Konstantin Kochin 0:24604e97c40c 95 port = parsed_args.port
Konstantin Kochin 0:24604e97c40c 96
Konstantin Kochin 0:24604e97c40c 97 try:
Konstantin Kochin 0:24604e97c40c 98 _read_from_serial_device(
Konstantin Kochin 0:24604e97c40c 99 port,
Konstantin Kochin 0:24604e97c40c 100 baudrate=parsed_args.baudrate
Konstantin Kochin 0:24604e97c40c 101 )
Konstantin Kochin 0:24604e97c40c 102 except KeyboardInterrupt:
Konstantin Kochin 0:24604e97c40c 103 print("Exit ...")
Konstantin Kochin 0:24604e97c40c 104
Konstantin Kochin 0:24604e97c40c 105
Konstantin Kochin 0:24604e97c40c 106 if __name__ == '__main__':
Konstantin Kochin 0:24604e97c40c 107 main()