element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Blog Low-Cost Microcontrollers: Using a CH32V003 RISC-V Device!
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: shabaz
  • Date Created: 12 Feb 2024 4:07 AM Date Created
  • Views 21745 views
  • Likes 12 likes
  • Comments 12 comments
  • ch32v003
  • riscv
  • RV32EC
  • risc-v
Related
Recommended

Low-Cost Microcontrollers: Using a CH32V003 RISC-V Device!

shabaz
shabaz
12 Feb 2024

Table of Contents

  • Introduction
  • Microcontroller Overview
  • What’s Needed to Get Started?
  • Development Environment
  • Editing the Default Code
  • Building (Compiling) the Code
  • Running the Code
  • Build Your Own Board
  • Coding
    • General Purpose Input/Output (GPIO)
    • UART Output (print statements)
    • UART Input
  • Sample Code
  • Standby Mode
  • Problems Connecting after Programming?
  • Still Problems Connecting?
  • Summary


Introduction

I’ve rarely encountered RISC-V devices so far, but I was quite interested in checking out the CH32V003 microcontroller for simple, small applications because it is low-cost (25 pence or cents!), has a usable amount of storage (16Kbytes) and pretty reasonable set of basic peripherals! It’s a no-nonsense, straightforward microcontroller, and it doesn’t need anything more than a single decoupling capacitor to function.

This blog post discusses my first attempt at getting going with the CH32V003, covers a brief overview of the microcontroller and development environment, and how to build a custom board and perform some basic operations, specifically GPIO input/output, UART input/output, and experimenting with the Standby mode to see what the current consumption is.

image

Microcontroller Overview

The diagram below indicates what the microcontroller contains! For more details, check out the datasheet and reference manual. 

It comes in four different packages, ranging from an 8-pin device, up to 20-pin. All pins apart from the supply and ground pins can be used as GPIO, meaning up to 18 pins of GPIO are possible.

image

All the alternate functions for the GPIO pins can be easily controlled by a single 32-bit register called AFIO_PCFR1. All external interrupts can be enabled using a register called AFIO_EXTICR.

The CH32V003 operates from 2.8V to 5.5V, and current consumption ranges from up to 8mA (every peripheral enabled, and at 48 MHz clock speed) down to 400uA in a 750 kHz sleep mode (peripheral clocks can run), and 11uA in standby (no clocks running, but GPIO pin interrupts are available to wake up the device).

The CPU core runs an instruction set called RV32EC, which apparently means embedded integer capabilities and compressed instructions (ability to reduce instructions to 16 bits instead of 32 bits, where feasible). I believe the instruction set can be found here. 

The microcontroller is programmed using just a single wire called SWIO. The USB programmer is low-cost, called WCH-LinkE. In reality, it is useful to dedicate two wires to the programmer, the other being either the *RST connection on the microcontroller, or the supply (VCC). Either *RST, or control of the supply voltage can allow the programmer to initiate programming. By default, all pins other than SWIO, *RST, VCC and GND pins are GPIO. The *RST pin can be set to GPIO mode by configuring an area of Flash, which can be done by the programming tool, or from the code running on the microcontroller.

What’s Needed to Get Started?

I purchased several TSSOP-20 packaged CH32V003 chips. Their part code is CH32V003F4P6. There’s a 20-pin QFN package version called that replaces the P6 suffix with U6. If you’re not comfortable with TSSOP or QFN, there is a SOIC-16 variant, called CH32V003A4M6. As mentioned earlier, the microcontroller doesn’t need a lot of external circuitry! The circuit diagram below shows the TSSOP-20 package variant. If you’re using a different package, the pin numbering will differ (refer to the datasheet).

image

Despite purchasing some chips, to start off with, it’s probably best to pick up a small evaluation board since they are cheap. I obtained an eval board called CH32V003F4P6-EVT-R0.

image

Plus, importantly, a USB programmer tool called WCH-LinkE is required.

image

Everything, including five TSSOP-20 chips, all cost about $12/£12.

Development Environment

