本帖最后由 平安一生 于 2024-10-21 15:12 编辑

1. 前言:


感谢平台给我这个评测的机会。
我非常珍惜这次评测和学习的机会。
这是第一次接触国民技术的产品,还需要时间不断的来学习。

也希望后续有机会学习和认识更多更好的产品。


2. 评测总结


1-这个板子自带下载器,这个必须点赞,对比别家的没有是下载器,在构建环境的时候,实在太麻烦了。

2-这个板子自带CH340,这个也必须点赞,因为这个在调试的时候,下载和输出信息只需要一根USB线,就这一点秒杀很多开发板啊。真正的做到了简单易用,虽然这个增加了硬件成本,但是真的是为入门选手节省了宝贵时间。

3-板子的每个IO都引出了,并且可以直接焊接双排针,这点太贴心了,真的让人喜欢啊。

4-预留了4路上拉和下拉4.7K电路,方便飞线使用,再也不用自己去焊接电阻了,非常方便测试

5-demo程序非常加单移动,非常方便拿来直接使用。各个功能模块都有很好的例程。

6-这是一款非常贴心的开发板,诚意满满,非常适合入门学习各个功能模块。


3. 认识国民技术开发板


N32G401系列采用32-bit Arm® Cortex®-M4F内核,最高工作主频72MHz,支持浮点运算和DSP指令,集成高达64KB嵌入式加密Flash,8KB SRAM,集成丰富的高性能模拟器件,内置1个12bit 4.2Msps ADC,3个高速比较器,集成4个U(S)ART、2个I2C、2个SPI等数字通信接口。有14个子型号可供选择,可广泛应用于电控、照明、扫地机、无线充、智能门锁、车身电子、无线麦克风、报警装置等领域。

(1)高性能,低功耗:芯片采用Arm® Cortex®-M4F内核,运行主频72MHz,内置1KB指令缓存,CoreMark跑分达235.8,浮点运算能力达90DMIPS;动态运行功耗90uA/MHz,STOP2功耗10uA (25℃最大值)。

(2)高可靠性:工作环境温度-40~105℃,具有双时钟安全监测系统,I/O支持电压钳位,抗静电ESD:±4kV(HBM模型),符合IEC60730标准。

(3)高精度:内置8MHz +/-1%精度RC振荡器,以及12bit 4.2Msps高速高精度ADC。

(4)小尺寸:支持TSSOP/LQFP/QFN等多种封装形式,提供20/28/32/48等管脚封装,最小尺寸3mm*3mm (QFN20封装)。



1.png


4. 环境搭建

本人采用Keil5.38作为开发版本。

下载时候需要注意作如下选择下载器:

2.png

3.png
5. 验证目标

1-实现浮点计算;

2-实现GPIO控制,LED控制亮灭;

3-实现串口通信;

4-实现GPIO中断,在中断函数处理事务:LED控制+串口输出

6. 程序开发


6.1. 串口实现printf



#include "log.h"

#if LOG_ENABLE

#include "n32g401.h"

#define LOG_USARTx      USART1

#define LOG_PERIPH      RCC_APB2_PERIPH_USART1

#define LOG_GPIO        GPIOA

#define LOG_PERIPH_GPIO RCC_AHB_PERIPH_GPIOA

#define LOG_TX_PIN      GPIO_PIN_9

#define LOG_RX_PIN      GPIO_PIN_10

void log_init(void)

{

    GPIO_InitType GPIO_InitStructure;

    USART_InitType USART_InitStructure;


    RCC_AHB_Peripheral_Clock_Enable(LOG_PERIPH_GPIO);

    RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO | LOG_PERIPH);


    GPIO_Structure_Initialize(&GPIO_InitStructure);

    GPIO_InitStructure.Pin            = LOG_TX_PIN;

    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;

    GPIO_InitStructure.GPIO_Alternate = GPIO_AF5_USART1;

    GPIO_Peripheral_Initialize(LOG_GPIO, &GPIO_InitStructure);


    GPIO_InitStructure.Pin             = LOG_RX_PIN;

    GPIO_InitStructure.GPIO_Alternate  = GPIO_AF5_USART1;

    GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


    USART_InitStructure.BaudRate            = 115200;

    USART_InitStructure.WordLength          = USART_WL_8B;

    USART_InitStructure.StopBits            = USART_STPB_1;

    USART_InitStructure.Parity              = USART_PE_NO;

    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;

    USART_InitStructure.Mode                = USART_MODE_TX;


    /* init uart */

    USART_Initializes(LOG_USARTx, &USART_InitStructure);


    /* enable uart */

    USART_Enable(LOG_USARTx);

}


