前言
终于在这周四拿到板子了,本来周一就可以拿到的,因为疫情封控,在周四才拿到板子,但是周内太忙了,来不及上手,趁着周末赶紧玩一玩。
首先是弄一下串口,因为串口是比较核心的一个功能,在开发过程中可以方便我们调试。
本文主要实现下面两个功能
- 本文是基于MDK开发的,实现了串口的printf以及scanf功能,完善了MDK支持的fgetc功能用于支持scanf;
- 上位机发送串口指令open以及close,下位机收到了这两个指令之后打开LED或者关闭LED;
- 如果收到的指令不是open或者close,打印Unknow command。
硬件连接
串口硬件
在操作串口之前我们需要知道板子的引脚复用关系,,以便确定使用哪一路串口。
引脚复用关系表在《GD32F427xx\_Datasheet\_Rev1.2.pdf》中2.6.6. GD32F427xx pin alternate functions。
我们可以知道USART0可以复用的引脚有PA9,PA10以及PB6,PB7。
本来打算使用PA9与PA10的,但是查看原理图可知:PA9通过一个三极管与VCC连接到了一起,通过PD2进行控制,所以不能用来作为串口引脚使用了。
所以最终确定使用PB6与PB7作为串口的TX引脚与RX引脚。
LED硬件
GD32F427V-START开发板只支持LED2作为用户LED,原理图如下:
见原理图可知,PC6为高电平的时候LED亮,PC6为低电平的时候,LED灭。
软件实现
串口初始化
串口初始化可以参考Demo示例,见GD32F4xx\_Firmware\_Library\_V3.0.2\GD32F4xx\_Firmware\_Library\Examples\USART\Printf
这是将串口通过printf实现打印功能。
static void Uart_Init(void)
{
/* USART interrupt configuration */
nvic_irq_enable(USART0_IRQn, 0, 0);
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* configure the USART0 TX pin and USART0 RX pin */
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);
/* configure USART0 TX as alternate function push-pull */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* configure USART0 RX as alternate function push-pull */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
fgetc函数实现
官方给的Demo示例中已经支持了printf重定向,其实也就是实现了fputc函数。
MDK也支持scanf的重定向,也就是需要实现fgetc函数,本文实现了fgetc函数,如下。
因为不需要支持文件系统,所以fgetc实现很简单,直接判断时候有串口数据,如果有数据则接收返回接收的数据。
int fgetc(FILE *stream)
{
while(RESET == usart_flag_get(USART0, USART_FLAG_RBNE))
{}
return usart_data_receive(USART0);
}
fputc函数实现
不做赘述,官方例程中已经实现.
实现该函数用于支持printf
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE))
{}
return ch;
}
LED初始化
static void Led_Init(void)
{
/* 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);
}
功能逻辑实现
使用scanf接收来自上位机的字符串,如果字符串为open,则打开LED2;如果字符串为close,则关闭LED2,否则打印UnKnow command。
注意:上位机再发送字符串的时候,字符串结束必须要写一个空格,不然scanf会认为输入没有结束。
#include "gd32f4xx.h"
#include "gd32f427v_start.h"
#include "systick.h"
#include <stdio.h>
#include <string.h>
int main(void)
{
char c[10];
/* configure systick */
systick_config();
/* configure the usart */
Uart_Init();
/* configure the led */
Led_Init();
printf("Startup\n\n");
while(1)
{
scanf("%s", &c[0]);
printf("Input command is %s \n", c);
if (!strcmp(&c[0], "open"))
{
gpio_bit_set(GPIOC, GPIO_PIN_6);
printf("turn on LED2 \n");
}
else if (!strcmp(&c[0], "close"))
{
gpio_bit_reset(GPIOC, GPIO_PIN_6);
printf("turn off LED2 \n");
}
else
{
printf("Unknown command \n");
}
}
}
实现结果
实现效果如下。