There are several development environments for the CV32V003. For now, I only tried the manufacturer-suggested one, called MounRiver Studio.
It is based on Eclipse, which means there is some familiarity for developers.

Once the software is installed (it only seems to be available for Windows, but there are other googleable open-source options available for Linux and Mac users), it can be started, and then File->New->MounRiver Project can be selected.

The window is populated as shown below, to select the microcontroller. Note that the Project Name needs to be set last because each time you modify the microcontroller selection, the project name defaults back to match the microcontroller name.

image

The main MounRiver Studio window view looks as shown below. In Eclipse terminology, it is known as the Code or Develop Perspective. 

image

(The view looks different when running your code, it is then called a Debug Perspective).

The most important icons are indicated below.

image

In normal development, you’ll click on Build Project (F7) to compile the code, and then click on the Debug icon (Run->Debug from the menu). The view style or Perspective can be selected from the right side, but generally, you don’t need to use the Perspective buttons often because Eclipse will automatically toggle the views between when debugging and when debugging has ended.

Editing the Default Code

The newly created project will contain default code. From the left side Project Explorer, expand the User folder, and double-click on main.c to have it appear in the coding pane. The default code reads data from the UART in the microcontroller, inverts the bits, and sends it back out of the UART.

I changed the line:

USART_SendData(USART1, ~val);

to:

USART_SendData(USART1, val+1);

Now, the UART should send back a character one ASCII code higher than what is typed by the user. Save the file (Ctrl+S), and then move on to the next section!

Building (Compiling) the Code

Click on the Build Project (F7) icon. The project will be compiled, and the result will be displayed in the Console tab in the lower pane.

image

Running the Code

Connect up the WCH-LinkE programmer to the evaluation board as shown below. There’s no need to power up the evaluation board via USB, because it will derive its power from the WCH-LinkE programmer.

image

Plug the USB cable into the PC, and then click on the Debug button (Run->Debug in the menu). When that’s clicked, the Debug Perspective will be displayed:

image

The important icons are shown in the screenshot below.

Since the example project makes use of the UART, you can open a serial console using your preferred software (such as PuTTY), or you can click on the Open Terminal icon and select the available COM port presented by the WCH-LinkE programmer, and select 115200 baud. A terminal tab will appear at the bottom pane.

image

Click on the Run icon, and the Terminal tab should show the following content:

image

Now press any alphanumeric key, and the console should display an ASCII character one value up!

The code is now incidentally in Flash, so the debugging procedure also resulted in programming the microcontroller.

Afterward, click on the Terminate icon, and the original Code (Develop) Perspective will appear again, all ready for more coding as desired.

Build Your Own Board

The CH32V003 needs no additional components other than a decoupling capacitor to function, although adding the optional reset circuit (button plus capacitor) is highly recommended.

image

The circuit diagram shown here was assembled.

image

Coding

Now that the custom board was assembled, it was time to explore coding a bit more! The following sections indicate code snippets for the custom board. The full code is available here. The snippets below are from the main.c file. 

General Purpose Input/Output (GPIO)

To configure an input, the following three lines of code are needed; this example configures GPIO PC1 to be an input with pull-up (IPU).

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);

An output is configured in a near-similar way; outputs have a speed setting (2/10/50 MHz).

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

It’s easiest to create defines to use the inputs/outputs:

// LED control (low = LED off, high = LED on)
#define LED_OFF GPIO_SetBits(GPIOC, GPIO_Pin_2)
#define LED_ON GPIO_ResetBits(GPIOC, GPIO_Pin_2)
// button pressed is active low
#define BUTTON_PRESSED (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0)
#define BUTTON_UNPRESSED (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) != 0)

UART Output (print statements)

The UART is highly useful for outputting debug statements. It is very easy to enable it:

USART_Printf_Init(115200); // this enables the use of print()

After that is done, normal printf() function calls are used to send data to any connected serial console.

UART Input

If you wish to use the UART for both input and output, then a bit more code is needed, to configure the UART more fully. See the code function uart_config_rxtx().

The UART input character buffer can be checked and read at any time using:

