Single pin Hardware serial

Post here first, or if you can't find a relevant section!
User avatar
Alextrical
Posts: 39
Joined: Tue Aug 02, 2022 12:59 pm
Location: Cornwall, UK

Single pin Hardware serial

Post by Alextrical »

I'm currently struggling to get half duplex serial working on a BigTreeTech EBB42 board

Unfortunately this design has connected a TMC2209 UART to PA15 which is a hardware RX pin.

I can see that it's possible to get the hardware serial to run in Half Duplex mode, but that looks to be using the TX pin. Looking at the spec sheet for the MCU I can see it should be possible to swap the TX and RX pins with setting a register. Is setting this register possible with STM32DUINO?
unknown-4.png
unknown-4.png (42.58 KiB) Viewed 2020 times
And if so would this allow hardware half duplex to send and receive signals over the RX / PA15 pin
by ozcar » Tue Aug 23, 2022 4:26 am
Alextrical wrote: Mon Aug 22, 2022 4:31 pm It seems like I'm not able to set the register bit with the
USART2->CR2 |= 1 << 15;
command

the CR2 register looks empty before and after writing the value.

...
Perhaps the USART peripheral clock is not enabled yet where you were trying to do that.

Try setting the CR2 flag after the Serial2.begin() and see if that makes any difference (you'd still need to turn off the enable bit first, and then turn it back on). Or, try turning on the peripheral clock via RCC_APBENR1 as the very first thing.
Go to full post
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Single pin Hardware serial

Post by ag123 »

for single pin, you would likely need to patch the codes and update the registers to make it work.
one way is to look in the core review how HardwareSerial is implemented.
Then you could copy that out and make a new cpp class and h file in your sketch folder for instance, name it differently so that you can update your custom HardwareSerial.

it isn't as easy as you would need additional calls to swap the direction for instance. This isn't there in the normal 'Serial' interface
https://www.arduino.cc/reference/en/lan ... on/serial/

you could also try to see if you can simply write a function and just update the registers while using the standard HardwareSerial.
it is still quite similar to a custom HardwareSerial and you would need to review codes and the ref manual to implement that.
User avatar
Alextrical
Posts: 39
Joined: Tue Aug 02, 2022 12:59 pm
Location: Cornwall, UK

Re: Single pin Hardware serial

Post by Alextrical »

Looking at a similar post from the past, this looks pretty close to what I need.
However it seems like that uses the TX pin for the half duplex functionality. However it also looks like there is a register to swap the hardware RX and TX pins. I'm not sure how to set bit 15 to swap the pins for the UART that PA15 is part of

Would this be possible with the setting of the register, and using the hardware half duplex?
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Single pin Hardware serial

Post by dannyf »

assuming that you are using cmsis.

1. find the uart instance in the header file. it is likely something like USART1 or USART2.
2. the register is CR2 per the datasheet.
3. UARTn->CR2 |= 1<<15; sets the bit. UARTn->CR2 &=~(1<<15); clears it.

or just use a diode / transistor.
User avatar
Alextrical
Posts: 39
Joined: Tue Aug 02, 2022 12:59 pm
Location: Cornwall, UK

Re: Single pin Hardware serial

Post by Alextrical »

I assume/hope I'm using cmsis too, I believe that is the default, and I haven't requested that to change.
The header file you are referring to, I assume is the following file that matches the BlackPill

The UART I'm trying to use is UART2

I unfortunately cant use a Diode or Resistor due to the constraints imposed my a commercially produced circuit, and also the awareness that most end users i'm expecting to use the end software are unlikely have the skills or tools to solder, and even less likely able to retrofit a component where it isn't designed to go. I'm hoping to make the open source project (PolyFormer) as easy and cheap as possible, hence the odd constraints I'm trying to work around

I have found that i have another issue, that the pins i'm trying to use are the alternative pins for USART2, the default being USART2_RX=PD6 & USART2_TX=PD5.
Now I need to figure out how to change this over to USART2_RX=PA15 & USART2_TX=PA14 before doing the register change
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Single pin Hardware serial

Post by ag123 »

if you have the 'swap' feature, you may like to test it out after all.
apparently various 'other' mcus (e.g. stm32f103cx (blue pill)) may not have it)

however, for 'single pin', it may need to use the TX pin after all. apparently, as i read further in the ref manual for stm32f103c8 (blue pill).
'disable' transmit is about the same as making that pin pinMode(pin, INPUT), I've not read the ref manual for that on your board.
and accordingly RX would be able to read the signals coming in on TX pins.
so transmitting again probably means pinMode(pin, OUTPUT) and I'm not sure if we'd need to tweak the alt functions.

TMC2209 (has 2 selectable bits gpio) and TMC2208 (worse) none, one of the conundrum is to share that pin as like SPI.
TMC2208 can't do that without an extra hc74xx multiplexer chip and some resistors.
only TMC2130 can perfectly do SPI (i.e. it has chip select pin) and accordingly, even driving the motors can be done completely with SPI alone.
https://www.trinamic.com/products/integ ... s/tmc2130/
but that this is a more expensive chip
User avatar
Alextrical
Posts: 39
Joined: Tue Aug 02, 2022 12:59 pm
Location: Cornwall, UK

Re: Single pin Hardware serial

Post by Alextrical »

The data sheet for the STM32G0B1CBT can be found here
the Reference manual can be found here
The schematic for the PCB I'm trying to work with is here

I only need to communicate with a single TMC2209 with address 00, as this is what the board has been hardwired for.
the TMC2209 can also be driven completely by serial, with no need for STEP/DIR (this is the end goal)

There is a swap function for the G0B1 series, described as Bit15 in section 34.7.3 on page 1121 of the reference manual linked above.
Unfortunately trying to set the bit as suggested, with

Code: Select all

USART2->CR2 |= 1 << 15; //Set pin swap
the USART pin doesn't swap.
From the reference manual

Code: Select all

Bit 15 SWAP: Swap TX/RX pins
This bit is set and cleared by software.
0: TX/RX pins are used as defined in standard pinout
1: The TX and RX pins functions are swapped. This enables to work in the case of a cross-wired
connection to another UART.
This bitfield can only be written when the USART is disabled (UE = 0).
It looks like Bit 0 in CR1 has to be set to 0, however the following code doesn't achieve the desired result

Code: Select all

//HardwareSerial Serial2(USART2); //RX, TX
HardwareSerial Serial2(PA15, PA14_ALT1); //Alternative Pins in USART2

void setup() {
  //  Serial2.setRx(PA_15); // RX using pin name PY_n
  //  Serial2.setTx(PA_14_ALT1); // TX using pin name PY_n
  USART2->CR1 &= ~(1 << 0); //Disable USART
  delay(100);
  USART2->CR2 |= 1 << 15; //Set pin swap
  delay(100);
  USART2->CR1 |= 1 << 0; //EnableUSART
  delay(100);
  Serial2.begin(9600);
  pinMode(PA13, OUTPUT);
}

void loop() {
  digitalWrite(PA13, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial2.println("HB");
  delay(250);                       // wait for a second
  digitalWrite(PA13, LOW);    // turn the LED off by making the voltage LOW
  Serial2.println("HB");
  delay(250);                       // wait for a second
}
am I missing anything obvious?
User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Single pin Hardware serial

Post by fpiSTM »

Lookin at the reference manual, it seems it could work.
Anyway, it would requires some test because some configuration comes from the ParipheralPins.c file and in this file pins are not inverted.
Maybe configure with the default Tx pin the swap could work.
User avatar
Alextrical
Posts: 39
Joined: Tue Aug 02, 2022 12:59 pm
Location: Cornwall, UK

Re: Single pin Hardware serial

Post by Alextrical »

It seems like I'm not able to set the register bit with the
USART2->CR2 |= 1 << 15;
command

the CR2 register looks empty before and after writing the value.
CR1 is empty until Serial2.begin is issued too.

Code: Select all

HardwareSerial Serial2(USART2);

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }
  
  MSBFunc((long)USART2->CR1);
  MSBFunc((long)USART2->CR2);
  
  USART2->CR2 |= 1 << 15;

  MSBFunc((long)USART2->CR1);
  MSBFunc((long)USART2->CR2);
  
  Serial2.setRx(PA_15); // using pin name PY_n
  Serial2.setTx(PA_14_ALT1); // using pin name PY_n
  Serial2.begin(9600);
  pinMode(PA13, OUTPUT);

  MSBFunc((long)USART2->CR1);
  MSBFunc((long)USART2->CR2);
}

void loop() {
  digitalWrite(PA13, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial2.println("HB");
  delay(250);                       // wait for a second
  digitalWrite(PA13, LOW);    // turn the LED off by making the voltage LOW
  Serial2.println("HB");
  delay(250);                       // wait for a second
}

void LSBFunc(long var) {
  Serial.print("0b");
  for (int i = 0; i < 32; i++)  {
    Serial.print(((var >> i) & 1) == 1 ? "1" : "0");
  }
  Serial.println();
}

void MSBFunc(long var) {
  Serial.print("0b");
  for (unsigned long test = 0x80000000; test; test >>= 1) {
    Serial.write(var  & test ? '1' : '0');
  }
  Serial.println();
}
Is there an alternative way to write to that register, or a list of available register names. I'm not sure where to look next
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Single pin Hardware serial

Post by ozcar »

Alextrical wrote: Mon Aug 22, 2022 4:31 pm It seems like I'm not able to set the register bit with the
USART2->CR2 |= 1 << 15;
command

the CR2 register looks empty before and after writing the value.

...
Perhaps the USART peripheral clock is not enabled yet where you were trying to do that.

Try setting the CR2 flag after the Serial2.begin() and see if that makes any difference (you'd still need to turn off the enable bit first, and then turn it back on). Or, try turning on the peripheral clock via RCC_APBENR1 as the very first thing.
Post Reply

Return to “General discussion”