cancel
Showing results for 
Search instead for 
Did you mean: 

WeAct BluePill + : SPI1 does not work (works with older generic BluePills !)

mwalt.3
Associate III

Hi all 

I made a little program under arduino IDE (but I write directly into the registers), in order to test the command of WS2812b chips via the SPI1 MOSI pin : It worked perfectly with older BluPill boards I have got.

Tried the same thing with BluePill + from WeAct  official store , it does not work. Even the SPI1->CR1 register is not set properly : it must be 0b1100111 , but it is actually 0b100011 : which is wrong , the Master Mode and SPI enable bits can not be set ...

Any idea , please ? thanks !

/* spi_dma_ws.h */

#define ws_chips 8  // number of RGB chips

void spi_dma_transmit();

extern SPI_HandleTypeDef hspi1;
extern uint16_t adc_pa5;

// some colours
const uint8_t ws_black[3] = { 0, 0, 0 };
const uint8_t ws_green[3] = { 25, 0, 0 };
uint8_t ws_green_adc[3] = { 0, 0, 0 };
const uint8_t ws_red[3] = { 0, 25, 0 };
const uint8_t ws_blue[3] = { 0, 0, 25 };
const uint8_t ws_white[3] = { 25, 25, 25 };
const uint8_t ws_purple[3] = { 0, 25, 25 };
const uint8_t ws_yell[3] = { 25, 25, 0 };
const uint8_t ws_turc[3] = { 25, 0, 25 };


uint8_t ws3[ws_chips][3];        // has the 3 colours of each RGB chip
uint8_t ws33[ws_chips * 3 * 3];  // has the 3 SPI bytes for each the 3 colours of each RGB chip
//  example with some colours
void ws_3() {
  for (int c = 0; c < 3; c++) {
    ws3[0][c] = ws_green_adc[c];
    ws3[1][c] = ws_red[c];
    ws3[2][c] = ws_blue[c];
    ws3[3][c] = ws_white[c];
    ws3[4][c] = ws_black[c];
    ws3[5][c] = ws_yell[c];
    ws3[6][c] = ws_turc[c];
    ws3[7][c] = ws_purple[c];
  }
}


//  7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
// |‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._|‾|_._  // 146 73 36
//  128   64    32    16    8     4     2     1
// |‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_|‾.‾|_  // 219 109 182
void ws_33() {
  uint8_t p = 0, w;
  ws_3();
  ws_green_adc[0] = adc_pa5 / 4;
  for (int ws = 0; ws < sizeof(ws3) / 3; ws++) {
    for (int c = 0; c < 3; c++) {
      w = ws3[ws][c];
      ws33[p] = 0b10010010;
      if (w & 128) ws33[p] += 0b01000000;
      if (w & 64) ws33[p] += 0b00001000;
      if (w & 32) ws33[p] += 1;
      p++;
      ws33[p] = 0b01001001;
      if (w & 16) ws33[p] += 0b00100000;
      if (w & 8) ws33[p] += 0b00000100;
      p++;
      ws33[p] = 0b00100100;
      if (w & 4) ws33[p] += 0b10000000;
      if (w & 2) ws33[p] += 0b00010000;
      if (w & 1) ws33[p] += 0b00000010;
      p++;
    }
  }
}


void send_ws() {
  ws_33();
  spi_dma_transmit();
}


void spi_dma_init() {
  // Enable Port A clock // Enable SPI Clock
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN;
  // Mode: Output, Speed: 10MHz // Alternate function push-pull
  GPIOA->CRL &= ~(GPIO_CRL_CNF7 | GPIO_CRL_MODE7);     // MOSI = PA7
  GPIOA->CRL |= (GPIO_CRL_CNF7_1 | GPIO_CRL_MODE7_0);  // 10.01

  // SPI Mode: Master
  SPI1->CR1 |= SPI_CR1_MSTR;
  // 100: BaudRate = fPCLK/32 // + CPOL + CPHA
  SPI1->CR1 |= SPI_CR1_BR_2 | SPI_CR1_CPOL | SPI_CR1_CPHA;
  // Set TXDMA bit in CR2 → enable DMA transmit
  SPI1->CR2 |= SPI_CR2_TXDMAEN;
  // SPI Enable
  SPI1->CR1 |= SPI_CR1_SPE;

  // DMA Configuration  // Enable DMA Clock
  RCC->AHBENR |= RCC_AHBENR_DMA1EN;
  // Priority Level = 0b10 → High
  DMA1_Channel3->CCR |= DMA_CCR_PL_1;
  // Memory Increment mode + Direction Read from Memory
  DMA1_Channel3->CCR |= DMA_CCR_MINC | DMA_CCR_DIR;  // no need for interrupt
  // Set Memory Address → Peripheral Address
  DMA1_Channel3->CMAR = (uint32_t)ws33;
  DMA1_Channel3->CPAR = (uint32_t)&SPI1->DR;
}

void spi_dma_transmit() {
  // stop DMA to refill CNDTR
  DMA1_Channel3->CCR &= ~DMA_CCR_EN;
  DMA1_Channel3->CNDTR = sizeof(ws33);
  // launch DMA
  DMA1_Channel3->CCR |= DMA_CCR_EN;
  ///Serial.print(sizeof(ws33));
}
/* spi_dma_ws.ino */

#include "spi_dma_ws.h"

uint16_t adc_pa5;

void setup() {
	Serial.begin(115200);
	spi_dma_init();
	pinMode(PB2, OUTPUT);
	delay(2000);
}

void loop() {
	delay(444);
	send_ws();
	adc_pa5 = analogRead(PA_5);

	Serial.print("GPIOA->CRL ");  /// debug
	Serial.println(GPIOA->CRL, BIN);
	Serial.print("SPI1->CR1 ");
	Serial.println(SPI1->CR1, BIN);
	Serial.print("SPI1->CR2 ");
	Serial.println(SPI1->CR2, BIN);
	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);  // BluePill+ LED
}

 

13 REPLIES 13
mwalt.3
Associate III

suite :
(finally I had the same problem with my older bluepills)

I did some tests , and realized that at the start , the thing works fine , the config of SP1->CR1 is ok , and the pin outputs the right signals , but after having put the bluepill on my PCB , or after having touched some pin of the naked bluepill with a finger , things were going wrong : SPI1->CR1 takes the wrong value , and only a reset can make it ok again ; what a mess !

I then realized that the problem occurs when I touch a given pin , which is PB4 aka SPI1 NSS : on my PCB , this pin is reused as an ADC input , and LOW level because of a shunt resistor to the GND. My thought was then that the problem is because this pin is tied to LOW , so I tried to configure it as OUTPUT HIGH ... and the problem disappeared.!

I had then to find another way , because I don't want to change my PCBs : I  put the pin as analog input , and tried to set the SSOE bit , and prayed : gotcha !

the line #87 of my code is :
SPI1->CR2 |= SPI_CR2_TXDMAEN ;
it must be :
SPI1->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_SSOE ;

If I get an official STM32F103 board , I will investigate and let you know

Bit 2 SSOE: SS output enable
0: SS output is disabled in master mode and the cell can work in multimaster configuration
1: SS output is enabled in master mode and when the cell is enabled. The cell cannot work
in a multimaster environment.

Alex410
Associate II

Finally!!!!!

mwalt.3
Associate III

yes , I also had problems to make timer3 to work , but it was more related to stm32duino : it worked when I wrote directly into the registers

STM32Duino issues should go here: https://www.stm32duino.com/

Or here: https://github.com/orgs/stm32duino/discussions

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.