uint16_t ch;
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {
    ch = USART_ReceiveData(USART1);
    val = (uint8_t)(ch & 0xFF); // val contains the received character
}

The above code does not wait, so one could place the USART_GetFlagStatus function in a loop, waiting for a character to arrive if desired.

Sample Code

There is lots of example code available in a CH32V003 Example Software Routines bundle. 

├───ADC
│   ├───ADC_DMA
│   │   └───User
│   ├───AnalogWatchdog
│   │   └───User
│   ├───Auto_Injection
│   │   └───User
│   ├───Discontinuous_mode
│   │   └───User
│   ├───ExtLines_Trigger
│   │   └───User
│   └───TIM_Trigger
│       └───User
├───APPLICATION
│   └───SoftUART
│       └───User
├───DMA
│   ├───DMA_MEM2MEM
│   │   └───User
│   └───DMA_MEM2PERIP
├───EXTI
│   └───EXTI0
│       └───User
├───FLASH
│   ├───BootAsUser
│   │   ├───Ld
│   │   ├───Startup
│   │   └───User
│   └───FLASH_Program
│       └───User
├───GPIO
│   └───GPIO_Toggle
│       └───User
├───I2C
│   ├───I2C_10bit_Mode
│   │   └───User
│   ├───I2C_7bit_Mode
│   │   └───User
│   ├───I2C_DMA
│   │   └───User
│   ├───I2C_EEPROM
│   │   └───User
│   └───I2C_PEC
│       └───User
├───IAP
│   └───V00x_APP
│       └───User
├───IWDG
│   └───IWDG
│       └───User
├───OPA
│   └───OPA
│       └───User
├───PWR
│   ├───Sleep_Mode
│   │   └───User
│   └───Standby_Mode
│       └───User
├───RCC
│   ├───Get_CLK
│   │   └───User
│   └───MCO
│       └───User
├───SDI_Printf
│   └───SDI_Printf
│       └───User
├───SPI
│   ├───1Lines_half-duplex
│   │   └───User
│   ├───2Lines_FullDuplex
│   │   └───User
│   ├───FullDuplex_HardNSS
│   │   └───User
│   ├───SPI_CRC
│   │   └───User
│   └───SPI_DMA
│       └───User
├───SRC
│   ├───Core
│   ├───Debug
│   ├───Ld
│   ├───Peripheral
│   │   ├───inc
│   │   └───src
│   └───Startup
├───SYSTICK
│   └───SYSTICK_Interrupt
│       └───User
├───TIM
│   ├───Clock_Select
│   │   └───User
│   ├───ComplementaryOutput_DeadTime
│   │   └───User
│   ├───ExtTrigger_Start_Two_Timer
│   │   └───User
│   ├───Input_Capture
│   │   └───User
│   ├───One_Pulse
│   │   └───User
│   ├───Output_Compare_Mode
│   │   └───User
│   ├───PWM_Output
│   │   └───User
│   ├───Synchro_ExtTrigger
│   │   └───User
│   ├───Synchro_Timer
│   │   └───User
│   └───TIM_DMA
│       └───User
├───USART
│   ├───USART_DMA
│   │   └───User
│   ├───USART_HalfDuplex
│   │   └───User
│   ├───USART_HardwareFlowControl
│   │   └───User
│   ├───USART_Interrupt
│   │   └───User
│   ├───USART_MultiProcessorCommunication
│   │   └───User
│   ├───USART_Polling
│   │   └───User
│   ├───USART_Printf
│   │   └───User
│   └───USART_SynchronousMode
│       └───User
├───USART_IAP
│   ├───CH32V003_APP
│   │   └───User
│   └───CH32V003_IAP
│       ├───Ld
│       └───User
└───WWDG
    └───WWDG
        └───User
        

Standby Mode

I was interested to see if the standby current consumption was 11uA or not. Test code was written to exercise the GPIO, UART and Standby mode. The code doesn’t have a practical purpose. All it does is (in Standby mode) wait for the user to press a button connected to GPIO PC1. When that occurs, the microcontroller wakes up and turns on an LED for one second, and goes into Standby again. During the time the LED is turned on, the UART output will display any character that the (single byte) UART receive buffer contains.

