i have a project that i use SPI1 in order to transfer data ,
PA7 MOSI1
PA6 MISO1
PA5 SCK1
PA4 NSS1
the board that i m using is hard to reach the MOSI pin PA7 basically its not breaked out anywhere i have to solder over MCU , i have access to PA6 though ,
So i am wondering before i make my next move , Is there any quick and easy way to Bit Bang data from MOSI1 to MISO1 ,
any example out there will save me tons of hours
https://github.com/nickgammon/bitBangedSPI
I’ve been using it with max7219 and BluePill and it works.
Something like this (not tested this way, you have to spend some pounds of time to elaborate):
// bitBangedSPI (const int mosi, const int miso, const int sck, const unsigned long delayUs = 4)
bitBangedSPI bbSPI(PA33, PA44, PA55);
..
bbSPI.begin();
..
inbyte = bbSPI.transfer(outbyte);
..
I am porting it into my code , i ll see how it goes.

- F1_SPI1_remap.jpg (53.11 KiB) Viewed 551 times
not sure what that means.
you can certainly bitbang any pins but if the pin isn’t routed out, not sure if it is instead better to bitbang a pin that is routed out.
[stevestrong – Mon Oct 09, 2017 11:34 am] –
Before using software SPI, you should maybe first consider remapping of the SPI pins, if those remapped pins are available:
F1_SPI1_remap.jpgNSS is not relevant though.

