Getting Started with the Cypress/Spansion FM0+ S6E1B8 Series Microcontrollers

Created by Matthew Bon, last modified on Apr 12, 2016

image

Useful Links:

S6E1B8 FM0+ Starter Kit

S6E1B Starter Kit Cypress page

FM0+ Cypress Page

Background:

This article will demonstrate how to create a simple demo application for the Cypress S6E1B8 microcontroller in which the brightness of a LED is controlled by adjusting a potentiometer. This example will show how to setup and utilize Cypress’s FM0+ Peripheral Driver Library on the S6E1B8 as well as how to use a base timer to generate pulse width modulation and how to setup and use the 12 bit SAR analog to digital converter.

Creating the Project using IAR Embedded Workbench:

  • Download the S6E1B8 Start kit complete setup file, shown below, from Cypress’s website: S6E1B8 Starter Kit page

  • Follow the directions on the install wizard to install the drivers and extract the PDL file.

  • Once the “FM_PDL_2.0.1” file is downloaded and extracted, navigate to \FM_PDL_2.0.1\template\IAR folder and open the example project:

  • Once the workspace is open, right click the project and select “Options”

  • Now, the tool chain needs to be configured. The section below details the process for the S6E1B8 microcontroller. The same process can be used for any member of the FM0+ family, however the exact files selected will be different for each microcontroller series.

Setting up the tool chain for the S6E1B8.

  1. In the “Options” window, select the “General Options” section. In the “Target” tab, make sure that “None” is selected for the device and “Cortex M0+” is selected for the core.

  2. Select the “Linker” section. Make sure that “PROJ_DIR\config\s6e1b8x\s6e1b86.icf” is selected as the linker configuration file.

  3. Select the debugger section. Under the setup section, make sure “CMSIS DAP” is selected and the setup macro is “PROJ_DIR\config\s6e1b8x\Ram_VTOR_s6e1b8.mac”. Under the “Download” tab, make sure the flash loader is “PROJ_DIR\config\s6e1b8x\flashloader\FlashLoader.board”.


  4. Select the “CMSIS DAP” Section, under the “JTAG/SWD” tab, make sure that “SWD” is selected.

  5. Click OK to apply the apply the changes.

  6. Next open up the pdl_devices.h file and change the MCU series to PDL_DEVICE_SERIES_S6E1B8X and the MCU package to PDL_DEVICE_PACKAGE_S6_E. Note that the MCU package determines how the PDL maps to the GPIO pins so each microcontroller family will have a different MCU package for each pinout that exists for that particular MCU.
    image

  7. Finally, it is important to check that the project has been configured correctly. To do this, simply select “Rebuild All” under the “Project” menu. If the project builds without errors, then it is most likely configured correctly.

Setting up PWM:

This section details how to setup a base timer for PWM operation. The ConfigurePWM() function shown in this section will be used later in the example program.

  • In the pdl_user.h file, enable GPIO operation, the base timer, and base timer modes as shown.

  • In main.c, define the following variables.

PWM defines and globals

/*Defines*/
#define User_Timer  BT5
               
/*Globals*/
 
//PWM globals
uint16_t Pulse_Value =  9999;     //Duty Cycle Value
stc_bt_pwm_config_t stcPwmConfig; //PWM Configuration Structure
  • Using the variables in the last step, the following function can be used to configure and start a timer in PWM mode.

ConfigurePWM()

void ConfigurePWM(void)
{
   /*Wipe structure*/
    PDL_ZERO_STRUCT(stcPwmConfig);
     
  /*Configure and Initialize PWM timer*/
    stcPwmConfig.enPres = PwmPres1Div4;              //20Mhz/4 = 5Mhz PWM clock
    stcPwmConfig.enMode = PwmContinuous;             //Enable continous mode
    stcPwmConfig.enExtTrig = PwmExtTrigDisable;      //Disable External Trigger
    stcPwmConfig.enOutputMask = PwmOutputNormal;     //Normal Output (no Mask)
    stcPwmConfig.enOutputPolarity = PwmPolarityLow;  //Initial Polarity Low
    stcPwmConfig.enRestartEn = PwmRestartEnable;     //Restart Enabled 
  
    Bt_Pwm_Init(&User_Timer , &stcPwmConfig);        //Init PWM with new Config 
     
     
    /* Set I/O mode */
    Bt_ConfigIOMode(&User_Timer, BtIoMode0);
     
     
    /* Set cycle and duty value*/
    Bt_Pwm_WriteCycleVal(&User_Timer, 9999); // Cycle = 200us
    Bt_Pwm_WriteDutyVal(&User_Timer,  Pulse_Value); // Duty = start at 100%
             
    /*Enable Counter Operation*/
    Bt_Pwm_EnableCount(&User_Timer);
     
    /*Enable Software Trigger/Start PWM timer*/
    Bt_Pwm_EnableSwTrig(&User_Timer);
}

Configuring the ADC:

This section demonstrates how to setup the ADC. The ConfigureADC() function shown in this section will be used later in the example program.

  • In the pdl_user.h file, enable the following

  • In main.c define the following global variables.

