【N32G401开发板】一文搞懂基础N32 GPIO之LED和EXTI
错误&问题
工程路径问题
在国民技术的官网下载到了开发板的示例工程
下载链接:
ftp://download.nationstech.com/1-Microcontrollers/
然后找到GPIO示例:
【PS:
大概功能为点亮LED灯然后按照一定的规律进行流水】
然后想把该GPIO的示例工程拷贝一份出来运行看效果的,结果在进行烧录的时候报错:
startup_n32g401.s: error: A1023E: File "..\..\..\..\..\..\firmware\CMSIS\device\startup\startup_n32g401.s" could not be opened: No such file or directory
此时拷贝的GPIO示例工程路径如下:
问下豆包:
startup_n32g401.s: error: A1023E: File "..\..\..\..\..\..\firmware\CMSIS\device\startup\startup_n32g401.s" could not be opened: No such file or directory 是什么问题?
这个错误信息表明在编译过程中找不到指定的文件“startup_n32g401.s”。
可能的原因如下:
一、文件路径错误
检查文件实际所在位置与指定路径是否一致。确保路径中的每个目录层级都是正确的,并且没有拼写错误或遗漏的目录。
-如果路径是相对路径,确认当前工作目录是否正确设置,以便能够正确找到相对路径下的文件。
-如果路径是绝对路径,仔细检查绝对路径是否准确无误。
二、项目配置问题
1.检查项目的构建配置或编译选项中指定的文件搜索路径是否正确。
-某些开发环境可能需要在特定的项目设置中指定包含头文件和源文件的路径。确保这些路径设置正确,以便编译器能够找到所需的文件。
2.确认项目是否正确导入或链接了相关的库或模块。有时候,缺少特定的库或模块可能导致编译器无法找到依赖的文件。
三、文件丢失或损坏
1.检查指定的文件是否确实存在于指定的位置。如果文件丢失,可能需要从备份中恢复文件或者重新获取该文件。
2.如果文件存在但可能已损坏,可以尝试从可靠的来源获取一个新的副本。
解决这个问题的步骤通常包括:
1.仔细检查文件路径,确保路径正确指向包含 “startup_n32g401.s” 文件的目录。
2.检查项目配置,确保文件搜索路径和相关的库链接设置正确。
3.如果文件确实丢失或损坏,采取适当的措施恢复或获取新的文件副本。
然后我就老实了,回到给的示例文件夹中:
【PS:我的文件夹路径如下】
F:\0-Project\MCU_Nationstech_Project\0_N32G401xx_V1.0.0\6.Software Development Kit-软件开发工具包\Nations.N32G401_Library.1.0.0\projects\n32g401_EVAL\examples\GPIO\Led_Blink\MDK-ARM
其实也有解决方法,就是将涉及到的文件添加到项目中,或者多加一个项目文件查找路径即可。
(但是我懒的搞了,直接copy一个算了)
GPIO-LED程序理解
/**
* Copyright (c) 2022, Nations Technologies Inc.
*
* All rights reserved.
*
* This software is the exclusive property of Nations Technologies Inc. (Hereinafter
* referred to as NATIONS). This software, and the product of NATIONS described herein
* (Hereinafter referred to as the Product) are owned by NATIONS under the laws and treaties
* of the People’s Republic of China and other applicable jurisdictions worldwide.
*
* NATIONS does not grant any license under its patents, copyrights, trademarks, or other
* intellectual property rights. Names and brands of third party may be mentioned or referred
* thereto (if any) for identification purposes only.
*
* NATIONS reserves the right to make changes, corrections, enhancements, modifications, and
* improvements to this software at any time without notice. Please contact NATIONS and obtain
* the latest version of this software before placing orders.
* Although NATIONS has attempted to provide accurate and reliable information, NATIONS assumes
* no responsibility for the accuracy and reliability of this software.
*
* It is the responsibility of the user of this software to properly design, program, and test
* the functionality and safety of any application made of this information and any resulting product.
* In no event shall NATIONS be liable for any direct, indirect, incidental, special,exemplary, or
* consequential damages arising in any way out of the use of this software or the Product.
*
* NATIONS Products are neither intended nor warranted for usage in systems or equipment, any
* malfunction or failure of which may cause loss of human life, bodily injury or severe property
* damage. Such applications are deemed, “Insecure Usage”.
*
* All Insecure Usage shall be made at user’s risk. User shall indemnify NATIONS and hold NATIONS
* harmless from and against all claims, costs, damages, and other liabilities, arising from or related
* to any customer’s Insecure Usage.
* Any express or implied warranty with regard to this software or the Product, including,but not
* limited to, the warranties of merchantability, fitness for a particular purpose and non-infringement
* are disclaimed to the fullest extent permitted by law.
* Unless otherwise explicitly permitted by NATIONS, anyone may not duplicate, modify, transcribe
* or otherwise distribute this software for any purposes, in whole or in part.
*
* NATIONS products and technologies shall not be used for or incorporated into any products or systems
* whose manufacture, use, or sale is prohibited under any applicable domestic or foreign laws or regulations.
* User shall comply with any applicable export control laws and regulations promulgated and administered by
* the governments of any countries asserting jurisdiction over the parties or transactions.
**/
/**
*\*\file main.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
**/
#include "main.h"
#include "bsp_led.h"
#include "bsp_delay.h"
/**
*\*\name main.
*\*\fun main function.
*\*\param none.
*\*\return none.
**/
int main(void)
{
/* Initialize Led1~Led3 as output push-pull mode */
LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Turn off Led1~Led3 */
LED_Off(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Turn on Led2~Led3 */
LED_On(LED2_GPIO_PORT, LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
while(1)
{
/* Turn on Led1 */
LED1_ON;
/* Toggle LED2 */
LED_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Toggle LED3 */
LED_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Turn off LED1 */
LED1_OFF;
/* Delay 1s */
SysTick_Delay_Ms(1000);
}
}
上面这段代码是官方给的示例工程中的main.c文件中的所有数据。
发现注释很多,好评。注释翻译一下:
导入需要的库:
插播:LED初始化函数:
/* Initialize Led1~Led3 as output push-pull mode */
LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
主程序main函数:
int main(void)
{
/* Initialize Led1~Led3 as output push-pull mode */
LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Turn off Led1~Led3 */
LED_Off(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Turn on Led2~Led3 */
LED_On(LED2_GPIO_PORT, LED2_GPIO_PIN | LED3_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
while(1)
{
/* Turn on Led1 */
LED1_ON;
/* Toggle LED2 */
LED_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Toggle LED3 */
LED_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Turn off LED1 */
LED1_OFF;
/* Delay 1s */
SysTick_Delay_Ms(1000);
}
}
先进行初始化,然后调用延时函数,再进行死循环(电子人的第一课hh)
然后在while循环中尽显点亮LED灯,然后翻转LED灯的电平。然后延时1s。
其实while循环或者说点亮LED就4个主要的代码语句:
/* Turn on Led1 打开LED1*/
LED1_ON;
/* Toggle LED2 切换LED2*/
LED_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Turn off LED1 关闭LED1*/
LED1_OFF;
然后这个示例工程实现的效果大概如下:(0为全灭)
23 - 13 - 1 - 0 - 12 - 123 - 23 - 13 - 1 ...
可以看出规律。
现在给他修改一下代码,实现往左的流水灯。
未修改前的while循环代码:
while(1)
{
/* Turn on Led1 打开LED1*/
LED1_ON;
/* Toggle LED2 切换LED2*/
LED_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Toggle LED3 */
LED_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
/* Delay 1s */
SysTick_Delay_Ms(1000);
/* Turn off LED1 关闭LED1*/
LED1_OFF;
/* Delay 1s */
SysTick_Delay_Ms(1000);
}
修改后的while循环代码:
while(1)
{
LED1_OFF;
LED2_OFF;
LED3_OFF;
LED1_ON;
SysTick_Delay_Ms(1000);
LED1_OFF;
LED2_ON;
SysTick_Delay_Ms(1000);
LED2_OFF;
LED3_ON;
SysTick_Delay_Ms(1000);
}
这段代码首先关闭所有 LED,然后依次点亮 LED1、LED2、LED3,实现了往左的流水灯效果。每次点亮一个 LED 后,等待 1 秒再进行下一个操作。
EXTI-外部中断
官方给的示例工程功能:通过外部触发中断,控制 LED 闪烁
使用环境
软件开发环境:
IDE工具:KEIL MDK-ARM V5.34.0.0
IAR EWARM 8.50.1
/* 硬件环境:工程对应的开发硬件平台 */
开发板:N32G401C8L7-STB V1.0
使用说明
/* 描述相关模块配置方法;例如:时钟,I/O等 */
SystemClock:72MHz
GPIO:PA5 选择作为外部中断入口,PA7 控制 LED(PD3) 闪烁
/* 描述Demo的测试步骤和现象 */
1.编译后下载程序复位运行;
2.按下松开 KEY2 按键,LED 闪烁;
示例工程代码解析
头文件
/**
*\*\file main.c
*\*\author Nations
*\*\version v1.0.0
*\*\copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
**/
main
/**
*\*\name main.
*\*\fun Main program.
*\*\param none
*\*\return none
**/
int main(void)
{
/* SystemInit() function has been called by startup file startup_n32g401.s */
/* Initialize Led as output pushpull mode */
/* 将Led初始化为输出推拉模式 */
LedInit(LED1_PORT, LED1_PIN);
LedInit(LED2_PORT, LED2_PIN);
/*Initialize key as external line interrupt*/
/* 将密钥初始化为外部线路中断 */
KeyInputExtiInit(KEY_INPUT_PORT, KEY_INPUT_PIN);
/*Turn on Led1*/
/* 打开LED1*/
LedOn(LED1_PORT, LED1_PIN);
while (1)
{
}
}
EXTI初始化
m GPIOx :
*\*\ - GPIOA
*\*\ - GPIOB
*\*\ - GPIOC
*\*\ - GPIOD
*\*\param Pin :
*\*\ - GPIO_PIN_0
*\*\ - GPIO_PIN_1
*\*\ - GPIO_PIN_2
*\*\ - GPIO_PIN_3
*\*\ - GPIO_PIN_4
*\*\ - GPIO_PIN_5
*\*\ - GPIO_PIN_6
*\*\ - GPIO_PIN_7
*\*\ - GPIO_PIN_8
*\*\ - GPIO_PIN_9
*\*\ - GPIO_PIN_10
*\*\ - GPIO_PIN_11
*\*\ - GPIO_PIN_12
*\*\ - GPIO_PIN_13
*\*\ - GPIO_PIN_14
*\*\ - GPIO_PIN_15
*\*\return none
**/
void KeyInputExtiInit(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_InitType GPIO_InitStructure;
EXTI_InitType EXTI_InitStructure;
NVIC_InitType NVIC_InitStructure;
/* Enable the GPIO Clock */
if (GPIOx == GPIOA)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOB)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOC)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else if (GPIOx == GPIOD)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
}
else
{
return;
}
if (Pin <= GPIO_PIN_ALL)
{
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(GPIOx, &GPIO_InitStructure);
}
/* Configure key EXTI Line to key input Pin */
GPIO_EXTI_Line_Set(KEY_INPUT_PORT_SOURCE, KEY_INPUT_PIN_SOURCE);
/* Configure key EXTI line */
EXTI_InitStructure.EXTI_Line = KEY_INPUT_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Peripheral_Initializes(&EXTI_InitStructure);
/* Set key input interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = KEY_INPUT_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIORITY_1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
}
延时
/**
*\*\name Delay.
*\*\fun Main program.
*\*\param count
*\*\return none
**/
void Delay(uint32_t count)
{
for (; count > 0; count--)
;
}
LED相关功能函数
下面是给的LED开、关函数(有一说一写的真的好,真的适合新手hhhh,更适合有点基础的人一看函数名就知道功能是什么。)// 传入指定的GPIO口,和PIN号,进行相关的GPIO操作
void LedOn(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_Pins_Set(GPIOx, Pin);
}
void LedOff(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_PBC_Pins_Reset(GPIOx, Pin);
}
// LED闪烁函数(翻转指定的LED GPIO电平)
// 即使用Toggle后1变0,0变1。
void LedBlink(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_Pin_Toggle(GPIOx, Pin);
}
// Define LED Init Function
void LedInit(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_InitType GPIO_InitStructure;
/* Enable the GPIO Clock */
if (GPIOx == GPIOA)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
}
else if (GPIOx == GPIOB)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
}
else if (GPIOx == GPIOC)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
}
else if (GPIOx == GPIOD)
{
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
}
else
{
return;
}
/* Configure the GPIO pin as output push-pull */
if (Pin <= GPIO_PIN_ALL)
{
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_Peripheral_Initialize(GPIOx, &GPIO_InitStructure);
}
}
// 调用LED初始化函数(在main函数中)
//Call the LED initialization function (in the main function)
/* Initialize Led as output pushpull mode */
LedInit(LED1_PORT, LED1_PIN);
LedInit(LED2_PORT, LED2_PIN);
/**
*\*\name LedOn.
*\*\fun Turns selected Led on.
*\*\param GPIOx :
*\*\ - GPIOA
*\*\ - GPIOB
*\*\ - GPIOC
*\*\ - GPIOD
*\*\param Pin :
*\*\ - GPIO_PIN_0
*\*\ - GPIO_PIN_1
*\*\ - GPIO_PIN_2
*\*\ - GPIO_PIN_3
*\*\ - GPIO_PIN_4
*\*\ - GPIO_PIN_5
*\*\ - GPIO_PIN_6
*\*\ - GPIO_PIN_7
*\*\ - GPIO_PIN_8
*\*\ - GPIO_PIN_9
*\*\ - GPIO_PIN_10
*\*\ - GPIO_PIN_11
*\*\ - GPIO_PIN_12
*\*\ - GPIO_PIN_13
*\*\ - GPIO_PIN_14
*\*\ - GPIO_PIN_15
*\*\return none
**/
void LedOn(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_Pins_Set(GPIOx, Pin);
}
/**
*\*\name LedOff.
*\*\fun Turns selected Led off.
*\*\param GPIOx :
*\*\ - GPIOA
*\*\ - GPIOB
*\*\ - GPIOC
*\*\ - GPIOD
*\*\param Pin :
*\*\ - GPIO_PIN_0
*\*\ - GPIO_PIN_1
*\*\ - GPIO_PIN_2
*\*\ - GPIO_PIN_3
*\*\ - GPIO_PIN_4
*\*\ - GPIO_PIN_5
*\*\ - GPIO_PIN_6
*\*\ - GPIO_PIN_7
*\*\ - GPIO_PIN_8
*\*\ - GPIO_PIN_9
*\*\ - GPIO_PIN_10
*\*\ - GPIO_PIN_11
*\*\ - GPIO_PIN_12
*\*\ - GPIO_PIN_13
*\*\ - GPIO_PIN_14
*\*\ - GPIO_PIN_15
*\*\return none
**/
void LedOff(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_PBC_Pins_Reset(GPIOx, Pin);
}
/**
*\*\name LedBlink.
*\*\fun Toggles the selected Led.
*\*\param GPIOx :
*\*\ - GPIOA
*\*\ - GPIOB
*\*\ - GPIOC
*\*\ - GPIOD
*\*\param Pin :
*\*\ - GPIO_PIN_0
*\*\ - GPIO_PIN_1
*\*\ - GPIO_PIN_2
*\*\ - GPIO_PIN_3
*\*\ - GPIO_PIN_4
*\*\ - GPIO_PIN_5
*\*\ - GPIO_PIN_6
*\*\ - GPIO_PIN_7
*\*\ - GPIO_PIN_8
*\*\ - GPIO_PIN_9
*\*\ - GPIO_PIN_10
*\*\ - GPIO_PIN_11
*\*\ - GPIO_PIN_12
*\*\ - GPIO_PIN_13
*\*\ - GPIO_PIN_14
*\*\ - GPIO_PIN_15
*\*\return none
**/
void LedBlink(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_Pin_Toggle(GPIOx, Pin);
}
作者:youyeye,来源:面包板社区
电路图集
常用模拟电路 | 运放电路 | 保护电路 | EMC标准电路 | 电源电路大全 | 实用控制电路 | 单片机应用电路 | 波形发生电路 | 汽车电路图大全 | 555电路 | 小家电电路 | 9大基本模块电路 | 原理图英文缩写 | 电路图符号
入门基础
电路基础 | 数字电路 | 示波器基础 | 万用表使用 | 信号完整性 | 地线知识 | 嵌入式基础 | STM32基础知识总结 | C语言知识点
元器件
电阻 | 电容 | 电感 | 二极管 | 三极管 | TVS | 晶闸管 | MOS管 |IGBT | 传感器 | 继电器 | 元器件等效电路| 元器件选型完全指南 | 元器件故障
加入社群
如果您想加入电子行业微信群,可以扫码添加我们社群运营。备注入群方向(简单描述目标群,如:嵌入式、市场行情等)