static int is_lr_sent = 0;


int fputc(int ch, FILE* f)

{

    if (ch == '\r')

    {

        is_lr_sent = 1;

    }

    else if (ch == '\n')

    {

        if (!is_lr_sent)

        {

            USART_Data_Send(LOG_USARTx, (uint8_t)'\r');

            /* Loop until the end of transmission */

            while (USART_Flag_Status_Get(LOG_USARTx, USART_FLAG_TXC) == RESET)

            {       }

        }

        is_lr_sent = 0;

    }

    else

    {

        is_lr_sent = 0;

    }

    USART_Data_Send(LOG_USARTx, (uint8_t)ch);

    /* Loop until the end of transmission */

    while (USART_Flag_Status_Get(LOG_USARTx, USART_FLAG_TXDE) == RESET)

    {   }

    return ch;

}

6.2. 按键中断实现



#define KEY1_INPUT_PORT        GPIOA

#define KEY1_INPUT_PIN         GPIO_PIN_4

#define KEY1_INPUT_EXTI_LINE   EXTI_LINE4

#define KEY1_INPUT_PORT_SOURCE EXTI_LINE_SOURCE4

#define KEY1_INPUT_PIN_SOURCE  AFIO_EXTI_PA4

#define KEY1_INPUT_IRQn        EXTI4_IRQn


#define KEY2_INPUT_PORT        GPIOA

#define KEY2_INPUT_PIN         GPIO_PIN_5

#define KEY2_INPUT_EXTI_LINE   EXTI_LINE5

#define KEY2_INPUT_PORT_SOURCE EXTI_LINE_SOURCE5

#define KEY2_INPUT_PIN_SOURCE  AFIO_EXTI_PA5

#define KEY2_INPUT_IRQn        EXTI9_5_IRQn


#define KEY3_INPUT_PORT        GPIOA

#define KEY3_INPUT_PIN         GPIO_PIN_6

#define KEY3_INPUT_EXTI_LINE   EXTI_LINE6

#define KEY3_INPUT_PORT_SOURCE EXTI_LINE_SOURCE6

#define KEY3_INPUT_PIN_SOURCE  AFIO_EXTI_PA6

#define KEY3_INPUT_IRQn        EXTI9_5_IRQn



#include "bsp_KEY.h"


void Key1InputExtiInit(void)

{

    GPIO_InitType GPIO_InitStructure;

    EXTI_InitType EXTI_InitStructure;

    NVIC_InitType NVIC_InitStructure;

    /* Enable the GPIO Clock */

    if (KEY1_INPUT_PORT == GPIOA)

    {

        CC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY1_INPUT_PORT == GPIOB)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY1_INPUT_PORT == GPIOC)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY1_INPUT_PORT == GPIOD)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else

    {

        return;

    }


    if (KEY1_INPUT_PIN <= GPIO_PIN_ALL)

    {

        GPIO_Structure_Initialize(&GPIO_InitStructure);

        GPIO_InitStructure.Pin          = KEY1_INPUT_PIN;

        GPIO_InitStructure.GPIO_Pull    = GPIO_PULL_UP;

        GPIO_Peripheral_Initialize(KEY1_INPUT_PORT, &GPIO_InitStructure);

    }


    /* Configure key EXTI Line to key input Pin */

    GPIO_EXTI_Line_Set(KEY1_INPUT_PORT_SOURCE, KEY1_INPUT_PIN_SOURCE);


    /* Configure key EXTI line */

    EXTI_InitStructure.EXTI_Line    = KEY1_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                   = KEY1_INPUT_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = NVIC_SUB_PRIORITY_1;

    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Initializes(&NVIC_InitStructure);

}



void Key2InputExtiInit(void)

{

    GPIO_InitType GPIO_InitStructure;

    EXTI_InitType EXTI_InitStructure;

    NVIC_InitType NVIC_InitStructure;




    /* Enable the GPIO Clock */

    if (KEY2_INPUT_PORT == GPIOA)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY2_INPUT_PORT == GPIOB)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY2_INPUT_PORT == GPIOC)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY2_INPUT_PORT == GPIOD)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else

    {

        return;

    }


    if (KEY2_INPUT_PIN <= GPIO_PIN_ALL)

    {

        GPIO_Structure_Initialize(&GPIO_InitStructure);

        GPIO_InitStructure.Pin          = KEY2_INPUT_PIN;

        GPIO_InitStructure.GPIO_Pull    = GPIO_PULL_UP;

        GPIO_Peripheral_Initialize(KEY2_INPUT_PORT, &GPIO_InitStructure);

    }


    /* Configure key EXTI Line to key input Pin */

    GPIO_EXTI_Line_Set(KEY2_INPUT_PORT_SOURCE, KEY2_INPUT_PIN_SOURCE);


    /* Configure key EXTI line */

    EXTI_InitStructure.EXTI_Line    = KEY2_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                   = KEY2_INPUT_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = NVIC_SUB_PRIORITY_1;

    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Initializes(&NVIC_InitStructure);

}




