Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试

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转串口的模块。
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第1张图片
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第2张图片
由于要用letter shell,所以要配置串口为tx rx模式,发送数据我们用普通轮询模式,接收数据用中断模式,中断函数每次接收到一个数据调用一次,我们在中断函数里调用 shellHandler(&shell, received_char)去处理数据即可。

a、串口时钟初始化

所有时钟的初始化,都放在了clock_init.c中的
void BOARD_ClockInit函数中
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第3张图片

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、中断处理函数

Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第4张图片

d、printf重定向

Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第5张图片
后面完善letter shell写函数的时候,跟这个类似,直接复制过去就行。

2、letter shell的移植

下载传送门
下载后,将src中所有的文件拷贝到我们的工程中,并新建shell_port.c shell_port.h文件,目录结构如图:
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第6张图片
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的初始化函数
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第7张图片
如果此时编译报错,修改ld文件如下:
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第8张图片

这样开机后,接到letter shell交互界面了。
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第9张图片

3、Letter Shell的使用

我们添加一个命令,来控制LED灯,输入LED On灯亮,输入LED Off灯灭,
输入LED Blink 100,灯开始间隔100ms开始闪烁。
首先在shell_cfg.h使能支持外部命令的宏。
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第10张图片
添加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灯,这样调试是不是很方便。
Nucleo-F411RE (STM32F411)LL库体验 4 -Letter Shell移植与调试_第11张图片

4 、代码

代码下载

你可能感兴趣的:(Nucleo-F411RE,stm32,单片机,嵌入式硬件)