ADC Globals

//ADC globals
stc_adcn_t       *pstcAdc = (stc_adcn_t *)&ADC0;
stc_adc_config_t stcConfig;                  
stc_adc_prio_t   stcPrioCfg;
uint16_t         ADC_Val          = 0;   //ADC Voltage Reading
uint32_t         ADC_READ         = 0;   //ADC FIFO Data  
uint32_t         Sample_Count     = 10;
  • Using the variables in the section above, the function below can be used to configure the ADC

ConfigureADC()

 void ConfigureADC(void)
{
    /*Wipe structures*/
    PDL_ZERO_STRUCT(stcConfig);
    PDL_ZERO_STRUCT(stcPrioCfg);
     
    /*Initialize priority conversion*/
    stcPrioCfg.bPrioExtTrigStartEnable = FALSE; //Disable External trigger
    stcPrioCfg.bPrioTimerStartEnable = FALSE;   //Disable Timer trigger start
    stcPrioCfg.enPrioTimerTrigger = AdcNoTimer; //Disable Trigger timer
    stcPrioCfg.u8PrioFifoDepth = 0;             //Set FIFO depth = 1 reading
    stcPrioCfg.u8PrioLevel1AnalogChSel = 0;
    stcPrioCfg.u8PrioLevel2AnalogChSel = 19;    //Select ADC input pin AN19
     
    stcConfig.u32SamplingTimeSelect.u32AD_CHn = 0; //Sample on channel 0 
    stcConfig.enSamplingTimeN0 = Value8;    //ST N0 Config bits
    stcConfig.u8SamplingTime0 = 8u;         //ST value for 0
    stcConfig.enSamplingTimeN1 = Value8;    //ST N1 Config bits
    stcConfig.u8SamplingTime1 = 8u;         //ST value for 1
    stcConfig.u8ComparingClockDiv = 3u;     //Frequency division ratio
    stcConfig.pstcPrioInit = &stcPrioCfg;  
}
  • Once the ConfigureADC function has been called, the following code can be used to start the ADC, perform a conversion and extract the data.

Operating the ADC

  /*Start ADC*/
    if ( Adc_Init(pstcAdc, &stcConfig) == Ok)        //Init ADC0
    {
        Adc_EnableWaitReady(pstcAdc);               //Enable ADC0 & wait for initialization
    }
  
    Adc_SwTriggerPrio(pstcAdc);                     //Trigger ADC0
        while (1)
        {
            if (TRUE == Adc_GetIrqFlag(pstcAdc, AdcPrioIrq)) //Wait for ADC conversion
            {
                Adc_ClrIrqFlag(pstcAdc, AdcPrioIrq);
                break;
            }
        }
         
  ADC_READ = Adc_ReadPrioFifo(pstcAdc); //Read ADC FIFO
         
  ADC_Val = Adc_GetPrioData(pstcAdc, ADC_READ); //Get voltage reading

Example Program:

The section contains an example program using the PWM and ADC configuration functions To use this example program, simply replace the main.c and pdl_user.h files in the FM_PDL_2.0.1 IAR example project with the ones included in this section. In addition, this section also includes a flowchart of the program’s operation as well as a code block which details all of the main.c file.

Source Files:

main.c (4.2 KB)

pdl_user.h (63.9 KB)

Flowchart:

Program Flowchart

Code Block:

Example Program Code
Main.c

/*
*
* FM0+ Example program
* This program reads the analog voltage on AN19 and uses it to adjust the PWM output on TIOA5
*
*This example was based in part on the FM0+ examples by Edison Zhang, Spansion Corporation.
*
**/ 
 
/*Includes*/
#include "pdl_header.h"
 
/*Defines*/
#define User_Timer  BT5
               
/*Globals*/ 
 
//PWM globals
uint16_t Pulse_Value =  9999;     //Duty Cycle Value
stc_bt_pwm_config_t stcPwmConfig; //PWM Configuration Structure
 
//ADC globals
stc_adcn_t       *pstcAdc = (stc_adcn_t *)&ADC0;
stc_adc_config_t stcConfig;                  
stc_adc_prio_t   stcPrioCfg;
uint16_t         ADC_Val          = 0;   //ADC Voltage Reading
uint32_t         ADC_READ         = 0;   //ADC FIFO Data  
uint32_t         Sample_Count     = 10;  
 
/*Function prototypes*/
void ConfigurePWM(void); 
void ConfigureADC(void);
    