void Key3InputExtiInit(void)

{

    GPIO_InitType GPIO_InitStructure;

    EXTI_InitType EXTI_InitStructure;

    NVIC_InitType NVIC_InitStructure;




    /* Enable the GPIO Clock */

    if (KEY3_INPUT_PORT == GPIOA)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY3_INPUT_PORT == GPIOB)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY3_INPUT_PORT == GPIOC)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else if (KEY3_INPUT_PORT == GPIOD)

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);

        RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    }

    else

    {

        return;

    }


    if (KEY3_INPUT_PIN <= GPIO_PIN_ALL)

    {

        GPIO_Structure_Initialize(&GPIO_InitStructure);

        GPIO_InitStructure.Pin          = KEY3_INPUT_PIN;

        GPIO_InitStructure.GPIO_Pull    = GPIO_PULL_UP;

        GPIO_Peripheral_Initialize(KEY3_INPUT_PORT, &GPIO_InitStructure);

    }


    /* Configure key EXTI Line to key input Pin */

    GPIO_EXTI_Line_Set(KEY3_INPUT_PORT_SOURCE, KEY3_INPUT_PIN_SOURCE);


    /* Configure key EXTI line */

    EXTI_InitStructure.EXTI_Line    = KEY3_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                   = KEY3_INPUT_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = NVIC_SUB_PRIORITY_1;

    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Initializes(&NVIC_InitStructure);

}


void EXTI9_5_IRQHandler(void)

{

    if (RESET != EXTI_Interrupt_Status_Get(KEY2_INPUT_EXTI_LINE))

    {

        LED2_ON;

printf("\nkey2");

        EXTI_Interrupt_Status_Clear(KEY2_INPUT_EXTI_LINE);

    }

    if (RESET != EXTI_Interrupt_Status_Get(KEY3_INPUT_EXTI_LINE))

    {

LED1_OFF;LED2_OFF;

        printf("\nkey3");

        EXTI_Interrupt_Status_Clear(KEY3_INPUT_EXTI_LINE);

    }

}



void EXTI4_IRQHandler(void)

{

    if (RESET != EXTI_Interrupt_Status_Get(KEY1_INPUT_EXTI_LINE))

    {

        LED1_ON;

printf("\nkey1");

        EXTI_Interrupt_Status_Clear(KEY1_INPUT_EXTI_LINE);

    }

}


6.3. LED初始化及定义


/** Define the GPIO port to which the LED is connected **/

#define LED1_GPIO_PORT      GPIOA                       /* GPIO port */

#define LED1_GPIO_CLK       RCC_AHB_PERIPH_GPIOA        /* GPIO port clock */

#define LED1_GPIO_PIN       GPIO_PIN_1                  /* GPIO connected to the SCL clock line */


#define LED2_GPIO_PORT      GPIOA                       /* GPIO port */

#define LED2_GPIO_CLK       RCC_AHB_PERIPH_GPIOA        /* GPIO port clock */

#define LED2_GPIO_PIN       GPIO_PIN_7                  /* GPIO connected to the SCL clock line */


#define LED3_GPIO_PORT      GPIOA                       /* GPIO port */

#define LED3_GPIO_CLK       RCC_AHB_PERIPH_GPIOA        /* GPIO port clock */

#define LED3_GPIO_PIN       GPIO_PIN_9                  /* GPIO connected to the SCL clock line */



/** Define macros that control IO **/

#define LED1_TOGGLE         {LED1_GPIO_PORT->POD ^= LED1_GPIO_PIN;}

#define LED1_ON             {LED1_GPIO_PORT->PBSC = LED1_GPIO_PIN;}

#define LED1_OFF            {LED1_GPIO_PORT->PBC = LED1_GPIO_PIN;}


#define LED2_TOGGLE         {LED2_GPIO_PORT->POD ^= LED2_GPIO_PIN;}

#define LED2_ON             {LED2_GPIO_PORT->PBSC = LED2_GPIO_PIN;}

#define LED2_OFF            {LED2_GPIO_PORT->PBC = LED2_GPIO_PIN;}


#define LED3_TOGGLE         {LED3_GPIO_PORT->POD ^= LED3_GPIO_PIN;}

#define LED3_ON             {LED3_GPIO_PORT->PBSC = LED3_GPIO_PIN;}

