关于ARM
ARM公司设计的处理器内核有很多种,根据不同的应用场景和性能需求,可以选择不同的内核进行设计。以下是一些常见的ARM内核:
- Cortex-A系列:面向高性能应用领域的内核,主要用于移动设备、智能终端、高端嵌入式系统等领域。Cortex-A系列内核具有高性能、高可扩展性、丰富的外设接口和低功耗等优点。
- Cortex-R系列:面向实时应用领域的内核,主要用于工业控制、汽车电子、航空航天等领域。Cortex-R系列内核具有高可靠性、低延迟、强实时性和硬件保护等特点。
- Cortex-M系列:面向低功耗嵌入式系统的内核,主要用于智能传感器、便携式设备、家用电器等领域。Cortex-M系列内核具有低功耗、低成本、高效能、易于开发等特点。
- ARM7系列:面向嵌入式系统领域的内核,主要用于控制器、存储设备、安全芯片等领域。ARM7系列内核具有低成本、低功耗、高集成度、易于开发等特点。
- ARM9系列:面向嵌入式系统领域的内核,主要用于数字音视频、通信、网络设备等领域。ARM9系列内核具有高性能、多媒体处理能力、丰富的外设接口和易于扩展等特点。
Cortex-M系列是ARM公司推出的一种面向低功耗嵌入式系统的处理器内核,主要用于智能传感器、便携式设备、家用电器等领域。Cortex-M系列内核具有低功耗、低成本、高效能、易于开发等特点,是目前嵌入式系统领域最受欢迎的处理器内核之一。根据不同的性能和功耗需求,Cortex-M系列内核又分为以下几类:
- Cortex-M0系列🌟:面向低功耗、成本敏感型应用,适用于智能传感器、安全芯片、家用电器等领域。Cortex-M0系列内核的主频通常在10MHz-50MHz之间,具有低功耗、低成本、易于开发等特点。
- Cortex-M3系列:面向高性能、实时应用,适用于工业控制、汽车电子、医疗设备等领域。Cortex-M3系列内核的主频通常在50MHz-120MHz之间,具有高性能、强实时性和硬件保护等特点。
- Cortex-M4系列🌟:基于Cortex-M3系列内核,增加了DSP和浮点运算单元,适用于音视频处理、图像处理、控制算法等领域。Cortex-M4系列内核的主频通常在80MHz-240MHz之间,具有高性能、DSP(Digital Signal Processing)和浮点运算能力等特点。
- Cortex-M7系列:基于Cortex-M4系列内核,增加了双精度浮点运算单元和指令预取器等特性,适用于音视频编解码、高速通信等领域。Cortex-M7系列内核的主频通常在200MHz-400MHz之间,具有高性能、低延迟和高精度的浮点运算能力等特点。
GD32的产品系列
- L系列:基于Cortex-M3内核,主要特点是低功耗和低成本,适用于高端家电、消费电子、医疗设备、工业控制等领域。
- F系列:基于Cortex-M4内核,主要特点是高性能和丰富的外设资源,适用于高端消费电子、医疗设备、工业控制、安防监控等领域。
- E系列:基于Cortex-M0+内核,主要特点是超低功耗和小尺寸,适用于物联网、可穿戴设备、智能家居等领域。
- V系列:基于Cortex-M0内核,主要特点是低功耗和高性价比,适用于低端家电、消费电子、LED灯等领域。
- C系列:基于Cortex-M4内核,主要特点是高性能和低功耗,适用于智能家居、安防监控、工业控制等领域。
- W系列:基于Cortex-M3内核,主要特点是超低功耗和高性价比,适用于物联网、可穿戴设备等领域。
- A系列:基于Cortex-A7内核,主要特点是高性能和丰富的外设资源,适用于高端工业控制、嵌入式计算机等领域。
GD32F470ZG
gpio
推挽输出
rcu_periph_clock_enable(RCU_GPIOx);
gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_x);
gpio_output_options_set(GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_x);
开漏输出
rcu_periph_clock_enable(RCU_GPIOx);
gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_x);
gpio_output_options_set(GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, GPIO_PIN_x);
开漏上拉输出
rcu_periph_clock_enable(RCU_GPIOx);
gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_x);
gpio_output_options_set(GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, GPIO_PIN_x);
上拉输入
rcu_periph_clock_enable(RCU_GPIOx);
gpio_mode_set(GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_x);
下拉输入
rcu_periph_clock_enable(RCU_GPIOx);
gpio_mode_set(GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_x);
电平读取
FlagStatus state = gpio_input_bit_get(GPIOx, GPIO_PIN_x);
串口
Usart0.h
#ifndef __USART0_H__
#define __USART0_H__
#include "gd32f4xx.h"
#include <stdio.h>
#define USART0_RX_ENABLE 1
void Usart0_init();
void Usart0_send_byte(uint8_t data);
void Usart0_send_string(char* data);
#if USART0_RX_ENABLE
extern void Usart0_recv(uint8_t* data, uint32_t len);
#endif
#endif
Usart.c
#include "Usart0.h"
#if USART0_RX_ENABLE
#define USART_RECEIVE_LENGTH 1024
//串口接收缓冲区大小
uint8_t g_recv_buff[USART_RECEIVE_LENGTH]; // 接收缓冲区
//接收到字符存放的位置
uint32_t g_recv_length = 0;
#endif
//1. 初始化
void Usart0_init() {
// 哪个串口
uint32_t usartx = USART0;
uint32_t usartx_rcu = RCU_USART0;
uint32_t usartx_irq = USART0_IRQn;
// 波特率
uint32_t usartx_p_baudrate = 115200;
// tx和rx,用了哪个引脚
uint32_t usartx_tx_port_rcu = RCU_GPIOA;
uint32_t usartx_tx_port = GPIOA;
uint32_t usartx_tx_pin = GPIO_PIN_9;
// 复用功能编号
uint32_t usartx_tx_af = GPIO_AF_7;
// tx和rx,用了哪个引脚
uint32_t usartx_rx_port_rcu = RCU_GPIOA;
uint32_t usartx_rx_port = GPIOA;
uint32_t usartx_rx_pin = GPIO_PIN_10;
// 复用功能编号
uint32_t usartx_rx_af = GPIO_AF_7;
/*************** gpio *****************/
// TX
// 配置时钟
rcu_periph_clock_enable(usartx_tx_port_rcu);
// 配置模式: 复用功能
gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
// 配置复用功能
gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
// RX
// 配置时钟
rcu_periph_clock_enable(usartx_rx_port_rcu);
gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
// 配置输出参数
gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
/*************** usart ****************/
// 串口时钟
rcu_periph_clock_enable(usartx_rcu);
// USART复位
usart_deinit(usartx);
// 波特率
usart_baudrate_set(usartx, usartx_p_baudrate);
// 校验位
usart_parity_config(usartx, USART_PM_NONE);
// 数据位数
usart_word_length_set(usartx, USART_WL_8BIT);
// 停止位
usart_stop_bit_set(usartx, USART_STB_1BIT);
// 先发送高位还是低位
usart_data_first_config(usartx, USART_MSBF_LSB);
// 发送功能配置
usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
#if USART0_RX_ENABLE
// 接收功能配置
usart_receive_config(usartx, USART_RECEIVE_ENABLE);
// 接收中断配置
nvic_irq_enable(usartx_irq, 2, 2);
// usart int rbne
usart_interrupt_enable(usartx, USART_INT_RBNE);
usart_interrupt_enable(usartx, USART_INT_IDLE);
#endif
// 使能串口
usart_enable(usartx);
}
//2. 发送
void Usart0_send_byte(uint8_t data) {
//通过USART发送
usart_data_transmit(USART0, data);
//判断缓冲区是否已经空了
//FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
void Usart0_send_string(char* data) {
while(data && *data) {
Usart0_send_byte((uint8_t)(*data));
data++;
}
}
// printf打印功能
int fputc(int ch, FILE *f){
Usart0_send_byte((uint8_t)ch);
return ch;
}
#if USART0_RX_ENABLE
// 名称不能随意改,串口0的中断,就是这个名字
void USART0_IRQHandler(void) {
if ((usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) == SET) {
uint16_t value = usart_data_receive(USART0);
g_recv_buff[g_recv_length] = value;
g_recv_length++;
}
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) {
//读取缓冲区,清空缓冲区
usart_data_receive(USART0);
g_recv_buff[g_recv_length] = '\0';
// TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
// printf("recv: %s\r\n", g_recv_buff);
Usart0_recv(g_recv_buff, g_recv_length);
g_recv_length = 0;
}
}
#endif
外部中断
硬件中断
static void EXTI_config() {
uint32_t extix = EXTI_0;
uint32_t extix_irq = EXTI0_IRQn;
uint32_t extix_irq_pre = 1;
uint32_t extix_irq_sub = 1;
uint32_t extix_trig = EXTI_TRIG_BOTH;
uint32_t extix_rcu = RCU_GPIOA;
uint32_t extix_port = GPIOA;
uint32_t extix_pin = GPIO_PIN_0;
uint32_t extix_pupd = GPIO_PUPD_NONE;
uint32_t extix_src_port = EXTI_SOURCE_GPIOA;
uint32_t extix_src_pin = EXTI_SOURCE_PIN0;
/*************** gpio ****************/
// PA0,
// 时钟初始化
rcu_periph_clock_enable(extix_rcu);
// 配置GPIO模式
gpio_mode_set(extix_port, GPIO_MODE_INPUT, extix_pupd, extix_pin);
/*************** exti ****************/
// 时钟配置
rcu_periph_clock_enable(RCU_SYSCFG);
// 配置中断源
syscfg_exti_line_config(extix_src_port, extix_src_pin);
// 中断初始化
exti_init(extix, EXTI_INTERRUPT, extix_trig);
// 配置中断优先级
nvic_irq_enable(extix_irq, extix_irq_pre, extix_irq_sub);
// 使能中断
exti_interrupt_enable(extix);
// 清除中断标志位
exti_interrupt_flag_clear(extix);
}
软件中断
static void EXTI_config() {
uint32_t extix = EXTI_0;
uint32_t extix_irq = EXTI0_IRQn;
uint32_t extix_irq_pre = 1;
uint32_t extix_irq_sub = 1;
uint32_t extix_trig = EXTI_TRIG_BOTH;
uint32_t extix_rcu = RCU_GPIOA;
uint32_t extix_port = GPIOA;
uint32_t extix_pin = GPIO_PIN_0;
uint32_t extix_pupd = GPIO_PUPD_NONE;
uint32_t extix_src_port = EXTI_SOURCE_GPIOA;
uint32_t extix_src_pin = EXTI_SOURCE_PIN0;
/*************** gpio ****************/
// PA0,
// 时钟初始化
rcu_periph_clock_enable(extix_rcu);
// 配置GPIO模式
gpio_mode_set(extix_port, GPIO_MODE_INPUT, extix_pupd, extix_pin);
/*************** exti ****************/
// 时钟配置
rcu_periph_clock_enable(RCU_SYSCFG);
// 配置中断源
syscfg_exti_line_config(extix_src_port, extix_src_pin);
// 中断初始化
exti_init(extix, EXTI_INTERRUPT, extix_trig);
// 配置中断优先级
nvic_irq_enable(extix_irq, extix_irq_pre, extix_irq_sub);
// 使能中断
exti_interrupt_enable(extix);
// 清除中断标志位
exti_interrupt_flag_clear(extix);
}
GD32F4中断线编号
GD32F4复用功能查询
PA
PB
PC
PD
PE
PF
PG
PH
PI
GD32F4串口引脚查询
GD32F4时钟树查询
架构图
时钟树
GD32F4定时器查询
类型 | 编号 | 引脚 | 计数模式 | 互补和死区 | |||
正极性 | 负极性 | ||||||
高级 | 定时器0 | 复用AF1 | CH0 | PA7 ON,PA8,PB13 ON | 向上 | PA8 | PA7 ONPB13 ON |
CH1 | PA9,PB0 ON,PB14 ON, | PA9 | PB0 ONPB14 ON | ||||
CH2 | PA10,PB1 ON,PB15 ON | PA10 | PB1 ONPB15 ON | ||||
CH3 | PA11,PE14 | ||||||
BRKIN | PA06,PB12,PE15 | ||||||
ETI | PE7 | ||||||
定时器7 | 复用AF3 | CH0 | PA5 ON,PA7 ON,PC6 | 向上 | PC6 | PA5 ONPA7 ON | |
CH1 | PB0 ON,PB14 ON,PC7, | PC7 | PB0 ONPB14 ON | ||||
CH2 | PB1 ON,PB15 ON,PC8, | PC8 | PB1 ONPB15 ON | ||||
CH3 | PC9,PI2 | NONE | |||||
BRKIN | PA6,PI4 | ||||||
ETI | PA0,PI3 | ||||||
通用(L0) | 定时器1 | 复用AF1 | CH0 | PA0,PA5,PA15,PB8 | 向上 | ||
CH1 | PA1,PB3,PB9 | ||||||
CH2 | PA2,PB10 | ||||||
CH3 | PA3,PB2,PB11 | ||||||
ETI | PB8 | ||||||
定时器2 | 复用AF2 | CH0 | PA6,PB4,PC6 | 向上 | |||
CH1 | PA7,PB5,PC7 | ||||||
CH2 | PB0,PC8 | ||||||
CH3 | PB1,PC9 | ||||||
ETI | PD2 | ||||||
定时器3 | 复用AF2 | CH0 | PB6,PD12 | 向上 | |||
CH1 | PB7,PD13 | ||||||
CH2 | PB8,PD14 | ||||||
CH3 | PB9,PD15 | ||||||
ETI | PE0 | ||||||
定时器4 | 复用AF2 | CH0 | PA0,PH10 | 向上 | |||
CH1 | PA1,PH11 | ||||||
CH2 | PA2,PH12 | ||||||
CH3 | PA3,PI0 | ||||||
通用(L1) | 定时器8 | 复用AF3 | CH0 | PA2,PE5 | 向上 | ||
CH1 | PA3,PE6 | ||||||
定时器11 | 复用AF9 | CH0 | PB14,PH6 | 向上 | |||
CH1 | PB15,PH7 | ||||||
通用(L2) | 定时器9 | 复用AF3 | CH0 | PB8,PF6 | 向上 | ||
定时器10 | 复用AF3 | CH0 | PB9,PF7 | 向上 | |||
定时器12 | 复用AF9 | CH0 | PA6,PF8 | 向上 | |||
定时器13 | 复用AF9 | CH0 | PA7,PF9 | 向上 | |||
基本 | 定时器5 | 倍频4 | NONE | 向上 | |||
定时器6 | 倍频4 | 向上 |
GD32F4 DMA功能查询
DMA0
DMA1
GD32F4的I2C查询
SCL | SDA | TXFRAME | SMBA |
|
|
|
|
|
|
|
|
|
|
|
|
GD32F4之ADC查询
通道 | ADC0 | ADC1 | ADC2 | |
外部通道 | IN0 | PA0 | PA0 | PA0 |
IN1 | PA1 | PA1 | PA1 | |
IN2 | PA2 | PA2 | PA2 | |
IN3 | PA3 | PA3 | PA3 | |
IN4 | PA4 | PA4 | PF6 | |
IN5 | PA5 | PA5 | PF7 | |
IN6 | PA6 | PA6 | PF8 | |
IN7 | PA7 | PA7 | PF9 | |
IN8 | PB0 | PB0 | PF10 | |
IN9 | PB1 | PB1 | PF3 | |
IN10 | PC0 | PC0 | PC0 | |
IN11 | PC1 | PC1 | PC1 | |
IN12 | PC2 | PC2 | PC2 | |
IN13 | PC3 | PC3 | PC3 | |
IN14 | PC4 | PC4 | PF4 | |
IN15 | PC5 | PC5 | PF5 | |
内部通道 | IN16 | 温度 | ||
IN17 | Vref | |||
电池电压通道 | IN18 | VBAT |
GD32F4之SPI查询
MOSI | MISO | SCK | NSS | |
SPI0 | PA7 | PA6 | PA5 | PA4 |
PB5 | PB4 | PB3 | PA15 | |
SPI1 | PB15 | PB14 | PA9 | PB9 |
PC1 | PC2 | PB10 | PB12 | |
PC3 | PI2 | PB13 | PD1 | |
PI3 | PC7 | PI0 | ||
PD3 | ||||
PI1 | ||||
SPI2 | PB0 | PB4 | PB3 | PA4 |
PB2 | PC11 | PC10 | PA15 | |
PB5 | ||||
PC1 | ||||
PC12 | ||||
PD0 | ||||
PD6 | ||||
SPI3 | PA1 | PA11 | PB13 | PB12 |
PE6 | PD0 | PE2 | PE4 | |
PE14 | PE5 | PE12 | PE11 | |
PG13 | PE13 | PG11 | PG14 | |
PG12 | ||||
SPI4 | PA10 | PA12 | PB0 | PB1 |
PB8 | PE13 | PE12 | PE11 | |
PE14 | PF8 | PF7 | PF6 | |
PF9 | PH7 | PH6 | PH5 | |
PF11 | ||||
SPI5 | PG14 | PG12 | PG13 | PG8 |
SPI5_IO2: PG10 | SPI5_IO3: PG11 |
独立看门狗
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"
void Usart0_on_recv(uint8_t* data, uint32_t len) {
printf("recv: %s\r\n", data);
}
static void wtd_config() {
fwdgt_config(2 * 500, FWDGT_PSC_DIV64);
fwdgt_enable();
}
int main(void)
{
systick_config();
Usart0_init();
wtd_config();
printf("start\r\n");
while(1) {
delay_1ms(960);
/* reed dog */
fwdgt_counter_reload();
}
}
窗口看门狗
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"
void Usart0_on_recv(uint8_t* data, uint32_t len) {
printf("recv: %s\r\n", data);
}
static void wtd_config() {
rcu_periph_clock_enable(RCU_WWDGT);
/*
* System clock up to 240Mhz, PCLK1=60MHz
* set WWDGT clock = (PCLK1 (60MHz)/4096)/4 = 3662Hz (~273 us)
* set counter value to 127
* set window value to 80
* refresh window is: ~273 * (127-80)= 5.9ms < refresh window < ~273 * (127-0x3F) =17.5ms.
*/
wwdgt_config(127, 80, WWDGT_CFG_PSC_DIV4);
wwdgt_enable();
}
int main(void)
{
systick_config();
Usart0_init();
wtd_config();
printf("start\r\n");
while(1) {
delay_1ms(13);
/* update WWDGT counter */
wwdgt_counter_update(127);
}
}