Bluepill project transferring to Blackpill

Post here all questions related to STM32 core if you can't find a relevant section!
Post Reply
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Bluepill project transferring to Blackpill

Post by Tardishead »

Hi there
I downloaded a Bluepill project and I can't work out why this won't work out on a Blackpill STM401
It is a quadrature LFO for analogue synthesisers
I have verified my connections to the OLED and the SPI DAC - both work fine
Is it something to do with the Timer commands? Sorry I am a bit of a novice. Learning fast though!
Can someone help. It just hangs on the welcome screen and won't go any further

Code: Select all

/*
   Ed Droog
   18-01-2021

   explanation belongs to schematic.
   The main two components are the experiment board known as Blue Pill, which holds a STM32F103C8T6 processor
   and an AD5664 4 channel, 16 bits Digital to Analog Converter.
   The four outputs of the DAC are buffered and sent to a connector placed on the front panel.
   Also they go via four 2k resistors to four bi-color LED's (RED and GREEN) which are connected with their cathode to a 2.5 volt source.
   So if the output of one of the DAC channels reach a voltage of about 3 volts, the corresponding LED lights up green, below 2 volt the
   LED will light up RED.
   SW1 and SW2 form a rotary encoder to travel thru the menu where SW1 is the encoder part and SW2 is the pushbutton activated by pressing the shaft.

*/
#include <Arduino.h>
#include <math.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>
#include "sinlookup.h"
#define SPI_CS0 PA4
#define SPI_CLK PA5
#define SPI_MOSI PA7
#define sinewave      0
#define trianglewave  1
#define sawwave       2
#define squarewave    3
#define quad_one        0
#define quad_two        1
#define quad_three      2
#define quad_four       3
volatile uint8_t DACchannel1, DACchannel2, DACchannel3, DACchannel4;
volatile uint8_t display_row = 1;
volatile bool rotate_right, switched, rotated;
volatile uint8_t column, which_channel, active_channel;
volatile uint16_t SAWtemp, dacdata, SAW;
bool turned = false;
bool pushed = false;
bool left = false;
bool next = false;
bool chan_change = false;
bool wave_change = false;
bool gain_change = false;
bool timing_change = false;
volatile bool timer_tick = true;
volatile uint16_t timer_value = 10;
int prescalefactor = 0xFF;
HardwareTimer timer(TIM2);
const float pi = 3.14159267;
void overflowISR();

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0,/* reset=*/ PB5, /* clock=*/ 42, /* data=*/ 43);

void encoderISR()
{
  turned = true;
}

void encoderButtonISR()
{
  switched = true;
}

void overflowISR()
{
  timer_tick = true;
}

float dacgain[5] = {
  0.00, 0.00, 0.00, 0.00, 0.00
};

uint8_t wavearray[4][4] = {
  {1 , 2, 3, 4 },
  {5, 6, 7, 8 },
  {9, 10, 11, 12},
  {13, 14, 15, 16}
};

uint8_t addquadrant[] = {
  0, 0, 0, 0, 0
};

// Lookup table Small-waves 4*32 points
// Max. amplitude =  16
uint8_t smallookup [128] = {
  //start sine wave
  8, 10, 11, 12, 14, 15, 15, 16,
  16, 16, 15, 15, 14, 12, 11, 10,
  8, 6, 5, 4, 2, 1, 1, 0,
  0, 0, 1, 1, 2, 4, 5, 6,
  //start triangle wave
  8, 9, 10, 11, 12, 13, 14, 15,
  16, 15, 14, 13, 12, 11, 10, 9,
  8, 7, 6, 5, 4, 3, 2, 1,
  0, 1, 2, 3, 4, 5, 6, 7,
  //start saw wave
  8, 8, 9, 9, 10, 10, 11, 11,
  12, 12, 13, 13, 14, 14, 15, 15,
  0, 0, 1, 1, 2, 2, 3, 3,
  4, 4, 5, 5, 6, 6, 7, 7,
  //start square wave
  16, 16, 16, 16, 16, 16, 16, 16,
  0, 0, 0, 0, 0, 0, 0, 0,
  16, 16, 16, 16, 16, 16, 16, 16,
  0, 0, 0, 0, 0, 0, 0, 0
};

uint8_t channel1 [4] = {1, 2, 3, 4}; //startup values sinewave
uint8_t channel2 [4] = {4, 1, 2, 3}; //all 90 degrees
uint8_t channel3 [4] = {3, 4, 1, 2}; //shifted
uint8_t channel4 [4] = {2, 3, 4, 1};

