初探国产RISC-V架构32位MCU--CH32V303

概述

CH32V303系列是基于32位RISC-V设计的工业级通用微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。CH32V303系列搭载V4F内核。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能,扩展串口UART数量到8组,电机定时器到4组。

产品特点

  • 青稞V4F处理器,最高144MHz系统主频
  • 支持单周期乘法和硬件除法,支持硬件浮点运算(FPU)
  • 64KB SRAM,256KB Flash
  • 供电电压:2.5/3.3V,GPIO单元独立供电
  • 多种低功耗模式:睡眠、停止、待机
  • 上/下电复位、可编程电压检测器
  • 2组18路通用DMA
  • 4组运放比较器
  • 1个随机数发生器TRNG
  • 2组12位DAC转换
  • 2单元16通道12位ADC转换,16路触摸按键TouchKey
  • 10组定时器
  • 1个USB2.0 FS主机/设备接口
  • 3个USART接口和5个UART接口
  • 1个CAN接口(2.0B主动)
  • SDIO接口、FSMC接口
  • 2组IIC接口、3组SPI接口、2组IIS接口
  • 80个I/O口,可以映射到16外部中断
  • CRC计算单元,96位芯片唯一ID
  • 串行2线调试接口
  • 封装形式:LQFP48、LQFP64M、LQFP100

EXTI外部中断+点亮LED实验

实验内容

本实验利用按键产生外部中断,在中断服务程序中令小灯闪烁,并且通过串口打印调试信息。

实验环境

采用了沁恒微电子官方推荐的MounRiver进行编程和调试,以及程序下载。这款IDE对开发做了不少优化,虽然他还是基于开源的Eclipse,利用的编译工具链和调试工具也是第三方开源的,但是用起来还是比较舒服的,尤其是强大的代码提示功能。

电路连接

验证板上的外围资源统一由ARDUINO接口引出,所以我们只要将ARDUINO接口中的LED、按键等接口通过杜邦线接到对应的GPIO口上即可完成电气连接。

首先编写按键GPIO初始化函数,由于CH32的开发SDK是基于STM32的库函数进行了移植和修改,所以程序写起来跟STM32大差不差,不过要注意使用GPIO之前必须开启GPIO端口的时钟;用到NVIC必须开启 AFIO 时钟。:

1
2
3
4
5
6
7
8
9
#include "key.h"

void keyGPIOInit(){
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

CH32V2x 和 CH32V3x 系列内置可编程快速中断控制器(PFIC– Programmable Fast Interrupt
Controller),最多支持 255 个中断向量。当前系统管理了 88 个外设中断通道和 8 个内核中断通道,
其他保留。

NVIC初始化函数,在该函数中对NVIC进行初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "../Hardware/EXTI/key_exti.h"

void keyNVICInit(void){

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
RCC_AHBPeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);

}

EXIT初始化函数,一定要记得GPIO_EXTILineConfig()函数一定不能忘记写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "../Hardware/EXTI/key_exti.h"

void keyEXTIConfig(){

EXTI_InitTypeDef EXTI_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1); //设置GPIOX中断源以及哪个中断脚
RCC_AHBPeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);


}

中断服务函数所在的ch32v30xit.c中一定要将这句话添加到文件的开头:
void EXTI1_IRQHandler(void)_attribute_((interrupt(“WCH-Interrupt-fast”)));添加了这句话,IDE在进行编译时,会将此函数体识别为中断服务函数,主动添加“压栈出栈”处理及中断返回指令。

实验现象

按下按键,led状态反转,串口打印”Run at EXTI”。