#define LED3_OFF            {LED3_GPIO_PORT->PBC = LED3_GPIO_PIN;}


#include "bsp_led.h"

void LED_Initialize(GPIO_Module* GPIOx, uint16_t pin)

{

    /* Define a structure of type GPIO_InitType */

    GPIO_InitType GPIO_InitStructure;


    /* Enable LED related GPIO peripheral 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_GPIOC);

    }

    else

    {

        RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);

    }


    if(pin < GPIO_PIN_ALL)

    {

        /* Assign default value to GPIO_InitStructure structure */

        GPIO_Structure_Initialize(&GPIO_InitStructure);


        /* Select the GPIO pin to control */

        GPIO_InitStructure.Pin          = pin;

        /* Set pin mode to general push-pull output */

        GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;

        /* Set the pin drive current to 4MA*/

        GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;

        /* Initialize GPIO */

        GPIO_Peripheral_Initialize(GPIOx, &GPIO_InitStructure);

    }

}


void LED_Toggle(GPIO_Module* GPIOx, uint16_t pin)

{

    GPIO_Pin_Toggle(GPIOx, pin);;

}


void LED_On(GPIO_Module* GPIOx,uint16_t pin)

{

    GPIO_Pins_Set(GPIOx, pin);

}


void LED_Off(GPIO_Module* GPIOx,uint16_t pin)

{

    GPIO_Pins_Reset(GPIOx, pin);

}



6.4. 延时函数实现

ms和us延时实现

#include "bsp_delay.h"


/**

*\*\name    DBG_SysTick_Config.

*\*\fun     System tick configuration.

*\*\param   ticks :system tick

*\*\return  none

**/

static uint32_t DBG_SysTick_Config(uint32_t ticks)

{

    if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */


    SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */

    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */

    SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */

    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |

                     SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */

    SysTick->CTRL  &= ~SysTick_CTRL_TICKINT_Msk;

    return (0);                                                  /* Function successful */

}


/**

*\*\name    SysTick_Delay_Us.

*\*\fun     microsecond delay.

*\*\param   us :any number

*\*\return  none

**/

void SysTick_Delay_Us( __IO uint32_t us)

{

    uint32_t i;

    RCC_ClocksType RCC_Clocks;


    RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);

    DBG_SysTick_Config(RCC_Clocks.SysclkFreq / 1000000);


    for(i=0;i<us;i++)

    {

        /* When the counter value decreases to 0, bit 16 of the CRTL register will be set to 1 */

        /* When set to 1, reading this bit will clear it to 0 */

        while( !((SysTick->CTRL)&(1<<16)) );

    }

    /* Turn off the SysTick timer */

    SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;

    }


/**

*\*\name    SysTick_Delay_Us.

*\*\fun     millisecond delay.

*\*\param   ms :any number

*\*\return  none

**/

void SysTick_Delay_Ms( __IO uint32_t ms)

{

    uint32_t i;

    RCC_ClocksType RCC_Clocks;


    RCC_Clocks_Frequencies_Value_Get(&RCC_Clocks);

    DBG_SysTick_Config(RCC_Clocks.SysclkFreq / 1000);


    for(i=0;i<ms;i++)

    {

        /* When the counter value decreases to 0, bit 16 of the CRTL register will be set to 1 */

        /* When set to 1, reading this bit will clear it to 0 */

        while( !((SysTick->CTRL)&(1<<16)) );

    }

    /* Turn off the SysTick timer */

    SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;

}


6.5. 主程序


系统初始化,初始化各个模块。

实现浮点运算,并通过串口输出到上位机

int main(void)

{

double y=0.0;

/* Initialize Led1~Led3 as output push-pull mode */

    LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN );

    /* Turn on Led2~Led3 */

    LED_On(LED2_GPIO_PORT, LED1_GPIO_PIN |LED2_GPIO_PIN);

    /* Delay 1s */

    SysTick_Delay_Ms(1000);

    /* Turn off Led1~Led3 */

    LED_Off(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN);

Key1InputExtiInit();

Key2InputExtiInit();

Key3InputExtiInit();

    log_init();

    /* Output a message on Hyperterminal using printf function */

    printf("\nUSART Printf Example: retarget the C library printf function to the USART");

    while (1)

    {

SysTick_Delay_Ms(1000);

y=0.11+y;

printf("\ny =%f",y);

    }

}


7. 效果验证

7.1. 串口输出

4.png
7.2. 按键中断

5.png
7.3. LED控制

按键控制KED的亮灭

6.png
实验验证视频详见:

演示视频
https://u.eet-china.com/video/3574