Bluno_M3_Reference_Manual-DFRobot

Bluno M3 Interface

In this section, we will introduce some functions about Bluno. Click here to go back Bluno M3 SKU:DFR0329

GPIO

Overview

There are 39 GPIO pins on Bluno M3 which are compatible with Arduino I/O pins.

GPIO Reference

Bluno M3's I/O function declarations are identical to Arduino UNO's. Function Declarations:

pinMode(pin, mode); digitalRead(pin); digitalWrite(pin,value); //value=HIGH/LOW

Example

int led = 13;  // Pin 13 has an LED connected on most Arduino boards.

void setup() {
  pinMode(led, OUTPUT);   // initialize the digital pin as an output.
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

USART

Overview

USART stands for Universal Synchronous/Asynchronous Receiver/Transmitter. Bluno M3 has 5 USARTs in all, and their communication function declarations are also compatible with Arduino UNO:

USART1 connects to the on-board RX1/TX1 pins. Bluetooth also uses the same USART.

USART Reference

Bluno M3's USART is compatible with Arduino's basic serial communication library. Refer to Arduino's official website for more details.

Example

/**
* 1. Initialize Serial1-Serial5
* 2. Read and write
*
*/
void setup() {
    /* initialize both serial ports.*/
    Serial1.begin(9600);
    Serial2.begin(9600);
    Serial3.begin(9600);
    Serial4.begin(9600);
    Serial5.begin(9600);
    Serial1.println("Bluno M3 Serials test begin .......!");
    Serial1.println("Please choose the Serial to test,and Send a string for it:");

}


void loop() {
    char arr[50];
    int len;
    char ch;
    int i;
    //Serial1.available() judge whether serial1 receive any data
    if (Serial1.available()) {

        Serial1.println("the string you input just now is :");
        //Read Serial1 received data
        ch = Serial1.read()
        //Output data
        Serial1.println(ch);
        Serial1.println("Please choose the Serial to test next,and Send a string for it:");
    }
    if ( Serial2.available()) {
        Serial2.println("the string you input just now is :");
        Serial2.println( ch = Serial2.read());
        Serial2.println("Please choose the Serial to test next,and Send a string for it:");
    }
    if (Serial3.available()) {
        Serial3.println("the string you input just now is :");
        Serial3.println( ch = Serial3.read());
        Serial3.println("Please choose the Serial to test next,and Send a string for it:");}
    if (Serial4.available()) {
        Serial4.println("the string you input just now is :");
        Serial4.println( ch = Serial4.read());
        Serial4.println("Please choose the Serial to test next,and Send a string for it:");  }
    if ( Serial5.available()) {
        Serial5.println("the string you input just now is :");
        Serial5.println( ch = Serial5.read());
        Serial5.println("Please choose the Serial to test next,and Send a string for it:"); }

}

PWM

Overview

The following pins are PWM compatible: 0, 1, 2, 3, 6, 7, 11, 12, 21, 22, 27, 28, 35, 36, 37, 38. Every PWM pin is connected with an internal timer, meaning timer configuration is not necessary.

Bluno M3 supports two PWM modes:

Mode 1: 1.Commandvoid`` ``analogWrite(uint32_t`` ``ulPin,`` ``uint32_t`` ``ulValue): This function will output a 1 KHz square wave. Its duty cycle is decided by "ulValue". In this mode, the PWM resolution is only 8-bits which will limit PWM output capacity.

Mode 2: 1.Commandvoid`` ``pwmMode(uint32_t`` ``ulPin,`` ``uint32_t`` ``pwmFre,`` ``uint32_t`` ``pwmMode): you can use this function to configure the PWM pin, PWM frequency and mode. There are two types in all: PWM_8_BIT and PWM_12_BIT InPWM_8_BITMode,pwmFrerange: 4Hz < pwmFre < 281250Hz. InPWM_12_BITMode,pwmFrerange: 1Hz < pwmFre < 17578Hz. 2.Commandvoid`` ``pwmWrite(uint32_t`` ``ulPin,`` ``uint32_t`` ``ulValue): Outputs a square wave with duty cycle of "ulValue" on Pin "ulPin", the following computational formula: InMODE_8_BITmode, ulValue range: 0 ~ 255, Dutycycle = ulValue / 255 * 100% InMODE_12_BITmode, ulValue range: 0 ~ 4095,Dutycycle = ulValue / 4095 * 100%

PWM Reference Function

void`` ``analogWrite(uint32_t`` ``ulPin,`` ``uint32_t`` ``ulValue)

Description: Outputs a 1KHz square wave with duty cycle "ulValue" on Pin "ulPin" Parameter:

Returns: None;

void`` ``pwmMode(uint32_t`` ``ulPin,`` ``uint32_t`` ``pwmFre,`` ``uint32_t`` ``pwmMode)

Description: configures PWM pin, PWM frequency and PWM mode. Parameter:

Returns: None

Example

Mode 1


  // pwm connected to digital pin 0
  int pwmPin = 0;
  void setup() {
     //nothing happens in setup
 }

  void loop() {

    // fade in from min to max in increments of 5 points:
    for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
         // sets the value (range from 0 to 255):
        analogWrite(pwmPin, fadeValue);
         // wait for 30 milliseconds to see the dimming effect
        delay(30);
    }

    // fade out from max to min in increments of 5 points:
    for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
        // sets the value (range from 0 to 255):
        analogWrite(pwmPin, fadeValue);
        // wait for 30 milliseconds to see the dimming effect
        delay(30);
    }
 }

Mode 2


#include <Arduino.h>
 int pwmPin = 0;    // PWM connected to digital pin 0
 int flag = 1;
 void setup() {
     //initailizing the pwmPin,  setting the period of PWM as 2000Hz and it's mode as 8'bit.
     pwmMode(pwmPin, 2000, PWM_8_BIT);
 }

 void loop() {

     // output the duty of the PWM , one is 39% based on the formula privided above.
     pwmWrite(pwmPin, 100);
     while (1);

}

