3153 views|3 replies

205

Posts

0

Resources
The OP
 

[National Technology Low Power Series N32L43x Review] 02. Create a template project [Copy link]

 This post was last edited by xld0932 on 2022-6-26 12:14

This article will use the KEIL MDK integrated development environment to create a template project based on the N32L43XRL-STB development board step by step. Through schematic design, the basic functions of the onboard resources LED, KEY, and USART are implemented, and the commonly used Letter-shell is transplanted through USART. The process will be detailed below. There is a debugging problem record at the end of the article for reference.

Create a project

STEP1. Open KEIL MDK integrated development environment software

STEP2. Click on the menu bar Project->New uVision Project...

STEP3. Enter the project file name in the Create New Project window that pops up, select the path where the project file needs to be saved, and click the Save button

STEP4. In the Select Device from Target window that pops up, select the corresponding chip model on the development board: N32L436RB, and then click OK

STEP5. In the pop-up Manage Run-Time Environment window, no operation is required for the time being, just click OK

STEP6. At this point, we have created an empty KEIL project based on the N32L436RB chip. Next, we need to add project files and configure the project.

STEP7. Click the Manage Project Items button on the toolbar to add project files

STEP8. In the Project Items in the Manage Project Items window that pops up, we can modify the Project Targets name, add file groups in Groups, and add the source code in the corresponding group in Files. After the operation is completed, we click OK

STEP9. The added project group and file information are shown in the figure below

STEP10. Next, we continue to click the Options for Target button on the toolbar to configure the project.

STEP11. In the Target, select Use default compiler version5 for ARM Compiler in the Code Generation area and check Use MicroLIB

STEP12. Check Create HEX File in Output so that the HEX burning file can be automatically generated after we compile the project.

STEP13. In C/C++, fill in the two macros N32L43X and USE_STDPERIPH_DRIVER in Define in Preprocessor Symbols, which act on the underlying driver library program of the chip. Then check C99 Mode, which is a personal compilation habit. Select it according to your needs, and then add the include path of the header file in the Include Paths column.

STEP14. Select the debugger in Debug: CMSIS-DAP Debugger, then click the Settings button. Then we will see that the MCU has been detected in the SW Device area (the development board needs to be connected to the computer via USB)

STEP15. Keep the default option settings in Utilities, then click the Settings button, and check Reset and Run in Flash Download in the pop-up window. In this way, after we download the program through KEIL, the chip will automatically reset and run the program. After confirming that the program download algorithm in Programming Algorithm is corresponding, we click OK

STEP16. At this point our complete KEIL project has been created and configured. Next we need to write code, compile, download the program, and run the debugger.

Writing a driver

STEP1. The development board has three color LED lights on board, which are controlled by the three GPIO port pins PA8, PB4 and PB5. From the schematic diagram, we can see that when the GPIO port pin outputs a high level, the corresponding LED light is in the state of lighting, and when the GPIO port pin outputs a low level, the corresponding LED light is in the state of extinguishing; the driver is as follows:

/*******************************************************************************
 * @brief * @param       
 * @retval      
 * @attention *******************************************************************************/
void LED_Init(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin          = GPIO_PIN_8;
    GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
    GPIO_InitStructure.GPIO_Pull    = GPIO_No_Pull;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_RESET);

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin          = GPIO_PIN_4;
    GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
    GPIO_InitStructure.GPIO_Pull    = GPIO_No_Pull;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    GPIO_WriteBit(GPIOB, GPIO_PIN_4, Bit_RESET);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin          = GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
    GPIO_InitStructure.GPIO_Pull    = GPIO_No_Pull;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    GPIO_WriteBit(GPIOB, GPIO_PIN_5, Bit_RESET);

    TASK_Append(TASK_ID_LED, LED_Toggle, 250);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LED_Toggle(void)
{
#if 0
    if(!GPIO_ReadOutputDataBit(GPIOA, GPIO_PIN_8))
    {
        GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_SET);
    }
    else
    {
        GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_RESET);
    }
#else
    static uint8_t Index = 0;

    switch(Index)
    {
        case 0:
            GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_SET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_4, Bit_RESET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_5, Bit_RESET);
            break;

        case 1:
            GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_RESET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_4, Bit_SET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_5, Bit_RESET);
            break;

        case 2:
            GPIO_WriteBit(GPIOA, GPIO_PIN_8, Bit_RESET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_4, Bit_RESET);
            GPIO_WriteBit(GPIOB, GPIO_PIN_5, Bit_SET);
            break;

        default:
            break;
    }

    Index = (Index + 1) % 3;
#endif
}