After the code was built and uploaded to the board (by using the Debug button in the development environment as before), I disconnected the board from the programmer and powered it from three AAA batteries for a 4.5V power source and measured the current consumption.

I could see the current reach 7 mA or so with the LED lit, and then when Standby mode was entered, the current consumption would drop to 10-11uA, so that was a success. See the code to see how to set up the ability to wake up on GPIO input and how to enter the Standby mode.

Note that to achieve 10uA, it is important to set all unused GPIO to inputs with pull-ups. If you’ve configured the UART but no serial console might be connected, then a pull-up resistor on the UART receive pin may be worthwhile adding, as shown in the circuit diagram.

Problems Connecting after Programming?

There can be a risk that if the SWIO pin is configured to an input or output, then it might not be possible for the debugger to be able ever to connect again! There are a few solutions, such as never using the SWIO pin. Another option is to place a short delay in the code prior to configuring any GPIO. Then, if it is not possible for the debugger to connect due to GPIO configuration, it is possible to press the reset button and then quickly press the Debug button in the development environment, and the debugger will be able to connect during the delay. In production code, this could then be removed if there is no need for the debugger ever to be connected again.

Still Problems Connecting?

Another option could be to try running software called WCH-LinkUtility, which is in the installed MounRiver\MounRiver_Studio\ExTool\SWDTool folder. Try the Target->Clear All Code options.

image

Summary

The CH32V003 is an interesting, cheap microcontroller that was fairly straightforward to program. There doesn’t seem to be standalone documentation for the library code, but the code is well documented, and it doesn’t take too long to figure out what’s what, especially because the registers are not very complicated. Besides, the CH32V003 is very popular, so it is possible to google for information when one gets stuck.

The microcontroller needs very few parts to get going and is available in hand-solder-friendly packages ranging from the large SOIC-16 down to TSSOP-20 and QFN-20. There is also an 8-pin SOIC-8 version.

Example code was written and it confirmed that it was not too difficult to enter and exit the Standby mode.

It is possible during development to accidentally end up in a situation where the USB programmer tool cannot connect if there is a GPIO pin clash, but a workaround was found, which involves having a reset button on the board and deliberately coding in a short (2-second) delay before GPIO configuration.

If you have any ideas for potential applications for this microcontroller, it would be great to hear them.

Thanks for reading!

  • Sign in to reply