ADC

Overview

An ADC (Analog-to-Digital Converter) is a device that converts a continuous physical quantity (usually voltage) to a digital number that represents the quantity's amplitude. Bluno M3 has 11 ADC pins: A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10. Their voltage range is 0~3.3V. They have two working modes:

Mode 1: 1.CommandanalogRead(uint32_t`` ``ulPin): default 10-bit sampling resolution, and its usage is same to Arduino, analogRead()

Mode 2: 1.Commandvoid`` ``adcMode(uint32_t`` ``ulPin,`` ``uint8_t`` ``Mode): Set ADC pin mode:ADC_8_BITADC_10_BITADC_12_BIT. *ADC_8_BIT. map range: 0~255; *ADC_10_BIT. map range: 0~1023; *ADC_12_BIT. map range: 0~4096; 2.Commanduint32_t`` ``adcRead`` ``(uint32_t`` ``ulPin), this function converts the PinulPinanalog input value to the corresponding one in the other mode. (E.g. If the voltage on A2 is 1.5V, you will get 116 underADC_8_BITpin mode, and you will get 465 and 1861 underADC_10_BITandADC_12_BITpin mode with this commend.)

ADC Reference Function

uint32_t`` ``analogRead(uint32_t`` ``ulPin)

Description: Return Pin ulPin analog value. Parameter:

Returns: ADC value

void`` ``adcMode(uint32_t`` ``ulPin,`` ``uint8_t`` ``Mode)

Description: Set ADC pin mode Parameter:

Returns: None

uint32_t`` ``adcRead(uint32_t`` ``ulPin)

Description: Return a mode converted ADC value Parameter:

Returns: ADC mode converted result.

Example

Mode 1:


 int sensorPin = 0;    // select the input pin for the potentiometer
 int sensorValue = 0;  // variable to store the value coming from the sensor
 void setup() {

   Serial1.begin(9600);

 }

 void loop() {

   sensorValue = analogRead(sensorPin);
   Serial1.println((int)sensorValue);
   delay(1000);

 }

Mode 2:



 int sensorPin = 0;    // select the input pin for the potentiometer
 int sensorValue = 0;  // variable to store the value coming from the sensor

 void setup() {
    Serial1.begin(9600);
    adcMode(sensorPin, ADC_12_BIT);
 }

 void loop() {

    sensorValue = adcRead(sensorPin);
    Serial1.println((int)sensorValue);
    delay(1000);
}

External Interrupts

Overview

All Bluno M3 digital I/O pins (D0~D38) can be used as external interrupt pins.

Reference Function

void`` ``attachInterrupt(uint32_t`` ``pin,`` ``void`` ``(*callback)(void),`` ``uint32_t`` ``mode)

Description: Configure a specified pin as external interrupt, and register a callback function for the interrupt. Parameter:

Returns: None

Example


//define the extern interrupt pin.
char intNumber = 2;

void setup() {
  //init the Serial1.
  Serial1.begin(9600);
  //register the interrupt handler for the pin and specify the interrupt mode in CHANGE mode
  attachInterrupt(intNumber, warning, CHANGE);
}

void loop() {
}
/*define a function as the handler when the extern Interrupt assert*/
void warning(){
  Serial1.println((int)intNumber);
}

I2C

Overview

I2C protocol (Inter-Integrated Circuit), (refer to I2C wikipedia for more information). Bluno M3 has a I2C interface. The default I2C interface is SDA (30) and SCL(29). It can also be free assigned.

I2C Reference Function

void`` ``begin()

Description: Use default I2C interface: On-board SDA (30) & SCL(29) Parameter: None Returns: None

void`` ``begin(uint8_t,`` ``uint8_t)

Description: Define I2C interface, SDA & SCL (D0~D38) Returns: None

For other usages please refer to Arduino official reference

Example

/*
 *  The sample code implements write/read function on chip 24C256 via I2C bus
 *
 *
 *
 */

#include <Wire.h> //I2C library
#define EEPROM_ADDR 0x50           // I2C Buss address of 24LC256 256K EEPROM
#define PAGESIZE    64             // 64 bytes each Page of 24LC256
int temp ;
void setup()
{
  Wire.begin();   // join I2C bus (address optional for master)
  Serial1.begin(9600);
}

void loop()
{
         int i;
         byte arr[64];
         byte arread[64];
         // TESTS FOR EACH FUNCTION BEGIN HERE
          Serial1.println("the data is going to be write to the 24LC256:");
         for (i = 0; i < PAGESIZE; i++)
         {
             arr[i] = i;
             Serial1.print(i);
             Serial1.print(' ');
             if (i != 0 && i % 10 == 0)
                Serial1.println("");
         }

          Serial1.println("");
         i2c_eeprom_write_page(EEPROM_ADDR, 0, arr, PAGESIZE);
         delay(100);

         i2c_eeprom_read_buffer(EEPROM_ADDR, 0, arread,PAGESIZE);
         Serial1.println("the data is reading from the 24LC256  :");
         delay(1000);

         for (i = 0; i < PAGESIZE; i++)
         {
             Serial1.print(arread[i]);
             Serial1.print(' ');
             if (i != 0 &&i % 10 == 0)
                 Serial1.println("");

         }
          Serial1.println("");
         if (memcmp(arr, arread, PAGESIZE) == 0)
         {
             Serial1.println("the driver of the 24LC256 correct!");
         }
         else
         {
              Serial1.println("the driver of the 24LC256 fault!");
         }

         while (1);
  }

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
  }

  // WARNING: address is a page address, 6-bit end will wrap around
  // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
      Wire.write(data[c]);
    Wire.endTransmission();
  }

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
  }

  // maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
      if (Wire.available()) buffer[c] = Wire.read();
  }

SPI

Overview

SPI (Serial Peripheral Interface) bus is a synchronous serial communication interface specification used for short distance communication, primarily in embedded systems. Refer to SPI wikipedia for more information. There are 2 SPI interfaces on Bluno M3: SPI and SPI1.