/*Main*/
int32_t main(void)
{
    
   /* Initialize GPIO pin as PWM pin..aka map the base timer to the correct IO port  */
    SetPinFunc_TIOA5_1_OUT();
     
    /*Configure ADC*/
    ConfigureADC();
     
    /*Configure and Start PWM*/
    ConfigurePWM();
     
     
    /*Start ADC*/
    if ( Adc_Init(pstcAdc, &stcConfig) == Ok)        //Init ADC0
    {
        Adc_EnableWaitReady(pstcAdc);               //Enable ADC0 & wait for initialization
    }
     
     
    /* Read ADC and adjust Duty Cycle*/
    while(1)
    {         
         
        Adc_SwTriggerPrio(pstcAdc);                 //Trigger ADC0
        while (1)
        {
            if (TRUE == Adc_GetIrqFlag(pstcAdc, AdcPrioIrq)) //Wait for ADC conversion
            {
                Adc_ClrIrqFlag(pstcAdc, AdcPrioIrq);
                break;
            }
        }
         
        ADC_READ = Adc_ReadPrioFifo(pstcAdc); //Read ADC FIFO
         
        ADC_Val = Adc_GetPrioData(pstcAdc, ADC_READ); //Get voltage reading
         
        Pulse_Value = 9999 - ADC_Val*2; //Scale Duty Cycle to ADC reading
         
        Bt_Pwm_WriteDutyVal(&User_Timer,Pulse_Value);//Write new Duty Cycle
         
         
     };
  
}
 
void ConfigurePWM(void)
{
   /*Wipe structure*/
    PDL_ZERO_STRUCT(stcPwmConfig);
     
  /*Configure and Initialize PWM timer*/
    stcPwmConfig.enPres = PwmPres1Div4;              //20Mhz/4 = 5Mhz PWM clock
    stcPwmConfig.enMode = PwmContinuous;             //Enable continous mode
    stcPwmConfig.enExtTrig = PwmExtTrigDisable;      //Disable External Trigger
    stcPwmConfig.enOutputMask = PwmOutputNormal;     //Normal Output (no Mask)
    stcPwmConfig.enOutputPolarity = PwmPolarityLow;  //Initial Polarity Low
    stcPwmConfig.enRestartEn = PwmRestartEnable;     //Restart Enabled 
  
    Bt_Pwm_Init(&User_Timer , &stcPwmConfig);        //Init PWM with new Config 
     
     
    /* Set I/O mode */
    Bt_ConfigIOMode(&User_Timer, BtIoMode0);
     
     
    /* Set cycle and duty value*/
    Bt_Pwm_WriteCycleVal(&User_Timer, 9999); // Cycle = 200us
    Bt_Pwm_WriteDutyVal(&User_Timer,  Pulse_Value); // Duty = start at 100%
             
    /*Enable Counter Operation*/
    Bt_Pwm_EnableCount(&User_Timer);
     
    /*Enable Software Trigger/Start PWM timer*/
    Bt_Pwm_EnableSwTrig(&User_Timer);
 
} 
 
void ConfigureADC(void)
{
    /*Wipe structures*/
    PDL_ZERO_STRUCT(stcConfig);
    PDL_ZERO_STRUCT(stcPrioCfg);
     
    /*Initialize priority conversion*/
    stcPrioCfg.bPrioExtTrigStartEnable = FALSE; //Disable External trigger
    stcPrioCfg.bPrioTimerStartEnable = FALSE;   //Disable Tiimer trigger start
    stcPrioCfg.enPrioTimerTrigger = AdcNoTimer; //Disable Trigger timer
    stcPrioCfg.u8PrioFifoDepth = 0;             //Set FIFO depth = 1 reading
    stcPrioCfg.u8PrioLevel1AnalogChSel = 0;
    stcPrioCfg.u8PrioLevel2AnalogChSel = 19;    //Select ADC input pin AN19
     
    stcConfig.u32SamplingTimeSelect.u32AD_CHn = 0; //Sample on channel 0 
    stcConfig.enSamplingTimeN0 = Value8;    //ST N0 Config bits
    stcConfig.u8SamplingTime0 = 8u;         //ST value for 0
    stcConfig.enSamplingTimeN1 = Value8;    //ST N1 Config bits
    stcConfig.u8SamplingTime1 = 8u;         //ST value for 1
    stcConfig.u8ComparingClockDiv = 3u;     //Frequency division ratio
    stcConfig.pstcPrioInit = &stcPrioCfg;  
}

Testing the Example:

  • Ensure that the dev board is connected to the PC via USB and that the drivers have installed properly.

  • On the dev boards, make sure the jumpers are configured as follows

Jumper Position
J1 Open
J2 Open
J3 2-3
J4 1-2
  • In IAR, select the “Rebuild All” from the Project Menu. Ensure the project builds without errors.

  • Once the project has built correctly, click the “Download and Debug” button, which is the Green arrow on the toolbar, or simply press “Ctrl+D” .

  • The first time the board is programmed, the following window will likely pop up.

  • To resolve this, simply click on each memory zone and select “Use Factory”. Once this has been done for all three zones, hit “Ok”

  • Once the board is enters debug mode, hit the F5 key to run the program. LED4 should shine brightest when the potentiometer, RP1, is in the full Counter-Clockwise position. As RP1 is turned Clockwise, LED4 should get dimmer until it finally turns off.

Questions / Comment

Hopefully this article helped you get started with Cypress’s FM0+ microcontrollers.
For questions or feedback about information on this or any other page, please go to the TechForum: TechForum