瑞萨单片机论坛
直播中

VOR

8年用户 25经验值
擅长:可编程逻辑 嵌入式技术 模拟技术 EDA/IC设计 控制/MCU RF/无线
私信 关注
[经验]

【RA4M2系列开发板GPIO体验2按键控制LED】

1. 前言

终于准备开发瑞萨的板子了,开始按照教程一步一步的搭建环境,还是非常不容易的。
本次开发使用的是瑞萨官方的编译器RASC+Keil。
本文实现的功能:

  • 从头创建一个新工程;
  • 配置LED以及按键端口;
  • 使用Renesas Flash Programmer下载程序;
  • 实现流水灯以及按键SW1按下停止流水灯,按键SW2按下开启流水灯的功能。

2. 配置工程

打开RASC,可直接跳过登录账号,也可登录在瑞萨官网注册的账号即可,然后按照下面的步骤新建工程即可。

2.1 新建FSP项目

输入项目名称LED_switch
在这里插入图片描述
选择目标单片机
所使用的单片机为R7FA4M2AD3DFP,如果有调试器,可以选择相应的调试器,否则可以选择None,当然后期可以修改。
在这里插入图片描述
在这里插入图片描述

选择工程类型
这里直接选择Flat Project就行,如果需要体验TrustZone,,可根据实际情况选择。
在这里插入图片描述

选择编译方式
这里选择第一个即可。
在这里插入图片描述
选择是否使用FreeRTOS
我这里选择了使用,方便后期开发,但是只能选择使用静态分配的任务。
然后点击完成。
在这里插入图片描述

到这里工程就算新建完成,但是什么都没有,需要我们通过FSP添加想要的组件,完成功能开发。

2.2 硬件连接以及FSP配置

2.2.1 硬件连接

我们需要用到LED以及按键,先查看原理图
LED原理图如下,由此可知,P405,P404,P002分别控制LED1,LED2,LED3,并且当控制引脚为HIGH的时候LED亮。
在这里插入图片描述

按键原理图如下,由此可知,P005连接到了SW01,P006连接到了SW2,且当引脚为LOW时表示按键按下。
在这里插入图片描述

2.2.2 FSP配置

知道了硬件连接,接下来就是使用FSP配置响应的硬件功能了。

在这里插入图片描述

配置按键P005,P006为输入模式。

选择FSP Configuration下面的Pins,配置引脚P405,P404,P002,配置为输出低[Output mode(Initial Low)]。

在这里插入图片描述
在这里插入图片描述

点击Generate Project Content生成配置代码。
在这里插入图片描述

选择Summary,进入项目文件夹
在这里插入图片描述

3. 软件实现

3.1 实现的功能

  • 系统上电,LED1,LED2,LED3按照亮灭,亮灭,亮灭的状态流水灯显示,流水灯切换周期为500ms;
  • 按下按键SW1,流水灯停止;
  • 按下按键SW2,流水灯继续;

3.2 FreeRTOS使用

创建工程的时候选择了使用FreeRTOS,RASC会默认配置一个最小配置项的freeRTOS环境,只支持基本的功能,很多扩展功能都不支持,只支持静态创建任务,我还没找到在哪里可以配置,因为直接修改配置文件不行,RASC再次生成的时候会覆盖。

虽然freeRTOS只支持静态配置以及一些基础功能,但是也够我们使用了,下面开始实现我的逻辑。

3.2.1 Stack分配函数

实现Idle任务的Stack分配函数,因为是静态分配栈,所以该部分功能需要我们自己实现,FreeRTOS提供了接口。

/* Implement the Idle task memory static alocation */
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
                                   StackType_t ** ppxIdleTaskStackBuffer,
                                   uint32_t * pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer = &xIdleTaskTcb;
    *ppxIdleTaskStackBuffer = xIdleTaskStack;
    *pulIdleTaskStackSize = 1024;
}

实现Timer任务的Stack分配函数
因为是静态分配栈,所以该部分功能需要我们自己实现,FreeRTOS提供了接口。

/* Implement the Timer task memory static alocation */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer = &xTimerTaskTcb;
	*ppxTimerTaskStackBuffer = xTiemrTaskStack;
	*pulTimerTaskStackSize = 2048;
}