Reference Functions

Refer to Arduino official functions: SPI Note:

Example


/**
*Drive SD module via SPI interface
*
*
*
*/






#include "SPI.h"


#define SD_TYPE_ERR     0X00
#define SD_TYPE_MMC     0X01
#define SD_TYPE_V1      0X02
#define SD_TYPE_V2      0X04
#define SD_TYPE_V2HC    0X06

#define CMD0    0
#define CMD1    1
#define CMD8    8
#define CMD9    9
#define CMD10   10
#define CMD12   12
#define CMD16   16
#define CMD17   17
#define CMD18   18
#define CMD23   23
#define CMD24   24
#define CMD25   25
#define CMD41   41
#define CMD55   55
#define CMD58   58
#define CMD59   59
#define MSD_DATA_OK                0x05
#define MSD_DATA_CRC_ERROR         0x0B
#define MSD_DATA_WRITE_ERROR       0x0D
#define MSD_DATA_OTHER_ERROR       0xFF
//SD¿¨»ØÓ¦±ê¼Ç×Ö
#define MSD_RESPONSE_NO_ERROR      0x00
#define MSD_IN_IDLE_STATE          0x01
#define MSD_ERASE_RESET            0x02
#define MSD_ILLEGAL_COMMAND        0x04
#define MSD_COM_CRC_ERROR          0x08
#define MSD_ERASE_SEQUENCE_ERROR   0x10
#define MSD_ADDRESS_ERROR          0x20
#define MSD_PARAMETER_ERROR        0x40
#define MSD_RESPONSE_FAILURE       0xFF


const int slaveSelectPin = 4;
u8  SD_Type=0;

u8 SD_WaitReady(void)
{
  u32 t=0;
  do
  {
    if(SPI.transfer(0xff)==0xff)
    {
      return 0;//is ok!!!
    }
    t++;
  }while(t<0xffffff);
  return 1;
}

void SD_DisSelect(void)
{
    digitalWrite(slaveSelectPin, HIGH);
    SPI.transfer(0xff);
}

u8 SD_Select(void)
{
    digitalWrite(slaveSelectPin, LOW);
    if(SD_WaitReady()==0)
          return 0;
    SD_DisSelect();
    return 1;
}

u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
    u8 r1;
    u8 Retry=0;
    SD_DisSelect();
    if(SD_Select())
    {
      return 0XFF;
    }
    SPI.transfer(cmd | 0x40);//·Ö±ðдÈëÃüÁî
    SPI.transfer(arg >> 24);
    SPI.transfer(arg >> 16);
    SPI.transfer(arg >> 8);
    SPI.transfer(arg);
    SPI.transfer(crc);
    if(cmd==CMD12)
      SPI.transfer(0xff);
    Retry=0X1F;
    do
    {
    r1=SPI.transfer(0xFF);
    }while((r1&0X80) && Retry--);

    return r1;
}

u8 SD_Initialize(void)
{
    u16 retry;
    u8 r1;
    u8 buf[4];
    u16 i;
    // set the slaveSelectPin as an output:
    pinMode (slaveSelectPin, OUTPUT);
    // initialize SPI:
    SPI.begin();
        SPI.setClockDivider(SPI_CLOCK_DIV256);
        SPI.setDataMode(SPI_MODE3);
    //SPI.setDataMode(SPI_MODE3);
    SPI.setClockDivider(SPI_CLOCK_DIV256);
    for(int i=0;i<10;i++)
    SPI.transfer(0xff);
    retry=20;
    do
    {
        r1=SD_SendCmd(CMD0,0,0x95);
    }while((r1!=0x01)&&retry--);
    SD_Type=0;
    if(r1==0X01)
    {
        if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
        {
            for(int i=0;i<4;i++)buf[i]=SPI.transfer(0XFF);
            if(buf[2]==0X01&&buf[3]==0XAA)
            {
                retry=0XFFFE;
                do
                {
                    SD_SendCmd(CMD55,0,0X01);
                    r1=SD_SendCmd(CMD41,0x40000000,0X01);
                }while(r1&&retry--);
                if(retry&&SD_SendCmd(CMD58,0,0X01)==0)
                {
                    for(int i=0;i<4;i++)buf[i]=SPI.transfer(0XFF);
                    if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;
                    else SD_Type=SD_TYPE_V2;
                }
            }
        }else//SD V1.x/ MMC V3
        {
            SD_SendCmd(CMD55,0,0X01);
            r1=SD_SendCmd(CMD41,0,0X01);
            if(r1<=1)
            {
                SD_Type=SD_TYPE_V1;
                retry=0XFFFE;
                do
                {
                    SD_SendCmd(CMD55,0,0X01);
                    r1=SD_SendCmd(CMD41,0,0X01);
                }while(r1&&retry--);
            }else
            {
                SD_Type=SD_TYPE_MMC;//MMC V3
                retry=0XFFFE;
                do
                {
                    r1=SD_SendCmd(CMD1,0,0X01);
                }while(r1&&retry--);
            }
            if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;
        }
    }
    SD_DisSelect();
    //SPIsetClockDivider(SPI_BaudRatePrescaler_2);
    if(SD_Type)
    return 0;
    else if(r1)return r1;
    return 0xaa;
}

u8 SD_GetResponse(u8 Response)
{
    u16 Count=0xFFF;
    while ((SPI.transfer(0XFF)!=Response)&&Count)Count--;
    if (Count==0)return MSD_RESPONSE_FAILURE;
    else return MSD_RESPONSE_NO_ERROR;
}

u8 SD_RecvData(u8*buf,u16 len)
{
    if(SD_GetResponse(0xFE))return 1;
    while(len--)
    {
        *buf=SPI.transfer(0xFF);
        buf++;
    }

    SPI.transfer(0xFF);
    SPI.transfer(0xFF);
    return 0;
}