In my case i want PA6 as MOSI . i want only to send data , the alternate pins (PB5,PB4,PB3….) of SPI1 are not available with my equipment . (at least not breaked out) bad luck i guess.
just ported the code without errors , i ll check later if my data pass through PA6 ..
If speed is not a concern for you, then it should be fine.
Otherwise you should use direct memory writes to toggle the pins.
[stevestrong – Mon Oct 09, 2017 1:21 pm] –
That code uses digitalWrite() function to toggle the pin level.
If speed is not a concern for you, then it should be fine.
Otherwise you should use direct memory writes to toggle the pins.
I think that the Speed is too slow..
How can i use direct memory writes ? any example?”
// clock high
digitalWrite (sck_, HIGH);
// delay between rise and fall of clock
delayMicroseconds (delayUs_);
// clock low
digitalWrite (sck_, LOW);
// delay between rise and fall of clock
delayMicroseconds (delayUs_);
} // end of for loop, for each bit
//transmission on sck's rising edge
void spi1_write(unsigned char data_t) {
unsigned char mask = 0x80; //start with the most signifcant bit
#if defined(SPI1_MOSI)
IO_OUT(SPI1_DDR, SPI1_MOSI); //mosi as output
#endif
IO_CLR(SPI1_PORT, SPI1_SCK); //default state of sck: low
while (mask) {
IO_CLR(SPI1_PORT, SPI1_SCK); //clear spi_sck
#if defined(SPI1_MOSI)
if (data_t & mask) IO_SET(SPI1_PORT, SPI1_MOSI); //send the data
else IO_CLR(SPI1_PORT, SPI1_MOSI);
#endif
IO_SET(SPI1_PORT, SPI1_SCK); //send on the rising edge
SPI1_DELAY(SPI1_DLY); //insert some delays to generate 50% dc
mask = mask >> 1; //next bit
}
//IO_CLR(SPI1_PORT, SPI1_MOSI); //clear mosi
//IO_CLR(SPI1_PORT, SPI1_SCK); //clear sck
}
[Pito – Mon Oct 09, 2017 3:15 pm] –
Comment out all delays if you need more speed (bitBangedSPI.cpp):First try to use this code, when you gather more experience with stm32 you may replace the digitalWrite()..
I just tried it , i do see some speed but , this isnt the issue though.
i suspect that i am making something wrong , and i guess its the intrerupt that i am not taking care of , so i will post my code in order to get things straigh,
So my normal code before the bit bang is
........
dma_init(SPIDMA_1);
dma_attach_interrupt(SPIDMA_1, DMA_CH3, &DMA1_CH3_handler);
spi_tx_dma_enable(SPI_Class->dev());
.......
// Interrupt handler for DMA (clear data output)
void DMA1_CH3_handler()
{
while(SPI_Class->dev()->regs->SR & SPI_SR_BSY);
SPI_Class->dev()->regs->DR = 0;
}
///SEND DATA
void SPI_dmaSend(uint8_t *transmitBuffer, uint16_t length) {
//DATA SEND INTO PA7 MOSI1
dma_setup_transfer(
SPIDMA_1, DMA_CH3, // DMA channel specification for SPI 1
&SPI_Class->dev()->regs->DR, // destination address: specify the SPI data register
DMA_SIZE_8BITS, // Destination data size: 1 byte
transmitBuffer, // source address: SRAM address
DMA_SIZE_8BITS, // Destination data size: 1 byte
DMA_MINC_MODE| // flag: cyclic
DMA_FROM_MEM | // Peripheral from memory, transfer complete interrupted
DMA_TRNS_CMPLT // Transfer complete Interrupted calling * /
);
dma_set_num_transfers(SPIDMA_1, DMA_CH3, length);
dma_enable(SPIDMA_1, DMA_CH3);
}
We have already an hardware SPI library which supports DMA: https://github.com/rogerclarkmelbourne/ … raries/SPI
As far as I know, the software (bit-bang) SPI cannot work with DMA.
You still haven’t mentioned in clear text what is your issue.
“It does not work” is not enough information.
and make the MISO of SPI1(PA6)act as a MOSI?
Because my microscope and solder station is ready to solder over the MCU the damn PA7
You are implying that you want the MCU to use the slave connections.
Did you build the hardware yourself?
If not… There must be a good reason for the manufacturer to use a non standard pin configuration
[RogerClark – Mon Oct 09, 2017 8:54 pm] –
Is your MCU acting as the Master or the Slave?You are implying that you want the MCU to use the slave connections.
Did you build the hardware yourself?
If not… There must be a good reason for the manufacturer to use a non standard pin configuration
if i understand the question corectly , Yes my MCU acting as the Master,
i already manage to use the alternate pins of SPI1 pb5 ,pb4 ,pb3 etc
afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); // release PB3 and PB5
afio_remap(AFIO_REMAP_SPI1); // remap SPI1
gpio_set_mode(GPIOB, 5, GPIO_AF_OUTPUT_PP);
gpio_set_mode(GPIOB, 3, GPIO_AF_OUTPUT_PP);
gpio_set_mode(GPIOB, 4, GPIO_INPUT_FLOATING);
gpio_set_mode(GPIOB, 3, GPIO_AF_OUTPUT_PP);
What is the hardware ?
You want to use a non-standard configuration of the SPI: outputting MOSI data on MISO pin.
That means, you have to forget any available hardware solution, forget the hardware SPI library, and forget DMA.
Available solution: software SPI (bit-banging), using the available soft SPI library – in this case, too, forget DMA.
Unlesss you decompose each bit of a data byte to a separate 16 bit data in the memory and trigger the DMA by a timer to send the decomposed 16 bits to the BSRR register directly. It is complicated, and the overhead to prepare the decomposed data in memory would cost you more time than just directly bit-bang the data out to the peripheral.
For GPIO fast output using direct register access please see:
– this thread: http://stm32duino.com/viewtopic.php?f=18&t=303
– or check an available solution (16 bit parallel LCD library): https://github.com/stevstrong/Adafruit_ … M32.h#L116
// Set A6, A7, A15
// digitalWrite(PA6, HIGH);
// digitalWrite(PA7, HIGH);
// digitalWrite(PA15, HIGH);
GPIOA->regs->BSRR = 0b1000000011000000;
// Clear B6, B7, B15
// digitalWrite(PB6, LOW);
// digitalWrite(PB7, LOW);
// digitalWrite(PB15, LOW);
GPIOB->regs->BRR = 0b1000000011000000;
@OP: the standard pins of a peripheral like the SPI port are those pins, because the micro controller has built in hardware that allows you to communicate via that protocol in a fast & efficient way.
Bitbanging means that you don’t use such hardware, but rather implement that protocol using simple manipulation of the ports of the microcontroller. This is slower & less efficient (it costs the microcontroller a lot more work to achieve the same thing).
As you’re switching from using the built in peripheral to something completely custom, there is no “half way” mode. You cant use the default peripheral for everything except for the mosi pin, which you then “bitbang”.
You either bitbang it all, or nothing at all.
So if you choose to use spi on your 3d printer board on pins not supported by the stm32 hardware, you can indeed resort to bitbanging it to other pins. And from that point on, it doesn’t matter whether you still keep most pins of the SPI port of the stm32, or just go to entirely different pins. As soon as you’re no longer using the default pins, you can’t use the built in spi port anymore, and are going to a custom implementation for everything.
I hope this clears it up.