3.2.2 LED任务

LED任务实现流水灯功能,每200ms切换一次。
任务创建:

/* Create static task */
    Task_Led_Handle = xTaskCreateStatic(Task_LedRunning,
                        "Led",          /* Task name */
                        1024,              /* Stack */
                        NULL,              /* Task parameter */
                        4,                 /* Priority */
                        xTaskLedStack,
                        &xTaskLedTcb);            /* Task handler */

LED任务实现:

static void Task_LedRunning(void *pvParameters)
{
    (void)pvParameters;
	
    for (;;)
    {
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));

        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_HIGH);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));

        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_HIGH);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));
    }
}

3.2.3 Key任务

按键实现了对按键SW1与SW2的采集,滤波等功能,任务周期为10ms,滤波时间为40ms。
当SW1按下,暂停LED任务;
当SW2按下,恢复LED任务。
任务创建:

Task_Key_Handle = xTaskCreateStatic(Task_KeyRunning,
						"Key",          /* Task name */
						1024,              /* Stack */
						NULL,              /* Task parameter */
						3,                 /* Priority */
						xTaskKeyStack,
						&xTaskKeyTcb);            /* Task handler */

任务实现:

static void Task_KeyRunning(void *pvParameters)
{
    (void)pvParameters;
	bsp_io_level_t key_Status[2] = {BSP_IO_LEVEL_HIGH, BSP_IO_LEVEL_HIGH};
	uint16_t key_press_cnt[2] = {0U, 0U};
	
	for (;;)
	{
        if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05, &key_Status[0]))
        {
            if (key_Status[0] == BSP_IO_LEVEL_LOW)
            {
				/* Filter */
				if (key_press_cnt[0] >= 0U)
				{
					/* Key SW0 press confirm */
					/* Suspend led task */
					vTaskSuspend(Task_Led_Handle);
				}
				else
				{
					key_press_cnt[0] ++;
				}
            }
			else
			{
				key_press_cnt[0] = 0U;
			}
        }
		
		if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, &key_Status[1]))
        {
            if (key_Status[1] == BSP_IO_LEVEL_LOW)
            {
				/* Filter */
				if (key_press_cnt[1] >= 4U)
				{
					/* Key SW1 press confirm */
					/* Resume led task */
					vTaskResume(Task_Led_Handle);
				}
				else
				{
					key_press_cnt[1] ++;
				}
            }
			else
			{
				key_press_cnt[1] = 0U;
			}
        }

		vTaskDelay(pdMS_TO_TICKS(10));		
	}
}

3.3 程序设计

hal_entry.c完整代码

#include "hal_data.h"
#include "FreeRTOS.h"
#include "task.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


/* Stack for Idle task */
static StackType_t xIdleTaskStack[512];
static StaticTask_t xIdleTaskTcb;
/* Stack for Timer task */
static StackType_t xTiemrTaskStack[512];
static StaticTask_t xTimerTaskTcb;

/* Staack for LED task */
static StackType_t xTaskLedStack[1024];
static StaticTask_t xTaskLedTcb;
static TaskHandle_t Task_Led_Handle = NULL;

/* Staack for LED task */
static StackType_t xTaskKeyStack[1024];
static StaticTask_t xTaskKeyTcb;
static TaskHandle_t Task_Key_Handle = NULL;

extern void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
                                          StackType_t ** ppxIdleTaskStackBuffer,
                                          uint32_t * pulIdleTaskStackSize);
extern void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                          StackType_t **ppxTimerTaskStackBuffer,
                                          uint32_t *pulTimerTaskStackSize);

static void Task_LedRunning(void *pvParameters);
static void Task_KeyRunning(void *pvParameters);

static void Task_LedRunning(void *pvParameters)
{
    (void)pvParameters;
	
    for (;;)
    {
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_02, BSP_IO_LEVEL_LOW);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));

        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_HIGH);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_02, BSP_IO_LEVEL_LOW);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));

        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_05, BSP_IO_LEVEL_LOW);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_02, BSP_IO_LEVEL_HIGH);

        /* Delay for 200ms */
        vTaskDelay(pdMS_TO_TICKS(200));
    }
}