u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;
    r1=SD_SendCmd(CMD9,0,0x01);
    if(r1==0)
    {
      r1=SD_RecvData(csd_data, 16);
    }
  SD_DisSelect();
  if(r1)
    return 1;
  else
    return 0;
}

u32 SD_GetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity;
    u8 n;
    u16 csize;
    if(SD_GetCSD(csd)!=0)
    {
      return 0;
    }

    if((csd[0]&0xC0)==0x40)
    {
        csize = csd[9] + ((u16)csd[8] << 8) + 1;
        Capacity = (u32)csize << 10;
    }
    else
    {
        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
        csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
        Capacity= (u32)csize << (n - 9);
    }
    return Capacity;
}

u8 SD_ReadDisk(u8* buf,u32 sector,u8 cnt)
{
    u8 r1;
    if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;
    if(cnt==1)
    {
        r1=SD_SendCmd(CMD17,sector,0X01);
        if(r1==0)
        {
            r1=SD_RecvData(buf,512);
        }
    }else
    {
        r1=SD_SendCmd(CMD18,sector,0X01);
        do
        {
            r1=SD_RecvData(buf,512);
            buf+=512;
        }while(--cnt && r1==0);
        SD_SendCmd(CMD12,0,0X01);
    }
    SD_DisSelect();
    return r1;//
}

u8 SD_WriteDisk(u8* buf,u32 sector,u8 cnt)
{
    u8 r1;
    if(SD_Type!=SD_TYPE_V2HC)sector *= 512;
    if(cnt==1)
    {
        r1=SD_SendCmd(CMD24,sector,0X01);
        if(r1==0)
        {
            r1=SD_SendBlock(buf,0xFE);
        }
    }
        else
    {
        if(SD_Type!=SD_TYPE_MMC)
        {
            SD_SendCmd(CMD55,0,0X01);
            SD_SendCmd(CMD23,cnt,0X01);
        }
        r1=SD_SendCmd(CMD25,sector,0X01);
        if(r1==0)
        {
            do
            {
                r1=SD_SendBlock(buf,0xFC);
                buf+=512;
            }while(--cnt && r1==0);
            r1=SD_SendBlock(0,0xFD);
        }
    }
    SD_DisSelect();
    return r1;//
}

u8 SD_SendBlock(u8*buf,u8 cmd)
{
    u16 t;
    if(SD_WaitReady())return 1;
    SPI.transfer(cmd);
    if(cmd!=0XFD)
    {
        for(t=0;t<512;t++)
              SPI.transfer(buf[t]);
          SPI.transfer(0xFF);
          SPI.transfer(0xFF);
        t=SPI.transfer(0xFF);
        if((t&0x1F)!=0x05)return 2;
    }
    return 0;
}