STEP2. The development board has three user buttons and one WAKEUP button on board. The three user buttons are controlled by the three GPIO port pins PA4, PA5 and PA6. From the schematic diagram, we can see that when a button is pressed, the corresponding button state is connected to GND and is at a low level. Therefore, we need to configure the normal state of these three buttons (the buttons are not pressed) as pull-up input, so that we can determine whether the button is pressed by detecting the level state of the button; the other button is the WAKEUP button, which is connected to the port pin PA0. It can be used as a normal button function or as a It is the wake-up button of MCU in low power mode. When used as a wake-up button, a resistor needs to be connected in series to the ground, and the button is connected to MCU_VDD to wake up the MCU in low power mode with a rising edge. When used as a normal button, I only need to configure this pin as a floating input, because under normal circumstances, this product pin has been pulled to GND by a series resistor, and when pressed, it will be short-circuited to MCU_VCC by the button, thereby judging the state of the button. The recognition levels of the three user buttons here are exactly opposite to those of the WAKEUP button, so you need to pay attention to this when programming. The driver is as follows:

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void KEY_Init(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin       = GPIO_PIN_0;
    GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin       = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
    GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    TASK_Append(TASK_ID_KEY, KEY_Scan, 10);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void KEY_SubScan(uint8_t *State, uint8_t *Count, uint8_t Value, uint8_t Active, char *Name)
{
    if(*State == 0)
    {
        if(Value == Active) *Count += 1;
        else                *Count  = 0;

        if(*Count > 5)
        {
            *Count = 0; *State = 1;
            printf("\r\n%s Pressed", Name);
        }
    }
    else
    {
        if(Value != Active) *Count += 1;
        else                *Count  = 0;

        if(*Count > 5)
        {
            *Count = 0; *State = 0;
            printf("\r\n%s Release", Name);
        }
    }
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void KEY_Scan(void)
{
    static uint8_t KeyState[4] = {0, 0, 0, 0};
    static uint8_t KeyCount[4] = {0, 0, 0, 0};

    KEY_SubScan(&KeyState[0], &KeyCount[0], GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_0), Bit_SET,   "WAKEUP");
    KEY_SubScan(&KeyState[1], &KeyCount[1], GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_4), Bit_RESET, "KEY1  ");
    KEY_SubScan(&KeyState[2], &KeyCount[2], GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_5), Bit_RESET, "KEY2  ");
    KEY_SubScan(&KeyState[3], &KeyCount[3], GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_6), Bit_RESET, "KEY3  ");
}

STEP3. In addition to the debugging and program downloading functions, the onboard NS-LINK also integrates a virtual serial port. By connecting it to the USART of the MCU, we can print out some required information to the PC. From the schematic diagram, we can see that the USART1 of the MCU can be connected to the TTL serial port of the NS-LINK by means of a jumper cap. In addition, based on the USART, we have also transplanted the open source code Letter-shell, and the driver is as follows:

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void shellPortWrite(const char ch)
{
    USART_SendData(USART1, (uint8_t)ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void shellPortInit(void)
{
    GPIO_InitType   GPIO_InitStructure;
    NVIC_InitType   NVIC_InitStructure;
    USART_InitType  USART_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin              = GPIO_PIN_9;
    GPIO_InitStructure.GPIO_Mode        = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate   = GPIO_AF4_USART1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin              = GPIO_PIN_10;
    GPIO_InitStructure.GPIO_Pull        = GPIO_Pull_Up;
    GPIO_InitStructure.GPIO_Alternate   = GPIO_AF4_USART1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    USART_StructInit(&USART_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_RX | USART_MODE_TX;
    USART_Init(USART1, &USART_InitStructure);

    USART_ClrFlag(USART1, USART_FLAG_RXDNE);
    USART_ConfigInt(USART1, USART_INT_RXDNE, ENABLE);

    USART_Enable(USART1, ENABLE);

    shell.write = shellPortWrite;
    shellInit(&shell);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void USART1_IRQHandler(void)
{
    if(USART_GetIntStatus(USART1, USART_INT_RXDNE) != RESET)
    {
        shellHandler(&shell, USART_ReceiveData(USART1));
        USART_ClrIntPendingBit(USART1, USART_INT_RXDNE);
    }
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (uint8_t)ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET);

    return ch;
}

Compile, download, debug and run

STEP1. After we have completed the driver program, click the Built or Rebuild button on the toolbar to compile the project source code and confirm that it is correct.

STEP2. Click the Download button on the toolbar or press the F8 shortcut key to burn the program to the chip

STEP3. Open the PC serial debugging software MobaXterm for monitoring. After the code starts running, we see the LED on the development board start flashing, and the serial software prints out messages. At the same time, every time we press a key, we will see the corresponding print message on the serial terminal software, as shown below:

Debugging Issues

After getting the development board, there is no jumper cap short-circuited for RESET in J5 interface. Even if the Reset and Run function is configured in KEIL, it only resets the chip by software reset, and does not actually operate the RESET process of the chip. Therefore, when J5 RESET is not connected, USART prints abnormally after the chip is powered on, as shown in the figure below; I once thought it was a problem with NS-LINK or the chip reset power-on timing, but when I pressed the onboard RESET button independently, the program was normal... So after connecting the oscilloscope to RESET to view the waveform, there was no reset level timing, so I located the RESET jumper cap of J5... After connecting the RESET jumper cap of J5, the program ran normally!!!

Normal power-on printing:

Abnormal power-on printing:

appendix:

Software engineering source code: Project.zip (476.74 KB, downloads: 6)

Operation effect:


This post is from Domestic Chip Exchange

Latest reply

Do all forum friends use Keil? Is there anyone who uses IAR like me?   Details Published on 2022-7-7 21:41
Personal signatureWe are a team and we work as a team !
 
 

6818

Posts

11

Resources
2
 
This post was last edited by lugl4313820 on 2022-6-26 16:57

The post is very well written, especially the key detection. Thank you for your hard work. I look forward to more excellent works!

This post is from Domestic Chip Exchange
 
 
 

205

Posts

0

Resources
3
 
lugl4313820 posted on 2022-6-26 12:48 The post is very well written, especially the key detection. Thank you for your hard work. I look forward to more excellent works!

This post is from Domestic Chip Exchange
Personal signatureWe are a team and we work as a team !
 
 
 

5998

Posts

6

Resources
4
 

Do all forum friends use Keil? Is there anyone who uses IAR like me?

This post is from Domestic Chip Exchange
Personal signature

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list