Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与使用
1、串口的初始化
Nucleo-F411RE自带st-link,并支持虚拟串口的功能,根据原理图,st-link的rx tx接到了Nucleo-F411RE的PA2 PA3,所以我们要初始化PA2 PA3为串口功能,这样我们就可以直接用st-link抓取打印,而不用再接一个usb转串口的模块。
由于要用letter shell,所以要配置串口为tx rx模式,发送数据我们用普通轮询模式,接收数据用中断模式,中断函数每次接收到一个数据调用一次,我们在中断函数里调用 shellHandler(&shell, received_char)去处理数据即可。
a、串口时钟初始化
所有时钟的初始化,都放在了clock_init.c中的
void BOARD_ClockInit函数中
b、gpio 、usart初始化
// 初始化PA2 PA3作为打印串口使用
static void Board_ConsoleInit(void)
{
LL_RCC_ClocksTypeDef rccClock;
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_2, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_2, LL_GPIO_AF_7);
LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_2, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_2, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_2, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_3, LL_GPIO_AF_7);
LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_3, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_3, LL_GPIO_PULL_UP);
/* (3) Configure USART functional parameters ********************************/
/* Disable USART prior modifying configuration registers */
/* Note: Commented as corresponding to Reset value */
// LL_USART_Disable(USART2);
NVIC_SetPriority(USART2_IRQn, 0);
NVIC_EnableIRQ(USART2_IRQn);
/* TX/RX direction */
LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(USART2, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
LL_RCC_GetSystemClocksFreq(&rccClock);
LL_USART_SetBaudRate(USART2, rccClock.PCLK1_Frequency, LL_USART_OVERSAMPLING_16, 115200);
/* Enable RXNE and Error interrupts */
LL_USART_EnableIT_RXNE(USART2);
LL_USART_EnableIT_ERROR(USART2);
/* (4) Enable USART *********************************************************/
LL_USART_Enable(USART2);
}
c、中断处理函数
d、printf重定向
后面完善letter shell写函数的时候,跟这个类似,直接复制过去就行。
2、letter shell的移植
下载传送门
下载后,将src中所有的文件拷贝到我们的工程中,并新建shell_port.c shell_port.h文件,目录结构如图:
shell_port.c 中内容如下:
#include “shell_port.h”
#include "shell.h"
#include "shell_port.h"
Shell shell;
char shell_buffer[512];
short userShellWrite(char *data, unsigned short len)
{
uint32_t i;
for (i = 0; i < len; i++)
{
while (!LL_USART_IsActiveFlag_TXE(USART2))
{
}
/* If last char to be sent, clear TC flag */
if (i == (len - 1))
{
LL_USART_ClearFlag_TC(USART2);
}
/* Write character in Transmit Data register.
TXE flag is cleared by writing data in DR register */
LL_USART_TransmitData8(USART2, data[i]);
}
return len;
}
void User_Shell_Init(void)
{
shell.write = userShellWrite;
shellInit(&shell, shell_buffer, 512);
}
shell_port.h内容如下:
#ifndef __SHELL_PORT_H__
#define __SHELL_PORT_H__
#include "shell.h"
#include "main.h"
extern Shell shell;
void User_Shell_Init(void);
#endif
main函数添加shell的初始化函数
如果此时编译报错,修改ld文件如下:
这样开机后,接到letter shell交互界面了。
3、Letter Shell的使用
我们添加一个命令,来控制LED灯,输入LED On灯亮,输入LED Off灯灭,
输入LED Blink 100,灯开始间隔100ms开始闪烁。
首先在shell_cfg.h使能支持外部命令的宏。
添加LED命令:
volatile static bool isBlinking = false;
volatile static long delay_time = 250;
int LED_Control(int argc,char *argv[])
{
if (argc == 2)
{
if (!strncmp(argv[1],"On",2))
{
isBlinking = false;
LED_ON();
}
else if (!strncmp(argv[1],"Off",3))
{
isBlinking = false;
LED_OFF();
}
else
{
printf(" param error.please use LED On/LED Off/LED Blink 200\r\n");
return -1;
}
}
else if (argc == 3)
{
if(!strncmp(argv[1],"Blink",5))
{
delay_time = strtol(argv[2],NULL,10);
if (delay_time > 0)
{
isBlinking = true;
}
else
{
isBlinking = false;
printf("please LED Blink 200 \r\n");
LED_OFF();
return -1;
}
}
else
{
printf(" param error.please use LED On/LED Off/LED Blink 200\r\n");
return -1;
}
}
else
{
printf(" param error.please use LED On/LED Off/LED Blink 200\r\n");
return -1;
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), LED, LED_Control, LED_Control);
编译后重新烧录,在串口中输入相关命令,即可控制LED灯,这样调试是不是很方便。
4 、代码
代码下载