前言
首先是弄一下串口,因为串口是比较核心的一个功能,在开发过程中可以方便我们调试。
本文主要实现下面两个功能
1 本文是基于MDK开发的,实现了串口的printf以及scanf功能,完善了MDK支持的fgetc功能用于支持scanf;
2 上位机发送串口指令open以及close,下位机收到了这两个指令之后打开LED或者关闭LED;
3 如果收到的指令不是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)
{
nvic_irq_enable(USART0_IRQn, 0, 0);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_USART0);
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);
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);
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_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)
{
rcu_periph_clock_enable(RCU_GPIOC);
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);
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];
systick_config();
Uart_Init();
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");
}
}
}
实现结果
实现效果如下。
原作者:hehung