Top Comments

  • michaelkellett
    michaelkellett over 1 year ago +2
    Thanks very much for this - helps crystallise my thoughts re. cheap RiscV parts: Interesting how closely they have cloned the ST library format for their peripheral control code. Easy for us to learn…
  • thetrueman
    thetrueman 9 months ago

    Hi,

    Very informative article about classic CH32V. I would like to see this microcontroller to be used with Quadrature Encoder Up/Down Counter. Any Example is welcomed. Thanks.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Henrik
    Henrik over 1 year ago

    Thank you for the informative post.

    I have successfully completed several projects using the Ch552 8-bit version of the CH32, a robust CPU.

    I utilize the CMD line compiler SDCC (small device C compiler), an excellent tool.

    In my next project, I will experiment with the CH32 thanks to your helpful article.

    Best regards,

    Henrik Andersen

    LinkedIn  http://linkedin.com/in/uhat

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 1 year ago

    I tried the external interrupts, this code worked for me. It configures rising/falling interrupts on pins PC0 and PC1, and when there is no activity on those pins for longer than a second, then an LED on pin PC3 or PC4 will blink rapidly. It's a dual-channel keep-alive type of monitor basically (I needed it for a project).

    /********************************
     * main.c
     * synth_monitor
     * rev 1 - shabaz - Feb 2024
     ********************************/
    
    /*****************************************************
     * Connections
     * PC0 - ADF4001 MUX pin (Lock Detect) input
     * PC1 - MAX2870 LD pin (Lock Detect) input
     * PC3 - AD_OOL (ADF4001 Out of Lock LED output)
     * PC4 - MAX_OOL (MAX2870 Out of Lock LED output)
     *****************************************************/
    
    // ************ includes *************************
    #include "debug.h"
    
    // ************ defines **************************
    #define FOREVER 1
    #define TIMER_START_VAL 10
    #define LED_PC3_ON GPIO_SetBits(GPIOC, GPIO_Pin_3);
    #define LED_PC3_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_3);
    #define LED_PC4_ON GPIO_SetBits(GPIOC, GPIO_Pin_4);
    #define LED_PC4_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_4);
    
    // ************ global variables *****************
    uint16_t hold_timer_0 = 0;
    uint16_t hold_timer_1 = 0;
    uint8_t led_pc3_state = 0;
    uint8_t led_pc4_state = 0;
    
    // ************ function prototypes ***************
    void EXTI7_0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
    
    
    // ****************** functions *******************
    void pc3_toggle_led(void) {
        led_pc3_state ^= 1;
        if (led_pc3_state) {
            LED_PC3_ON;
        } else {
            LED_PC3_OFF;
        }
    }
    
    void pc4_toggle_led(void) {
        led_pc4_state ^= 1;
        if (led_pc4_state) {
            LED_PC4_ON;
        } else {
            LED_PC4_OFF;
        }
    }
    
    void out_gpio_init(void) {
        GPIO_InitTypeDef GPIO_InitStructure = {0};
    
        // enable periph clock for GPIOC
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
        // configure PC3 as output
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    
        // configure PC4 as output
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    }
    
    void ext_int_init(void) {
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        EXTI_InitTypeDef EXTI_InitStructure = {0};
        NVIC_InitTypeDef NVIC_InitStructure = {0};
    
        // enable periph clock for AFIO and GPIOC
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC, ENABLE);
    
        // configure PC0 as input with pull-up
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    
        // configure PC1 as input with pull-up
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
    
        // enable EXTI0 interrupt for PC0
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
    
        // enable EXTI1 interrupt for PC1
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);
        EXTI_InitStructure.EXTI_Line = EXTI_Line1;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
    
        NVIC_InitStructure.NVIC_IRQChannel = EXTI7_0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    
    }
    
    // **************** interrupt handlers *************
    void EXTI7_0_IRQHandler(void) {
        // PC0
        if(EXTI_GetITStatus(EXTI_Line0)!=RESET) // PC0 interrupt occurred
        {
            hold_timer_0 = TIMER_START_VAL;
            LED_PC3_OFF;
            EXTI_ClearITPendingBit(EXTI_Line0);  // clear interrupt flag
        }
        // PC1
        if (EXTI_GetITStatus(EXTI_Line1)!=RESET) // PC1 interrupt occurred
        {
            hold_timer_1 = TIMER_START_VAL;
            LED_PC4_OFF;
            EXTI_ClearITPendingBit(EXTI_Line1);  // clear interrupt flag
        }
    }
    
    // *************************************************************
    // ********************* main function *************************
    // *************************************************************
    
    int
    main(void)
    {
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        SystemCoreClockUpdate();
        Delay_Init();
    
        out_gpio_init(); // configure PC3 and PC4 as outputs (LEDs)
        ext_int_init(); // configure PC0 and PC1 as external interrupts
    
        // set hold timers to 0, i.e. assume both PLLs are out of lock
        hold_timer_0 = 0;
        hold_timer_1 = 0;
    
        while(FOREVER)
        {
            Delay_Ms(100);
            if (hold_timer_0) {
                hold_timer_0--;
            } else {
                pc3_toggle_led();
            }
            if (hold_timer_1) {
                hold_timer_1--;
            } else {
                pc4_toggle_led();
            }
        }
    
        return(0); // warning on this line is fine!
    }
    

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 1 year ago in reply to DAB

    Hi DAB,

    Not yet, but looking forward to trying that out hopefully later this week, I'll report back here when I do.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 1 year ago

    Have you had a chance to check the analog section and ADC stability?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube