How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

What are you developing?
Post Reply
hitachii
Posts: 22
Joined: Sat Jan 29, 2022 8:59 pm

How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by hitachii »

I have previously done this project using an Arduino Uno: https://create.arduino.cc/projecthub/in ... der-964837

The Arduino writes an arbitrary 8 bit value to PORTD, using 8 digital output pins. The command to set the register is very simple, but since Arduino is supposed to be simplified code I'm not sure if it's setting and resetting the bits, or just setting them. I'll elaborate on this below.

I looked into adapting this for the green "black pill" board and am a little confused as to what to do. The following link contains instructions for setting the GPIO registers on the Blue Pill: https://gist.github.com/iwalpola/6c36c9 ... 0a118571ca

Here's where a couple of my questions begin. The first and most general question is, what is the best method to replicate the ATMEGA328P based sample code attached? Is it sufficient to write just the lower 8 bits in the register using ODR, or would I need to reset the bits for each cycle using BSRR and BRR?

From a previous post, I saw that there's a different syntax for the Black Pill boards, where on the Blue Pill would be:

Code: Select all

GPIOA->regs->ODR = 0b0011000000000100; //note,  binary
The Black Pill equivalent is:

Code: Select all

GPIOA->ODR = 0b0011000000000100;
If that's all I need to do to adapt the R2R DAC example code, then we're all set and that answers my question! But, if I need to use BRR and BSRR, the Black Pill core only recognizes BSRR like so:

Code: Select all

GPIOA->BSRR...
BRR is not recognized and does not compile. So if it is necessary for me to use BRR and BSRR to adapt the code, how would I go about this? If ODR suffices, then this is not necessary but maybe it is good to know for anyone looking in the future.

Thanks in advance!
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by Bakisha »

RM0368, page 161

Code: Select all

GPIOA->BSRR = uint32_t ( bits );
In short, upper 16 bits of BSSR resets corresponding bits (1=reset, 0=don't change), and lower 16bit set corresponding bits (1=set, 0=don't change).
Set bits have priority over reset bits.
BSRR - Bit Set/Reset Register
Clipboard02.jpg
Clipboard02.jpg (94.21 KiB) Viewed 3269 times
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by ag123 »

just 2 cents, if you are changing all the bits in one go, you may as well use ODR.
for BSRR, to do the same, it may be 2 transactions, first reset all bits, then set the bits again separately.

the alternate would be to do things like

Code: Select all

GPIOA->BSRR = value | (~ value << 16);
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by Bakisha »

ag123 wrote: Sun May 15, 2022 9:33 am just 2 cents, if you are changing all the bits in one go, you may as well use ODR.
for BSRR, to do the same, it may be 2 transactions, first reset all bits, then set the bits again separately.

the alternate would be to do things like

Code: Select all

GPIOA->BSRR = value | (~ value << 16);
I agree. In this case (R2R 8bit ladder), ODR is much simpler and faster.
BSSR is good when a single bit need to be set/reset without the need of reading for rest of bits in ODR.
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 26
Location: Prudnik, Poland

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by GonzoG »

hitachii wrote: Sun May 15, 2022 1:33 am
From a previous post, I saw that there's a different syntax for the Black Pill boards, where on the Blue Pill would be:

Code: Select all

GPIOA->regs->ODR = 0b0011000000000100; //note,  binary
The Black Pill equivalent is:

Code: Select all

GPIOA->ODR = 0b0011000000000100;
Those commands differ not because they are for blue/black pills. They are different because they are from different cores.
In STM32 core you use GPIOx->ODR for all boards.
GPIOx->regs->ODR if for libmaple based cores.

But depending on what other ports will you use using ODR might not be possible as it changes all 16 ports.
If you want to change only 8 ports you need to use BSRR. Use higher 16 bits to reset ports (set them to 0) and lower 16 bit to set ports to 1.

Or you can use serial to parallel shift registers (eg. 74HC595) and easily get much higher resolution. Sending 16 bits to two 74HC595 registers takes about 4us on F401 (using digitalWriteFast()).
hitachii
Posts: 22
Joined: Sat Jan 29, 2022 8:59 pm

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by hitachii »

ag123 wrote: Sun May 15, 2022 9:33 am just 2 cents, if you are changing all the bits in one go, you may as well use ODR.
for BSRR, to do the same, it may be 2 transactions, first reset all bits, then set the bits again separately.

the alternate would be to do things like

Code: Select all

GPIOA->BSRR = value | (~ value << 16);
perfect, thank you this is exactly the answer I hoped to hear! Had a feeling I was complicating things.
Bakisha wrote: Sun May 15, 2022 10:02 am I agree. In this case (R2R 8bit ladder), ODR is much simpler and faster.
BSSR is good when a single bit need to be set/reset without the need of reading for rest of bits in ODR.
and thanks for confirming it!
GonzoG wrote: Sun May 15, 2022 10:09 am
Or you can use serial to parallel shift registers (eg. 74HC595) and easily get much higher resolution. Sending 16 bits to two 74HC595 registers takes about 4us on F401 (using digitalWriteFast()).
Will consider this! I have a few lying around a didn't know the write speed was so fast compared to direct port manipulation.
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 26
Location: Prudnik, Poland

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by GonzoG »

hitachii wrote: Sun May 15, 2022 3:43 pm
GonzoG wrote: Sun May 15, 2022 10:09 am
Or you can use serial to parallel shift registers (eg. 74HC595) and easily get much higher resolution. Sending 16 bits to two 74HC595 registers takes about 4us on F401 (using digitalWriteFast()).
Will consider this! I have a few lying around a didn't know the write speed was so fast compared to direct port manipulation.
Generally using shift registers is much slower then using BSSR, because with shift registers you need at least 3 port operations for each bit of data
and BSRR needs just few (or even 1, cannot find information about it) CPU cycles for all 16 ports.
But if you need to calculate values for BSRR the difference might be much smaller.

I use 74HC595 and 74HC165 quite often so I've wrote functions to send 8b and 16b using just 1 function:

Code: Select all

void regOut8(uint8_t dataPin,uint8_t clkPin, uint8_t latchPin, int8_t bOrder, uint8_t data){
	digitalWrtiteFast(digitalPinToPinName(latchPin),0);
	for(uint8_t i=0;i<8;i++)
	{
		if(bOrder==LSBFIRST)
			digitalWrtiteFast(digitalPinToPinName(dataPin),(data>>i)&1);
		else
			digitalWrtiteFast(digitalPinToPinName(dataPin),(data<<i)&0x80);
		digitalWrtiteFast(digitalPinToPinName(clkPin),1);
		digitalWrtiteFast(digitalPinToPinName(clkPin),1);
		digitalWrtiteFast(digitalPinToPinName(clkPin),0);
	}
	digitalWrtiteFast(digitalPinToPinName(latchPin),1);
}
void regOut16(uint8_t dataPin,uint8_t clkPin, uint8_t latchPin, int8_t bOrder, uint16_t data){
	digitalWrtiteFast(digitalPinToPinName(latchPin),0);
	for(uint8_t i=0;i<16;i++)
	{
		if(bOrder==LSBFIRST)
			digitalWrtiteFast(digitalPinToPinName(dataPin),(data>>i)&1);
		else
			digitalWrtiteFast(digitalPinToPinName(dataPin),(data<<i)&0x8000);
		digitalWrtiteFast(digitalPinToPinName(clkPin),1);
		digitalWrtiteFast(digitalPinToPinName(clkPin),1);
		digitalWrtiteFast(digitalPinToPinName(clkPin),0);
	}
	digitalWrtiteFast(digitalPinToPinName(latchPin),1);
}
The doubled line with "digitalWrtiteFast(digitalPinToPinName(clkPin),1);" is necessary because F401 and F411 are too fast for 74HC595 and it often did not trigger bit shift.
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: How do I adapt this 8 bit ladder DAC for STM32F401 Black Pill?

Post by ozcar »

Some STM32 processors have built-in DAC, so if you used one of those you would not need the resistor ladder.

As for writing to ODR, that should be very simple if you could arrange things to use say bit 7 to bit 0 for the DAC lines in sequence high-order to low order, with the other 8 GPIOs of the port unused. If you need to use the other lines for something else, then you would have to avoid disturbing those, and that can get a bit complicated (not an issue on the Uno, as ports are only 8 bits wide).
Post Reply

Return to “Projects”