void setup()
{
  u32 sector_size;
  u8 ybuf[512]="DFROBOT!";
  u8 xbuf[512];

  Serial1.begin(9600);
 // SPI.begin();
  Serial1.println("Serial1 init is OK!");
   while(SD_Initialize()!=0)
   {
     Serial1.println("SD init Failed");
     delay(1000);
   }
   Serial1.println("SD init OK!");
   sector_size=SD_GetSectorCount()/1024;
  // sector_size=0x3af000;
   Serial1.println(sector_size/4);
   SD_WriteDisk(ybuf,0,1);
   delay(500);
   SD_ReadDisk(xbuf,0,1);

   Serial1.println(xbuf[0]);
   Serial1.println(xbuf[1]);
   Serial1.println(xbuf[2]);
   Serial1.println(xbuf[3]);
   Serial1.println(xbuf[4]);
   Serial1.println(xbuf[5]);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Timer

Overview

Bluno M3 implements a software timer function via a software library. It will meet some user timing requirements on some special occasions. The timer function is encapsulated in the timer class, you only need to define and initialize the object and it will work. The timer supports single and periodic timing interrupt processing modes. In single timing interrupt processing mode, the function only runs once. In periodic mode, it will be executed periodically. Note: One timer object can be switched between two modes. Timer class also supports the callback function.

Reference function

Timer(void)

Description: Default constructor function Parameter: None Returns: None

Timer(uint32_t`` ``ms,`` ``Func`` ``tfunc,`` ``tKind_t`` ``mode,`` ``void`` ``*data)

Description: Support object instantiating and parameter passing Parameter:

Returns: None

~Timer()

Description: Destructor, invoke for destroy the Timer automatically. Parameter: None Returns: None

void`` ``config(uint32_t`` ``ms,`` ``Func`` ``tfunc,`` ``tKind_t`` ``mode,`` ``void`` ``*data)

Description: The function which is used to configure the timer object. Parameter: None

Returns: None

uint8_t`` ``get_tNum(void)

Description: Return the current Timer serial number. Parameter: None Returns: The current Timer serial number (This serial number is assigned when it is created.)

uint32_t`` ``get_resTime(void)

Description: Return the current Timer remaining time. Parameter: None Returns: Return the current Timer remaining time.

void`` ``change_callbackFunc(Func`` ``ttFunc)

Description: Change the current Timer callback function. Parameter:

Returns: None

void`` ``change_mode(tKind_t`` ``mode)

Description: Change the current Timer mode Parameter:

Returns: None

Example



/***
*
*Bluno M3 Timer Demonstration
*
*/

#include "timerobj.h"
#include <stdlib.h>
unsigned char td;

/*define the objects of the Timer that are best to be a global variable*/
//instantiate a object of the class Timer with the hook function myfunc,and speicify the mode t_period.
Timer timer1(1000, myfunc, t_period, NULL );

Timer timer2(3000, myfunc1, t_period, NULL );


void myfunc(void *data)
{
     Serial1.println("it is processing the first call back function! on timer1\n");
}

void myfunc1(void *data)
{
     static int i;
     i++;
     Serial1.println(i);
     Serial1.println("it is processing the second call back function! on timer2\n");

     if (i == 3)
     {
         Serial1.println("changing the callback function for the timer1\n");
         timer1.change_callbackFunc(myfunc2);  // changing the callback function for the object timer1
      }

}

void myfunc2(void *data)
{

      static int i;
      i++;
      Serial1.println(i);
      Serial1.println("myfunc2");
      if (i == 2)
      {
         Serial1.println("changing the kind of type for timer2\n");
         timer2.change_type(t_single);  // changing the mode for the timer2 from t_period to t_single.
      }
}

void setup() {

      Serial1.begin(9600);

}

void loop() {


}

Flash

Overview

Bluno M3 is microcontroller based on stm32f103 ARM processor. The internal flash is 512k. You could store and run the program on it, or store the user data. There are 256 page in flash, and each page is 2KB. Generally, it requires to erase data first before writing. And it only could write one page at one time. So it is very difficult to make a flash underlying operations on Bluno M3. So we made a special Flash class for Bluno M3. It divides M3 Flash into two major area: code area and user data area. Code area is place where the program in, it is not visible to the user, and address range is from 0x00000000~0x0807B000. On the other hand, the user data area is available for the client. Read, write or any other operation are allow be allowed in this space. Its address range is from 0x0807B000 ~ 0x08080000. The client could have 20KB storage space even there is no external storage chip. And the data-write function has wiping feature itself. You don't need to consider the flash paging problem anymore, because it also has been integrated in data-write function.

Reference Function

FLASH_Status`` ``ErasePage(uint32_t`` ``Page_Address)

Description: Erase a page. Parameter:

Returns: FLASH_Status

FLASH_Status`` ``EraseAllPages(void)

Description: Erase all user data area (not including code area) Parameter:None Returns: FLASH_Status

void`` ``Read`` ``(uint32_t`` ``Addr,`` ``void`` ``*data,`` ``uint32_t`` ``NumByteToWrite)

Description: Read data from assigned address Parameter:

Returns: None

uint16_t`` ``Read(uint32_t`` ``Addr)

Description: Read data (single byte) Parameter:

Returns: Return raw byte, (16-bit)

FLASH_Status`` ``Write(uint32_t`` ``WriteAddr,`` ``uint16_t`` ``data)

Description: Write a 16-bit data Parameter:

Returns: FLASH_Status

void`` ``Write(uint32_t`` ``WriteAddr,`` ``void`` ``*data,`` ``uint32_t`` ``NumByteToWrite)

Description: Write more data to assigned address (Start address) Parameter:

Returns: None

uint32_t`` ``GetFlashSpace(void)

Description: Return the capacity of the user data area Parameter: None Returns: Return the capacity of the user data area, unit:byte

Example


#include <Flash.h>

void setup() {
    // initialize the Serial1
    Serial1.begin(9600);
}

void loop() {

    unsigned short temp = 68, readBuf;

    Serial1.println("the data to write is :");
    Serial1.println(temp);
    //write the value 68 to the address 0x08005010 in flash.
    flash.Write(0x08005010, &temp, 1);
    delay(1000);

    Serial1.println("the data from reading is :");
    //read the value to the variable for the address 0x08005010 in flash
    flash.Read(0x08005010, &readBuf, 1);
    Serial1.println(readBuf);

    delay(10000);

}

Servo Application

Overview

We construct a Servo class, to make Bluno M3 have same servo interface with Arduino UNO. If the client need a servo on Bluno M3, he only needs use attach() function.

Example

uint8_t`` ``attach(int`` ``pin)

Description: Drive servo on some pin, and return the pin number. Parameter:

Returns: Servo driving pin number

void`` ``write(int`` ``value)

Description: Input servo rotation angle Parameter:

Returns: None

Example

Library ServoM3 locates Arduino-1.5.5\hardware\arduino\STM32\libraries folder

#include <ServoM3.h>

Servo myservo;  // create servo object to control a servo
                // twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
  for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

Ethernet Application

Overview

Bluno M3 is compatible with W5200 Ethernet shield. Here is a sample for how to use it on Bluno M3.

Reference Function

Please refer to Arduino official Ethernet library. Anyway, W5200 shield requires a update version Ethernet library. Please visit our website for library download. DFRobot W5200 wiki

Example

/*
  Web Server (based on the sheld W5200)

 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield.

 Analog inputs attached to pins A0 through A5 (optional)


 */

#include <SPI.h>
#include <Ethernet.h>
//Attention: Official SPI port use "D10" as SS interface.You need to define SS pin acording to the actual SS wire connection
//the default ss pin is attached to 10 pin for the sheld W5200
#define SS    10
#define nRST  8
#define nPWDN 9
#define nINT 3

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
  //Next setting parameter is very important!!!! If you don't have reliable reset setting, W5200 maybe will not work!!!!!  //
  pinMode(SS,OUTPUT);
  pinMode(nRST,OUTPUT);
  pinMode(nPWDN,OUTPUT);
  pinMode(nINT,INPUT);
  digitalWrite(nPWDN,LOW);  //enable power

  digitalWrite(nRST,LOW);  //Reset W5200
  delay(10);
  digitalWrite(nRST,HIGH);
 delay(200);       // wait W5200 work
 /////////////////////////////////////////////////////////////
 // Open Serial1 communications and wait for port to open:
  Serial1.begin(9600);
   while (!Serial1) {
    ; // wait for Serial1 port to connect. Needed for Leonardo only
  }


  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial1.print("server is at ");
  Serial1.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial1.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial1.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
                    // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial1.println("client disonnected");
  }
}

SD Application

Overview

An example for Bluno M3 and SD module

Reference Function

Arduino official SD library

Example

/*
  SD card basic file example

 This example shows how to create and destroy an SD card file
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 This example code is in the public domain.

 */
#include <SPI.h>
#include <SD.h>