uint16_t get_dacdata (uint8_t part_of_signal)
{
  switch (part_of_signal) {
    //sinewave
    case 1:
      dacdata = pgm_read_word (&sinlookup[SAW]);    //1st quadrant
      break;
    case 2:
      dacdata = pgm_read_word (&sinlookup[4095 - SAW]);  //2nd quadrant
      break;
    case 3:
      dacdata = 65535 - pgm_read_word (&sinlookup[SAW]);  //3rd quadrant
      break;
    case 4:
      dacdata = 65535 - pgm_read_word (&sinlookup[4095 - SAW]); //4th quadrant
      break;
    //trianglewave
    case 5:
      dacdata = 32768 + (8 * SAW); //1st quadrant
      break;
    case 6:
      dacdata = 65535 - (SAW * 8); //2nd quadrant
      break;
    case 7:
      dacdata = 32768 - (SAW * 8); //3rd quadrant
      break;
    case 8:
      dacdata = SAW * 8;  //4th quadrant
      break;
    //sawwave
    case 9:
      dacdata = 32768 + (4 * SAW); //1st quadrant
      break;
    case 10:
      dacdata = 49152 + (4 * SAW); //2nd quadrant
      break;
    case 11:
      dacdata = SAW * 4;        //3rd quadrant
      break;
    case 12:
      dacdata = 16384 + (4 * SAW); //4th quadrant
      break;
    //squarewave
    case 13:
      dacdata = 65535;    //1st quadrant
      break;
    case 14:
      dacdata = 65535;    //2nd quadrant
      break;
    case 15:
      dacdata = 0;        //3rd quadrant
      break;
    case 16:
      dacdata = 0;        //4th quadrant
      break;
    default:
      dacdata = 32768;
      break;
  }
  return dacdata;
}

/*
  void ext_triggerISR()
  {
  // set your trigger flag here
  }
*/

void setup_welcome_screen (void)
{
  u8g2.firstPage();
  do {
    for (uint8_t n = 0; n < 32; n++)
    {
      u8g2.drawPixel(n, smallookup[n]);
      u8g2.drawPixel(n, 30 + smallookup[32 + n]);
      u8g2.drawPixel(80 + n, smallookup[64 + n]);
      u8g2.drawPixel(80 + n, 30 + smallookup[96 + n]);
    }
    u8g2.setFont(u8g2_font_Born2bSportySlab_tr);
    u8g2.drawStr(8, 30, "QUADRO");
  } while ( u8g2.nextPage() );
}

void setup_working_screen (uint8_t display_channel) {
  uint8_t q = addquadrant[display_channel] * 8; // 1-sine,2=tri,3=saw,4=sqr
  u8g2.firstPage();
  do {
    for (uint8_t n = 0; n < 32; n++)
    {
      u8g2.drawPixel(112 - n, smallookup[n + q]);
    }
    u8g2.setFont(u8g2_font_crox1cb_tr);
    if (wave_change) {
      u8g2.drawStr(0, 14, "*");
    };
    u8g2.drawStr(8, 14, " Wave:");
    if (next) {
      u8g2.drawStr(0, 28, "*");
    };
    u8g2.drawStr(8, 28, " Channel:");
    u8g2.setCursor(90, 28);
    u8g2.print(display_channel);
    if (gain_change) {
      u8g2.drawStr(0, 40, "*");
    };
    u8g2.drawStr(8, 40, " Gain: ");
    u8g2.setCursor(90, 40);
    u8g2.print(dacgain[display_channel]);
    if (timing_change) {
      u8g2.drawStr(0, 54, "*");
    };
    u8g2.drawStr(8, 54, " Timing: ");
    u8g2.setCursor(90, 54);
    u8g2.print(timer_value - 10);
  } while ( u8g2.nextPage() );
}

void analog_out (uint8_t channel_to_write, uint16_t analog_data)
{
  // writing to the DAC
  // take the SS pin low to select the chip:
  digitalWrite(SPI_CS0, LOW);
  //  send in the address and value via SPI:
  SPI.transfer(channel_to_write);
  SPI.transfer(analog_data >> 8);
  SPI.transfer(analog_data & 0xFF);
  // take the SS pin high to de-select the chip:
  digitalWrite(SPI_CS0, HIGH);//DAC done
  //SPI.endTransaction();
}

void setup(void)
{
  timer.pause();
  timer.setPrescaleFactor(prescalefactor);
  timer.setOverflow(timer_value);
  timer.refresh();
  timer.attachInterrupt(4, overflowISR);
  pinMode(PB5, OUTPUT);//SCL1 Display
  pinMode(PB6, OUTPUT);//SCL1 Display
  pinMode(PB7, OUTPUT);//SDA1 Display
  pinMode(PB13, INPUT_PULLUP);//rotary encoder
  pinMode(PB14, INPUT_PULLUP);//rotary encoder
  pinMode(PB15, INPUT_PULLUP);//rotary pusbutton
  pinMode(SPI_CS0, OUTPUT);
  u8g2.begin();
  pinMode(PA4, OUTPUT);//Chip Select DAC
  pinMode(PA5, OUTPUT);//CLK
  pinMode(PA7, OUTPUT);//MOSI
  attachInterrupt(digitalPinToInterrupt(PB14),  encoderISR,      FALLING);  //call encoderISR()   every high->low change
  attachInterrupt(digitalPinToInterrupt(PB15), encoderButtonISR, FALLING); //call pushButtonISR() every high->low change
  rotated = false;
  switched = false;
  digitalWrite(SPI_CS0, HIGH);
  delay(10);
  digitalWrite(SPI_CS0, HIGH);
  SPISettings settingsA(70000000, MSBFIRST, SPI_MODE2);
  SPI.beginTransaction(settingsA);
  analog_out(0x30, 0x000F); // LDAC setup DAC
}