static void Task_KeyRunning(void *pvParameters)
{
    (void)pvParameters;
	bsp_io_level_t key_Status[2] = {BSP_IO_LEVEL_HIGH, BSP_IO_LEVEL_HIGH};
	uint16_t key_press_cnt[2] = {0U, 0U};
	
	for (;;)
	{
        if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05, &key_Status[0]))
        {
            if (key_Status[0] == BSP_IO_LEVEL_LOW)
            {
				/* Filter */
				if (key_press_cnt[0] >= 0U)
				{
					/* Key SW0 press confirm */
					/* Suspend led task */
					vTaskSuspend(Task_Led_Handle);
				}
				else
				{
					key_press_cnt[0] ++;
				}
            }
			else
			{
				key_press_cnt[0] = 0U;
			}
        }
		
		if (FSP_SUCCESS == R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06, &key_Status[1]))
        {
            if (key_Status[1] == BSP_IO_LEVEL_LOW)
            {
				/* Filter */
				if (key_press_cnt[1] >= 4U)
				{
					/* Key SW1 press confirm */
					/* Resume led task */
					vTaskResume(Task_Led_Handle);
				}
				else
				{
					key_press_cnt[1] ++;
				}
            }
			else
			{
				key_press_cnt[1] = 0U;
			}
        }

		vTaskDelay(pdMS_TO_TICKS(10));		
	}
}

/* Implement the Idle task memory static alocation */
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
                                   StackType_t ** ppxIdleTaskStackBuffer,
                                   uint32_t * pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer = &xIdleTaskTcb;
    *ppxIdleTaskStackBuffer = xIdleTaskStack;
    *pulIdleTaskStackSize = 1024;
}

/* Implement the Timer task memory static alocation */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize)
{
	*ppxTimerTaskTCBBuffer = &xTimerTaskTcb;
	*ppxTimerTaskStackBuffer = xTiemrTaskStack;
	*pulTimerTaskStackSize = 2048;
}

/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
	/* Create static task */
    Task_Led_Handle = xTaskCreateStatic(Task_LedRunning,
                        "Led",          /* Task name */
                        1024,              /* Stack */
                        NULL,              /* Task parameter */
                        4,                 /* Priority */
                        xTaskLedStack,
                        &xTaskLedTcb);            /* Task handler */
	
	Task_Key_Handle = xTaskCreateStatic(Task_KeyRunning,
						"Key",          /* Task name */
						1024,              /* Stack */
						NULL,              /* Task parameter */
						3,                 /* Priority */
						xTaskKeyStack,
						&xTaskKeyTcb);            /* Task handler */

    if (NULL != Task_Led_Handle)
	{
	    vTaskStartScheduler();
	}

	while (1) {}

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

#if BSP_TZ_SECURE_BUILD

BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
#endif

3.3.1 设置输出hex文件

在这里插入图片描述

3.3.2 编译

在这里插入图片描述

3.3.3 下载hex文件

打开Renesas Flash Programmer,点击File->New Project,做如下配置。
主要是配置微控制器类型,工程名字,工程目录以及串口端口。
在这里插入图片描述

配置完成之后点击Connect,此时会连接失败,如下图
在这里插入图片描述

需要按住Reset按钮,之后点击Connect,在松手。

配置Boot
如果使用串口下载,需要配置一下单片机上面的boot跳线帽,切换为SCI/USB BOOT模式如下:
在这里插入图片描述

开发板上也有描述,下载完成之后需要将跳线帽变回Interrnal Flash模式。

下载hex文件到单片机
如下图,选择hex文件,然后按下Reset按钮,电机Start,松开Reset按钮,等待下载完成即可。
在这里插入图片描述

4. 效果展示

  • 系统上电,LED1,LED2,LED3按照亮灭,亮灭,亮灭的状态流水灯显示,流水灯切换周期为500ms;
  • 按下按键SW1,流水灯停止;
  • 按下按键SW2,流水灯继续。

5. 总结

更多回帖

×
20
完善资料,
赚取积分