1. GD32F427V-START例程学习笔记
1.1. Demo-01\_GPIO-Running-LED
该例程实现对板载LED连接的IO引脚(PC6)设置高/低电平,实现LED的亮灭闪烁。
1.1.1. 打开项目
使用Keil打开项目文件,初次运行会提示未知设备GD32F427,可以在Keil的Pack Installer里安装对应的DFP文件包。(实际测试发现,不安装也能编译,但是下载算法需要将DFP包中的GD32F4xx\_3MB.FLM文件复制到Keil安装目录的ARMFlash下,这样才能顺利下载)
1.1.2. 代码分析
分析main函数代码运行过程,首先设置systick,然后使能LED对应的GPIO的时钟,最后设置PC6为推挽输出,并初始化为低电平。
然后在无限循环中,每隔1000ms设置PC6引脚为高/底电平,实现LED的亮灭。
int main(void)
{
/* configure systick */
systick_config();
/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOC);
/* configure LED2 GPIO port */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED2 GPIO pin */
gpio_bit_reset(GPIOC, GPIO_PIN_6);
while(1) {
/* turn on LED2 */
gpio_bit_set(GPIOC, GPIO_PIN_6);
delay_1ms(1000);
/* turn off LED2 */
gpio_bit_reset(GPIOC, GPIO_PIN_6);
delay_1ms(1000);
}
}
1.1.3. 运行效果
编译后,下载到开发板,运行效果如下:
1.2. Demo-02\_GPIO-Key-polling-mode
1.2.1. 代码分析
本例程代码在前一个例程GPIO-Running-LED的基础上,
- 对连接在User Key按键上的IO引脚(PA0)设置为输入模式,
- 然后在无限循环中,检测该按键的电平,
- 当按键按下时,设置LED翻转,然后等待按键释放,如此循环往复。
int main(void)
{
/* configure systick */
systick_config();
/* enable the LED2 clock */
rcu_periph_clock_enable(RCU_GPIOC);
/* configure LED2 GPIO port */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED2 GPIO pin */
gpio_bit_reset(GPIOC, GPIO_PIN_6);
/* enable the User Key GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* configure key pin as input */
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
while(1) {
/* check whether the key is pressed */
if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
delay_1ms(100);
/* check whether the key is pressed */
if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
gpio_bit_write(GPIOC, GPIO_PIN_6, (bit_status)(1 - gpio_input_bit_get(GPIOC, GPIO_PIN_6)));
}
while(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
}
}
}
}
1.2.2. 运行效果
编译后,下载到开发板,运行效果如下:
1.3. Demo-03\_EXTI-Key-Interrupt\_mode
本例程将按键设置为中断模式,并在中断响应函数中,闪烁LED。
1.3.1. 代码分析
1. main函数
- 设置systick、LED的GPIO,同前;
- PA0对应的GPIO的设置;
- EXTI\_0对应的NVIC中断相关的设置
int main(void)
{
/* configure systick */
systick_config();
/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOC);
/* configure LED2 GPIO port */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED2 GPIO pin */
gpio_bit_reset(GPIOC, GPIO_PIN_6);
/* flash the LED for test */
led_flash(1);
/* enable the key clock */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_SYSCFG);
/* configure key pin as input */
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
/* connect key EXTI line to key GPIO pin */
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
while(1) {
}
}
2. 在中断处理函数EXTI0\_IRQHandler中
- 首先确认是EXTI\_0的中断标志,
- 然后翻转PC6的电平,
- 最后清除EXTI\_0的中断标志。
void EXTI0_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_0)) {
gpio_bit_toggle(GPIOC, GPIO_PIN_6);
exti_interrupt_flag_clear(EXTI_0);
}
}
3. systick相关函数
- 内核定时器的初始化配置函数systick\_config中,将其主频的1/1000,即每1ms中断一次,
- 中断处理函数SysTick\_Handler中,调用delay\_decrement,
- delay\_decremen函数中,变量delay,果非零则减1,从而实现精确的毫秒定时。
void systick_config(void)
{
/* setup systick timer for 1000Hz interrupts */
if(SysTick_Config(SystemCoreClock / 1000U)) {
/* capture error */
while(1) {
}
}
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
void SysTick_Handler(void)
{
delay_decrement();
}
void delay_decrement(void)
{
if(0U != delay) {
delay--;
}
}
1.3.2. 运行效果
编译后,下载到开发板,运行效果同Demo-02,不再重复。
1.4. Demo-04\_Timer-Key-EXTI
本例程在前一个例程的基础上,添加了Timer输出到PA6,然后PA6通过杜邦线连接到PA4,PA4也跟PA0同样设置为EXTI中断,在中断响应函数中闪烁LED.
1.4.1. 代码分析
1. main函数
- main函数完成key、led、systick等设置同前。
- 然后闪烁一次LED;
- 分别调用exti、gpio、timer的设置函数。
- 进入无限循环。
int main(void)
{
/* initialize KEY and LED, configure SysTick */
gd_eval_key_init(KEY_USER, KEY_MODE_EXTI);
led_config();
systick_config();
/* flash the LED for test */
led_flash(1);
/* configure EXTI, TIMER */
exti_config();
gpio_config();
timer_config();
while(1){
}
}
2.PA6设置为TIMER2\_CH0的输出
void gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
/*Configure PA6(TIMER2_CH0) as alternate function*/
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_6);
}
- PA4设置为EXTI\_4,并在中断响应函数EXTI4\_IRQHandler中翻转LED。
void exti_config(void)
{
/* enable the clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable and set EXTI interrupt */
nvic_irq_enable(EXTI4_IRQn, 1U, 0U);
/* configure EXTI line */
exti_init(EXTI_4, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_4);
}
void EXTI4_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_4)){
gd_eval_led_toggle(LED2);
}
exti_interrupt_flag_clear(EXTI_4);
}
- Timer2设置为时钟100KHz,计数到25000/50000,在CH0分别输出高低电平。
void timer_config(void)
{
/* -----------------------------------------------------------------------
TIMER2CLK is 100KHz
TIMER2 channel0 duty cycle = (25000/ 50000)* 100 = 50%
----------------------------------------------------------------------- */
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
timer_deinit(TIMER2);
/* TIMER configuration */
timer_initpara.prescaler = 999;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 49999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
/* configurate CH0 in PWM mode0 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 24999);
timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER2);
/* auto-reload preload enable */
timer_enable(TIMER2);
}
1.4.2. 运行效果
将PA6通过杜邦线连接到PA4,并接上示波器观察Timer2\_CH0输出波形,如下:
1.5. Demo-05\_USB-MSC-Device
本例程实现一个USB大容量存储设备,使用MCU的USB-FS或者USB-HS模块作为USB接口,实现标准的MSC类,使用内部RAM作为存储空间,可以在PC上对存储空间进行格式化、文件读写等操作。
在编译时会出现“cannot find cortex-m4f.h”错误,原因在于CMSIS没有自动包含在编译头文件目录中,在Keil的options选项卡设置,如图:
1.5.1. 运行效果
用另一个USB线连接USB-FS/USB-HS对应的USB接口到PC,就可以弹出新移动存储设备的窗口,格式化后,文件的复制、读写、删除等操作,与普通U盘一致。