File myFile;
int cs_pin = 4;       //D4 is attached as cs pin
void setup()
{
  // Open serial communications and wait for port to open:
  Serial1.begin(9600);
  while (!Serial1) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial1.print("Initializing SD card...");

  if (!SD.begin(cs_pin)) {
    Serial1.println("initialization failed!");
    return;
  }
  Serial1.println("initialization done.");

  if (SD.exists("example.txt")) {
    Serial1.println("example.txt exists.");
  }
  else {
    Serial1.println("example.txt doesn't exist.");
  }

  // open a new file and immediately close it:
  Serial1.println("Creating example.txt...");
  myFile = SD.open("example.txt", FILE_WRITE);
  myFile.close();

  // Check to see if the file exists:
  if (SD.exists("example.txt")) {
    Serial1.println("example.txt exists.");
  }
  else {
    Serial1.println("example.txt doesn't exist.");
  }

  // delete the file:
  Serial1.println("Removing example.txt...");
  SD.remove("example.txt");

  if (SD.exists("example.txt")) {
    Serial1.println("example.txt exists.");
  }
  else {
    Serial1.println("example.txt doesn't exist.");
  }
}

void loop()
{
  // nothing happens after setup finishes.
}

Generate a Sine-wave by TIM8

Overview

the application is useful for generator a sine-wave by TIM8,the frequence of which can be inditated form 70Hz to 2000Hz. In this application , only the out compare 1 chanel of TIM8 has initialized ,which generate a sine-wave on the PC8.Of course the PC8 must be attached a low pass filter,which can be made samply of two resistances and two capacitances,i.e. RC integrated circuit.Generally TIM8 have 4 independent channels which can be configure as out compare mode, so user can change the following code to generate mulititude sine-wave at the same time. the schematic drawing shows as follow: `Blune`` ``M3`

Example


   #define FAST_MATH_TABLE_SIZE  512
   const float sinTable_f32[FAST_MATH_TABLE_SIZE + 1] = {
   0.00000000f, 0.01227154f, 0.02454123f, 0.03680722f, 0.04906767f, 0.06132074f,
   0.07356456f, 0.08579731f, 0.09801714f, 0.11022221f, 0.12241068f, 0.13458071f,
   0.14673047f, 0.15885814f, 0.17096189f, 0.18303989f, 0.19509032f, 0.20711138f,
   0.21910124f, 0.23105811f, 0.24298018f, 0.25486566f, 0.26671276f, 0.27851969f,
   0.29028468f, 0.30200595f, 0.31368174f, 0.32531029f, 0.33688985f, 0.34841868f,
   0.35989504f, 0.37131719f, 0.38268343f, 0.39399204f, 0.40524131f, 0.41642956f,
   0.42755509f, 0.43861624f, 0.44961133f, 0.46053871f, 0.47139674f, 0.48218377f,
   0.49289819f, 0.50353838f, 0.51410274f, 0.52458968f, 0.53499762f, 0.54532499f,
   0.55557023f, 0.56573181f, 0.57580819f, 0.58579786f, 0.59569930f, 0.60551104f,
   0.61523159f, 0.62485949f, 0.63439328f, 0.64383154f, 0.65317284f, 0.66241578f,
   0.67155895f, 0.68060100f, 0.68954054f, 0.69837625f, 0.70710678f, 0.71573083f,
   0.72424708f, 0.73265427f, 0.74095113f, 0.74913639f, 0.75720885f, 0.76516727f,
   0.77301045f, 0.78073723f, 0.78834643f, 0.79583690f, 0.80320753f, 0.81045720f,
   0.81758481f, 0.82458930f, 0.83146961f, 0.83822471f, 0.84485357f, 0.85135519f,
   0.85772861f, 0.86397286f, 0.87008699f, 0.87607009f, 0.88192126f, 0.88763962f,
   0.89322430f, 0.89867447f, 0.90398929f, 0.90916798f, 0.91420976f, 0.91911385f,
   0.92387953f, 0.92850608f, 0.93299280f, 0.93733901f, 0.94154407f, 0.94560733f,
   0.94952818f, 0.95330604f, 0.95694034f, 0.96043052f, 0.96377607f, 0.96697647f,
   0.97003125f, 0.97293995f, 0.97570213f, 0.97831737f, 0.98078528f, 0.98310549f,
   0.98527764f, 0.98730142f, 0.98917651f, 0.99090264f, 0.99247953f, 0.99390697f,
   0.99518473f, 0.99631261f, 0.99729046f, 0.99811811f, 0.99879546f, 0.99932238f,
   0.99969882f, 0.99992470f, 1.00000000f, 0.99992470f, 0.99969882f, 0.99932238f,
   0.99879546f, 0.99811811f, 0.99729046f, 0.99631261f, 0.99518473f, 0.99390697f,
   0.99247953f, 0.99090264f, 0.98917651f, 0.98730142f, 0.98527764f, 0.98310549f,
   0.98078528f, 0.97831737f, 0.97570213f, 0.97293995f, 0.97003125f, 0.96697647f,
   0.96377607f, 0.96043052f, 0.95694034f, 0.95330604f, 0.94952818f, 0.94560733f,
   0.94154407f, 0.93733901f, 0.93299280f, 0.92850608f, 0.92387953f, 0.91911385f,
   0.91420976f, 0.90916798f, 0.90398929f, 0.89867447f, 0.89322430f, 0.88763962f,
   0.88192126f, 0.87607009f, 0.87008699f, 0.86397286f, 0.85772861f, 0.85135519f,
   0.84485357f, 0.83822471f, 0.83146961f, 0.82458930f, 0.81758481f, 0.81045720f,
   0.80320753f, 0.79583690f, 0.78834643f, 0.78073723f, 0.77301045f, 0.76516727f,
   0.75720885f, 0.74913639f, 0.74095113f, 0.73265427f, 0.72424708f, 0.71573083f,
   0.70710678f, 0.69837625f, 0.68954054f, 0.68060100f, 0.67155895f, 0.66241578f,
   0.65317284f, 0.64383154f, 0.63439328f, 0.62485949f, 0.61523159f, 0.60551104f,
   0.59569930f, 0.58579786f, 0.57580819f, 0.56573181f, 0.55557023f, 0.54532499f,
   0.53499762f, 0.52458968f, 0.51410274f, 0.50353838f, 0.49289819f, 0.48218377f,
   0.47139674f, 0.46053871f, 0.44961133f, 0.43861624f, 0.42755509f, 0.41642956f,
   0.40524131f, 0.39399204f, 0.38268343f, 0.37131719f, 0.35989504f, 0.34841868f,
   0.33688985f, 0.32531029f, 0.31368174f, 0.30200595f, 0.29028468f, 0.27851969f,
   0.26671276f, 0.25486566f, 0.24298018f, 0.23105811f, 0.21910124f, 0.20711138f,
   0.19509032f, 0.18303989f, 0.17096189f, 0.15885814f, 0.14673047f, 0.13458071f,
   0.12241068f, 0.11022221f, 0.09801714f, 0.08579731f, 0.07356456f, 0.06132074f,
   0.04906767f, 0.03680722f, 0.02454123f, 0.01227154f, 0.00000000f, -0.01227154f,
   -0.02454123f, -0.03680722f, -0.04906767f, -0.06132074f, -0.07356456f,
   -0.08579731f, -0.09801714f, -0.11022221f, -0.12241068f, -0.13458071f,
   -0.14673047f, -0.15885814f, -0.17096189f, -0.18303989f, -0.19509032f,
   -0.20711138f, -0.21910124f, -0.23105811f, -0.24298018f, -0.25486566f,
   -0.26671276f, -0.27851969f, -0.29028468f, -0.30200595f, -0.31368174f,
   -0.32531029f, -0.33688985f, -0.34841868f, -0.35989504f, -0.37131719f,
   -0.38268343f, -0.39399204f, -0.40524131f, -0.41642956f, -0.42755509f,
   -0.43861624f, -0.44961133f, -0.46053871f, -0.47139674f, -0.48218377f,
   -0.49289819f, -0.50353838f, -0.51410274f, -0.52458968f, -0.53499762f,
   -0.54532499f, -0.55557023f, -0.56573181f, -0.57580819f, -0.58579786f,
   -0.59569930f, -0.60551104f, -0.61523159f, -0.62485949f, -0.63439328f,
   -0.64383154f, -0.65317284f, -0.66241578f, -0.67155895f, -0.68060100f,
   -0.68954054f, -0.69837625f, -0.70710678f, -0.71573083f, -0.72424708f,
   -0.73265427f, -0.74095113f, -0.74913639f, -0.75720885f, -0.76516727f,
   -0.77301045f, -0.78073723f, -0.78834643f, -0.79583690f, -0.80320753f,
   -0.81045720f, -0.81758481f, -0.82458930f, -0.83146961f, -0.83822471f,
   -0.84485357f, -0.85135519f, -0.85772861f, -0.86397286f, -0.87008699f,
   -0.87607009f, -0.88192126f, -0.88763962f, -0.89322430f, -0.89867447f,
   -0.90398929f, -0.90916798f, -0.91420976f, -0.91911385f, -0.92387953f,
   -0.92850608f, -0.93299280f, -0.93733901f, -0.94154407f, -0.94560733f,
   -0.94952818f, -0.95330604f, -0.95694034f, -0.96043052f, -0.96377607f,
   -0.96697647f, -0.97003125f, -0.97293995f, -0.97570213f, -0.97831737f,
   -0.98078528f, -0.98310549f, -0.98527764f, -0.98730142f, -0.98917651f,
   -0.99090264f, -0.99247953f, -0.99390697f, -0.99518473f, -0.99631261f,
   -0.99729046f, -0.99811811f, -0.99879546f, -0.99932238f, -0.99969882f,
   -0.99992470f, -1.00000000f, -0.99992470f, -0.99969882f, -0.99932238f,
   -0.99879546f, -0.99811811f, -0.99729046f, -0.99631261f, -0.99518473f,
   -0.99390697f, -0.99247953f, -0.99090264f, -0.98917651f, -0.98730142f,
   -0.98527764f, -0.98310549f, -0.98078528f, -0.97831737f, -0.97570213f,
   -0.97293995f, -0.97003125f, -0.96697647f, -0.96377607f, -0.96043052f,
   -0.95694034f, -0.95330604f, -0.94952818f, -0.94560733f, -0.94154407f,
   -0.93733901f, -0.93299280f, -0.92850608f, -0.92387953f, -0.91911385f,
   -0.91420976f, -0.90916798f, -0.90398929f, -0.89867447f, -0.89322430f,
   -0.88763962f, -0.88192126f, -0.87607009f, -0.87008699f, -0.86397286f,
   -0.85772861f, -0.85135519f, -0.84485357f, -0.83822471f, -0.83146961f,
   -0.82458930f, -0.81758481f, -0.81045720f, -0.80320753f, -0.79583690f,
   -0.78834643f, -0.78073723f, -0.77301045f, -0.76516727f, -0.75720885f,
   -0.74913639f, -0.74095113f, -0.73265427f, -0.72424708f, -0.71573083f,
   -0.70710678f, -0.69837625f, -0.68954054f, -0.68060100f, -0.67155895f,
   -0.66241578f, -0.65317284f, -0.64383154f, -0.63439328f, -0.62485949f,
   -0.61523159f, -0.60551104f, -0.59569930f, -0.58579786f, -0.57580819f,
   -0.56573181f, -0.55557023f, -0.54532499f, -0.53499762f, -0.52458968f,
   -0.51410274f, -0.50353838f, -0.49289819f, -0.48218377f, -0.47139674f,
   -0.46053871f, -0.44961133f, -0.43861624f, -0.42755509f, -0.41642956f,
   -0.40524131f, -0.39399204f, -0.38268343f, -0.37131719f, -0.35989504f,
   -0.34841868f, -0.33688985f, -0.32531029f, -0.31368174f, -0.30200595f,
   -0.29028468f, -0.27851969f, -0.26671276f, -0.25486566f, -0.24298018f,
   -0.23105811f, -0.21910124f, -0.20711138f, -0.19509032f, -0.18303989f,
   -0.17096189f, -0.15885814f, -0.14673047f, -0.13458071f, -0.12241068f,
   -0.11022221f, -0.09801714f, -0.08579731f, -0.07356456f, -0.06132074f,
   -0.04906767f, -0.03680722f, -0.02454123f, -0.01227154f, -0.00000000f
};

