I have worked out a solution for my problem.
This solution will work for all STM32F405XX µC.
In the code below 300 baud are only on UART’s (Com2, Com3) supported that are connected to the low speed bus APB1. If you want to use it with Com1 you have to modify RCC_CFGR_PPRE1_16 and RCC_CFGR_PPRE1_4.
If you want to run at 300 Baud 7E1 then you have to change the clock devider for APB1 from 4 to 16, now the bus is running with 10,5 Mhz.
**** Be carefull other peripherals also use this bus, never set the clock devider lower than 4 ********
When we calculate the baudrate as in the manual described, we get
10500000 / (16 * 300) = 2187,5 // this number must be smaler than 2^12, thats the reason why we have to adjust the clock devider
This value is devided into the integer and the fractional part, like in the manual discribed we get
UART_BRR = 0x88B8
// This section is only necessery because there is a bug in NETMF or in the porting code.
// So that the parity bit is set wrong
To get 7E1 working we have the set the M, PCE and PE Bit in the UART_CR1 register right. The STM32F4 supports 4 possible frame-formats:
=================================================
M bit | PCE bit | USART frame
0 | 0 | SB | 8 bit data | STB
0 | 1 | SB | 7-bit data | PB | STB
1 | 0 | SB | 9-bit data | STB
1 | 1 | SB | 8-bit data | PB | STB
The PE bit defines only if it is even (0) or odd (1)
Importend as I have observed if you use 7E1 and call Read or ReadByte you get the 7 data bits and the parity bit.
I have writen a wrapper class for the serialport for better handling:
namespace Pps.IO
{
using System;
using System.IO.Ports;
using GHI.Processor;
using Microsoft.SPOT;
public class SerialPort : System.IO.Ports.SerialPort
{
// COM1
private const uint USART6_BASE_ADDRESS = 0x40011400;
// COM2
private const uint USART2_BASE_ADDRESS = 0x40004400;
// COM3
private const uint USART3_BASE_ADDRESS = 0x40004800;
private const uint RCC_BASE_ADDRESS = 0x40023800;
private const uint USART_CR1_PCE = 0x400;
private const uint USART_CR1_M = 0x1000;
private const uint USART_CR1_PE = 0x200;
private const uint RCC_CFGR_PPRE1_16 = 0x1C00;
private const uint RCC_CFGR_PPRE1_4 = 0x1400;
private const uint BAUD_300 = 0x88B8;
private readonly Register USART_BRR;
private readonly Register USART_CR1;
private readonly Register RCC_CFGR;
public SerialPort(string portName)
: this(portName, 9600, Parity.None, 8)
{
}
public SerialPort(string portName, int baudRate, Parity parity, int dataBits)
: base(portName, baudRate, parity, dataBits)
{
uint baseAddress = 0;
switch (portName.ToLower())
{
case "com1":
baseAddress = USART6_BASE_ADDRESS;
break;
case "com2":
baseAddress = USART2_BASE_ADDRESS;
break;
case "com3":
baseAddress = USART3_BASE_ADDRESS;
break;
default:
throw new ArgumentException("invalid portname", "portName");
}
this.USART_BRR = new Register(baseAddress + 0x08);
this.USART_CR1 = new Register(baseAddress + 0x0C);
this.RCC_CFGR = new Register(RCC_BASE_ADDRESS + 0x08);
this.RCC_CFGR.Value = (this.RCC_CFGR.Value & ~RCC_CFGR_PPRE1_16) | RCC_CFGR_PPRE1_4;
}
public new void Open()
{
uint cr1 = 0x0;
base.Open();
cr1 = this.USART_CR1.Value;
if (this.BaudRate == 300)
{
this.RCC_CFGR.Value |= RCC_CFGR_PPRE1_16;
this.USART_BRR.Value = BAUD_300;
}
else
{
this.RCC_CFGR.Value = (this.RCC_CFGR.Value & ~RCC_CFGR_PPRE1_16) | RCC_CFGR_PPRE1_4;
}
if (this.DataBits == 8 && this.Parity == Parity.None && this.StopBits != StopBits.None)
{
cr1 &= ~USART_CR1_PCE;
cr1 &= ~USART_CR1_M;
cr1 &= ~USART_CR1_PE;
}
else if (this.DataBits == 7 && (this.Parity == Parity.Even || this.Parity == Parity.Odd) && this.StopBits != StopBits.None)
{
cr1 |= USART_CR1_PCE;
cr1 &= ~USART_CR1_M;
if (this.Parity == Parity.Even)
{
cr1 &= ~USART_CR1_PE;
}
else
{
cr1 |= USART_CR1_PE;
}
}
else if (this.DataBits == 9 && this.Parity == Parity.None && this.StopBits != StopBits.None)
{
cr1 &= ~USART_CR1_PCE;
cr1 |= USART_CR1_M;
cr1 &= ~USART_CR1_PE;
}
else if (this.DataBits == 8 && (this.Parity == Parity.Even || this.Parity == Parity.Odd) && this.StopBits != StopBits.None)
{
cr1 |= USART_CR1_PCE;
cr1 |= USART_CR1_M;
if (this.Parity == Parity.Even)
{
cr1 &= ~USART_CR1_PE;
}
else
{
cr1 |= USART_CR1_PE;
}
}
else
{
throw new InvalidOperationException("no valid frame format");
}
this.USART_CR1.Value = cr1;
}
public override void Close()
{
base.Close();
this.RCC_CFGR.Value = (this.RCC_CFGR.Value & ~RCC_CFGR_PPRE1_16) | RCC_CFGR_PPRE1_4;
}
public override int ReadByte()
{
if (this.Parity != System.IO.Ports.Parity.None)
{
return base.ReadByte() & ~0x80;
}
else
{
return base.ReadByte();
}
}
}
}