void loop(void) {
  setup();
  setup_welcome_screen();
  int n = 0;
  uint16_t dacvalue = 0;
  active_channel = 1;
  next = true;
  timer.resume();//start the interrupt by timer2
  while (1) {
    for (uint8_t quadrant_number = 0; quadrant_number < 4; quadrant_number++)
    {
      for (SAW = 0; SAW < 4095; SAW++)
      {
        /*
           To ensure all DAC channels output their data at the same time
           the last write to the DAC is #13 to produce a software LDAC
           (see table 7 datasheet page 16 of 23)

           Table 7.
           Command Definition C2 C1 C0 Command
           0 0 0 Write to input register n
           0 0 1 Update DAC register n
           0 1 0 Write to input register n, update all (software LDAC)
           0 1 1 Write to and update DAC channel n
           1 0 0 Power down DAC (power-up) 1 0 1 Reset
           1 1 0 Load LDAC register
           1 1 1 Reserved

        */
        dacvalue = dacgain[1] * ((int)get_dacdata (channel1[quadrant_number] + addquadrant[1]));
        analog_out(0x10, dacvalue); //write data to channel 1
        dacvalue = dacgain[2] * ((int)get_dacdata (channel2[quadrant_number] + addquadrant[2]));
        analog_out(1, dacvalue); //write data to channel 2
        dacvalue = dacgain[3] * ((int)get_dacdata (channel3[quadrant_number] + addquadrant[3]));
        analog_out(2, dacvalue); //write data to channel 3
        dacvalue = dacgain[4] * ((int)get_dacdata (channel4[quadrant_number] + addquadrant[4]));

        if (switched) {
          if (wave_change & switched) {
            next = true;
            wave_change = false;
            gain_change = false;
            timing_change = false;
            setup_working_screen (active_channel);
            switched = false;
          }
          if (next & switched) {
            next = false;
            wave_change = false;
            gain_change = true;
            timing_change = false;
            setup_working_screen (active_channel);
            switched = false;
          }
          if (gain_change & switched) {
            next = false;
            wave_change = false;
            gain_change = false;
            timing_change = true;
            setup_working_screen (active_channel);
            switched = false;
          };
          if (timing_change & switched) {
            next = false;
            wave_change = true;
            gain_change = false;
            timing_change = false;
            setup_working_screen (active_channel);
            switched = false;
          };
        };
        if (turned) {
          if (turned & next) {
            if (GPIOB->IDR & (1 << 13)) {
              active_channel++; if (active_channel > 4) {
                active_channel = 1;
              };
            }
            else
            { active_channel--; if (active_channel < 1) {
                active_channel = 4;
              };
            }
          }
          if (turned & wave_change)
          {
            addquadrant[active_channel] += 4;
            if (addquadrant[active_channel] > 15) {
              addquadrant[active_channel] = 0;
            }
          }
          if (turned & gain_change)
          {
            if (GPIOB->IDR & (1 << 13)) {
              dacgain[active_channel] += 0.05; if (dacgain[active_channel] > 1) {
                dacgain[active_channel] = 1;
              }
            }
            else
            {
              dacgain[active_channel] -= 0.05; if (dacgain[active_channel] < 0.05) {
                dacgain[active_channel] = 0;
              };
            }
          };

          if (turned & timing_change)
          {
            if (GPIOB->IDR & (1 << 13)) {
              if (timer_value < 100) {
                timer_value += 1;
              }
              else timer_value += 10;
            }
            else
            {
              if (timer_value > 100) {
                timer_value -= 10;
              }
              else timer_value -= 1;
              if (timer_value < 10) {
                timer_value = 10;
              }
            }
            timer.pause();
            timer.setPrescaleFactor(0xff);
            timer.setOverflow(timer_value);
            timer.refresh();
            timer.resume();
          };
          setup_working_screen (active_channel);
          turned = false;
        }
        while (!timer_tick);
        analog_out(0x13, dacvalue); //write data to channel 4 and update all channels
        timer_tick = false;
      }
    }
  }
}
oliver07
Posts: 1
Joined: Wed Nov 24, 2021 8:23 am

Re: Bluepill project transferring to Blackpill

Post by oliver07 »

You need to set up your board as a first step in STM32CubeIDE. The IDE knows about ST's own development boards and sets them up for you, but the Blue Pill, while using a ST processor, it is not an ST product, so you are on your own here.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Bluepill project transferring to Blackpill

Post by fpiSTM »

Have you check the pin mapping, it is not the same. Default SPI, Serial,... pins are probably not the same.
Post Reply

Return to “General discussion”