/*Tim8 ccr address */
#define TIM8_CCR1_Address    0x40013434
#define TIM8_CCR2_Address    0x40013438
#define TIM8_CCR3_Address    0x4001343C
#define TIM8_CCR4_Address    0x40013440
static uint16_t Ctcs_Table[4500];



void RCC_Configuration(void)
{
    /* TIM8 and GPIOC clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8 | RCC_APB2Periph_GPIOC
                           , ENABLE);
    /* DMA 2 clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
}


void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* GPIOC Configure: Channel 1 as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}

void DMA_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    /* DMA2 Channel3 Config */
    DMA_DeInit(DMA2_Channel3);

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM8_CCR1_Address;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Ctcs_Table;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA2_Channel3, &DMA_InitStructure);

}
float arm_sin_f32(float x)
{
    float sinVal, fract, in;
    uint16_t index;
    float a, b;
    int32_t n;
    float findex;
    in = x * 0.159154943092f;
    n = (int32_t) in;
    if(x < 0.0f)
    {
      n--;
    }
    in = in - (float) n;
    findex = (float) FAST_MATH_TABLE_SIZE * in;
    index = ((uint16_t)findex) & 0x1ff;
    fract = findex - (float) index;

    a = sinTable_f32[index];
    b = sinTable_f32[index+1];

    sinVal = (1.0f-fract)*a + fract*b;

    return (sinVal);
}
#define SAMPLE_FREQ 282352    // the sample frequence of the pwm that is to be filtered by the attached low pass filter.
void DF_TIM8PwmInit(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;

    RCC_Configuration();  //configure the RCC clock of related modules i.e. GPIOC,TIM8 etc.
    GPIO_Configuration();  //configure the GPIO pin for TIM8 as alternate function.
    DMA_Configuration();   //configure DMA channel for TIM8 the indicated out compare channel.
    TIM_TimeBaseStructure.TIM_Period = 255; //set the sine wave

    /*the source lock of TIM8 is 72MHz */
    TIM_TimeBaseStructure.TIM_Prescaler = 1 - 1; // set the prescaler of TIM8 as 0,so the input clock of TIM8 is 72MHz.
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // the counter mode is configured as upcounting mode
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;
    TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);


    /*configure the TIM8 as PWM1 Mode.*/
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OCInitStructure.TIM_Pulse = 0;        // this parameter is very important,since the sine wave generating depends on changing the Pulse value which will be assined to CCRx.
                                              // of course the example is based on the DMA way, with the value of the CCRx register is updated by  TIM8_CCR1_Address,so user can ignore the variable.
    TIM_OC1Init(TIM8, &TIM_OCInitStructure);  // initailize TIM8 out compare chanel
    TIM_DMACmd(TIM8, TIM_DMA_CC1, ENABLE);    // enable the TIM8's out compare 1 chanle addressed by DMA.
}

const float pi = 3.1415;

/*calculate the a table depending on the Freq ,whose elements are used to update TIM8_CCR1_Address's value  */
void DF_SinFreqSet(uint32_t Freq)
{
    float fraction;
    uint16_t i,a;
    uint16_t Sample_Num;

    /*calculate the number of the sample point*/
    Sample_Num = SAMPLE_FREQ / Freq;
    for (i = 0; i < Sample_Num; i++)
    {
      /*use the formula to calculate the value corresponding to each point  */
      Ctcs_Table[i] = 127 * arm_sin_f32( 2 * pi * i / Sample_Num) + 128;

    }

    /*tell the DMA controller the total number of the data is to be transmit */
    DMA2_Channel3->CNDTR = Sample_Num;


}

/*start the sinewave generating.*/
void DF_SinStart(void)
{
    /* DMA enable*/
    DMA_Cmd(DMA2_Channel3, ENABLE);
    /*enable the PWM out compare  of TIM8*/
    TIM_CtrlPWMOutputs(TIM8,ENABLE);
    /*enable the TIM8 module*/
    TIM_Cmd(TIM8,ENABLE);
}

/*stop the sinewave generating*/
void DF_SinStop(void)
{
    /* DMA disable*/
    DMA_Cmd(DMA2_Channel3, DISABLE);
    /*disable the PWM out compare  of TIM8*/
    TIM_CtrlPWMOutputs(TIM8, DISABLE);
     /*disable the TIM8 module*/
    TIM_Cmd(TIM8, DISABLE);
}

void setup()
{
    /*initialize the TIM8 mode and DNMA etc. */
    DF_TIM8PwmInit();
     /*set the sine-wave frequence as 1000Hz*/
    DF_SinFreqSet(1000);
    /*start the sine-wave generating*/
    DF_SinStart();
}

void loop() {

    delay(10000);
    /*expire the sine-wave Generating*/
    DF_SinStop();
    delay(10000);
    /*change the sine-wave frequence as 2KHz*/
    DF_SinFreqSet(2000);
    /*start the sine-wave generating*/
    DF_SinStart();


}

SWD

STM32F103RET6 supports SWD online simulation debugging, it needs 4 pins: GND, RST, SWDIO, SWDCLK. The upload speed can reach 10M/s. Bluno M3 retains SWD port for STM32 standard development. It is easy to monitor STM32 internal register parameters and the status of program running via the SWD port.

If you need this function, you will need an emulator. Compatible emulators are ST-link and J-Link, and their corresponding IDEs are IAR and Keil4. Arduino IDE doesn't support SWD online debugging, so you need to change to IAR. Related instructions are well documented online.