欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F103ZE FreeRTOS移植、测试

程序员文章站 2024-02-22 18:36:11
...

一、前期准备
单片机:STM32F103ZET6
开发环境:MDK5.14
库函数:标准库V3.5
FreeRTOS:V9.0.0(网上下载,官网上目前是V10.0.1)

二、实验效果
总共6个任务,串口1、串口2、4个RGB小灯以不同频率闪烁。5050 RGB LED驱动请参考RGB驱动,串口1、2同时打印测试信息。
STM32F103ZE FreeRTOS移植、测试

三、移植准备
下载好的FreeRTOS源码中,只需要把Source文件夹加入工程。
1.FreeRTOS内核文件,如下图所示,里面所有C文件加入到工程里面
STM32F103ZE FreeRTOS移植、测试
2.将portable中无关文件夹删除掉,只留下如图所示的三个文件夹。Keil文件夹不用管,MemMang里面是heap1.c~heap5.c文件,这个是内存管源码,这里移植将heap4.c加入工程。RVDS中ARM_M3的C文件加入工程
STM32F103ZE FreeRTOS移植、测试
STM32F103ZE FreeRTOS移植、测试
STM32F103ZE FreeRTOS移植、测试
STM32F103ZE FreeRTOS移植、测试
3.Keil工程
STM32F103ZE FreeRTOS移植、测试
4.修改stm32启动文件
STM32F103ZE FreeRTOS移植、测试

四、测试代码
完整工程请加QQ:1002521871,验证:呵呵
uart.h

#ifndef __UART_H__
#define __UART_H__

#include "stm32f10x.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "message.h"

/*  UART IOpin definirion   */
#define     TX1         GPIO_Pin_9
#define     RX1         GPIO_Pin_10
#define     TX2         GPIO_Pin_2
#define     RX2         GPIO_Pin_3
#define     TX3         GPIO_Pin_10
#define     RX3         GPIO_Pin_11

#define     RecDataLen      128
extern char RecData[RecDataLen];
extern char *pIndex;
extern char *pWrite;
extern char *pRead;

extern int USART_PRINTF_FLAG;
extern void USARTConfiguration(int Baudrate);
extern void USART_Send(USART_TypeDef* USARTx, char c);
extern char USART_Received(USART_TypeDef* USARTx);

#endif

uart.c,多串口通用printf程序请参考多串口共用printf讲解

#include "uart.h"

char RecData[RecDataLen] = {0};
char *pIndex = RecData;
char *pWrite = RecData;
char *pRead = RecData;

int USART_PRINTF_FLAG = 0;

void USARTConfiguration(int Baudrate)
{
    USART_InitTypeDef   MyUSART;
    GPIO_InitTypeDef    GPIO;
    NVIC_InitTypeDef    MyNVIC;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | 
                           RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO.GPIO_Pin = TX1;
    GPIO.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO);

     /* Configure USART1 Rx (PA.10) as input floating */
    GPIO.GPIO_Pin = RX1;
    GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    MyNVIC.NVIC_IRQChannel = USART1_IRQn;
    MyNVIC.NVIC_IRQChannelSubPriority = 0;
    MyNVIC.NVIC_IRQChannelPreemptionPriority = 0;
    MyNVIC.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&MyNVIC);  

    MyUSART.USART_BaudRate = Baudrate;
    MyUSART.USART_WordLength = USART_WordLength_8b;
    MyUSART.USART_StopBits = USART_StopBits_1;
    MyUSART.USART_Parity = USART_Parity_No;
    MyUSART.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    MyUSART.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &MyUSART);
    USART_Cmd(USART1, ENABLE);

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);

    /* Configure USART2 Tx (PA.02) as alternate function push-pull */
    GPIO.GPIO_Pin = TX2;
    GPIO.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO);

     /* Configure USART2 Rx (PA.3) as input floating */
    GPIO.GPIO_Pin = RX2;
    GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    MyNVIC.NVIC_IRQChannel = USART2_IRQn;
    MyNVIC.NVIC_IRQChannelSubPriority = 0;
    MyNVIC.NVIC_IRQChannelPreemptionPriority = 1;
    MyNVIC.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&MyNVIC);  

    MyUSART.USART_BaudRate = Baudrate;
    MyUSART.USART_WordLength = USART_WordLength_8b;
    MyUSART.USART_StopBits = USART_StopBits_1;
    MyUSART.USART_Parity = USART_Parity_No;
    MyUSART.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    MyUSART.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART2, &MyUSART);
    USART_Cmd(USART2, ENABLE);

    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); 
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);

    /* Configure USART3 Tx (PB.10) as alternate function push-pull */
    GPIO.GPIO_Pin = TX3;
    GPIO.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO);

     /* Configure USART3 Rx (PB.11) as input floating */
    GPIO.GPIO_Pin = RX3;
    GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    MyNVIC.NVIC_IRQChannel = USART3_IRQn;
    MyNVIC.NVIC_IRQChannelSubPriority = 0;
    MyNVIC.NVIC_IRQChannelPreemptionPriority = 2;
    MyNVIC.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&MyNVIC);  

    MyUSART.USART_BaudRate = Baudrate;
    MyUSART.USART_WordLength = USART_WordLength_8b;
    MyUSART.USART_StopBits = USART_StopBits_1;
    MyUSART.USART_Parity = USART_Parity_No;
    MyUSART.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    MyUSART.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART3, &MyUSART);
    USART_Cmd(USART3, ENABLE);

    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); 
    USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
}

void USART_Send(USART_TypeDef* USARTx, char c)
{
    USART_SendData(USARTx, c);
    /* loop until the end of transmission */
    while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);    
}

char USART_Received(USART_TypeDef* USARTx)
{
    char dat;
    //while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
    dat = (char)(USART_ReceiveData(USARTx)&0xff);
    return dat;
}

void USART1_IRQHandler(void)
{
    uint8_t clear = clear;
    USART_PRINTF_FLAG = 1;
    if(USART_GetFlagStatus(USART1,USART_IT_RXNE) != RESET )
    {
        if ( (*(pWrite-1) != 0x0A) && ((pWrite - pIndex) < RecDataLen) )
        {
            *pWrite = USART_Received(USART1);
            pWrite ++;
        }
        else
        {
            USART_Received(USART1);
        }
    }
    else if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
    {
        if ( *(pWrite - 1) == 0x0A && *(pWrite - 2) == 0x0D)
        {
            cmdDealFlag = 1;
        }
        else 
        {
            printf("%s", RecFlowMess);
        }

        pWrite = pIndex;
        clear = USART1->SR;
        clear = USART1->DR;
    }
}

void USART2_IRQHandler(void)
{
    uint8_t clear = clear;
    USART_PRINTF_FLAG = 2;
    if(USART_GetFlagStatus(USART2,USART_IT_RXNE) != RESET )
    {
        if ( (*(pWrite-1) != 0x0A) && ((pWrite - pIndex) < RecDataLen) )
        {
            *pWrite = USART_Received(USART2);
            pWrite ++;
        }
        else
        {
            USART_Received(USART2);
        }
    }
    else if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
    {
        if ( *(pWrite - 1) == 0x0A && *(pWrite - 2) == 0x0D)
        {
            cmdDealFlag = 1;
        }
        else 
        {
            printf("%s", RecFlowMess);
        }

        pWrite = pIndex;
        clear = USART2->SR;
        clear = USART2->DR;
    }
}

void USART3_IRQHandler(void)
{
    uint8_t clear = clear;
    USART_PRINTF_FLAG = 3;
    if(USART_GetFlagStatus(USART3,USART_IT_RXNE) != RESET )
    {
        if ( (*(pWrite-1) != 0x0A) && ((pWrite - pIndex) < RecDataLen) )
        {
            *pWrite = USART_Received(USART3);
            pWrite ++;
        }
        else
        {
            USART_Received(USART3);
        }
    }
    else if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
    {
        if ( *(pWrite - 1) == 0x0A && *(pWrite - 2) == 0x0D)
        {
            cmdDealFlag = 1;
        }
        else 
        {
            printf("%s", RecFlowMess);
        }

        pWrite = pIndex;
        clear = USART3->SR;
        clear = USART3->DR;
    }
}
int fputc(int ch, FILE *f)
{
#ifdef DBG_ITM
/* ?Printf????ITM???????  */
  if (DEMCR & TRCENA) {
    while (ITM_Port32(0) == 0);
    ITM_Port8(0) = ch;
  }
#else  
/* ?Printf?????? */
    switch (USART_PRINTF_FLAG)
    {   
        case 1:
            USART_SendData(USART1, (unsigned char) ch);
            while (!(USART1->SR & USART_FLAG_TXE));
            break;
        case 2:
            USART_SendData(USART2, (unsigned char) ch);
            while (!(USART2->SR & USART_FLAG_TXE));
            break;
        case 3:
            USART_SendData(USART3, (unsigned char) ch);
            while (!(USART3->SR & USART_FLAG_TXE));
            break;
        default:
            USART_SendData(USART1, (unsigned char) ch);
            while (!(USART1->SR & USART_FLAG_TXE));
            break;
    }

#endif  
  return (ch);
}

rtos_app.h

#ifndef __RTOS_APP_H__
#define __RTOS_APP_H__
#include "stm32f10x.h"
#include "uart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"

#define     START_TASK_PRIO         1
#define     START_STK_SIZE          128
extern TaskHandle_t StartTask_Handler;
extern void Start_task(void *pvParameters);

#define     LED0_TASK_PRIO          2
#define     LED0_STK_SIZE           50
extern void LED0_task(void *pvParameters);

#define     LED1_TASK_PRIO          3
#define     LED1_STK_SIZE           50
extern void LED1_task(void *pvParameters);

#define     LED2_TASK_PRIO          6
#define     LED2_STK_SIZE           50
extern void LED2_task(void *pvParameters);

#define     LED3_TASK_PRIO          5
#define     LED3_STK_SIZE           50
extern void LED3_task(void *pvParameters);

#define     UART1_TASK_PRIO         4
#define     UART1_STK_SIZE          50

#define     UART2_TASK_PRIO         7
#define     UART2_STK_SIZE          50


#endif

rtos_app.c,因为多串口共用 printf()打印信息,需要访问标志量USART_PRINTF_FLAG ,这个变量是临界资源,必须加上处理措施,才能进行正常的运行。这里是在俩段程中各加入了进入临界资源taskENTER_CRITICAL(); 和退出临界资源taskEXIT_CRITICAL();函数进行保护。有关临界资源互斥、同步访问的问题,请自行百度。

#include "rtos_app.h"


TaskHandle_t StartTask_Handler;
TaskHandle_t LED0Task_Handler;
TaskHandle_t LED1Task_Handler;
TaskHandle_t LED2Task_Handler;
TaskHandle_t LED3Task_Handler;
TaskHandle_t UART1Task_Handler;
TaskHandle_t UART2Task_Handler;

void LED0_task(void *pvParameters)
{
    while(1)
    {
        RGB_LED1 = ON;
        vTaskDelay(200 / portTICK_RATE_MS);
        RGB_LED1 = OFF;
        vTaskDelay(800 / portTICK_RATE_MS);
    }
}

void LED1_task(void *pvParameters)
{
    while(1)
    {
        RGB_LED2 = ON;
        vTaskDelay(400 / portTICK_RATE_MS);
        RGB_LED2 = OFF;
        vTaskDelay(600 / portTICK_RATE_MS);
    }
}

void LED2_task(void *pvParameters)
{
    while(1)
    {
        RGB_LED3 = ON;
        vTaskDelay(600 / portTICK_RATE_MS);
        RGB_LED3 = OFF;
        vTaskDelay(400 / portTICK_RATE_MS);
    }
}

void LED3_task(void *pvParameters)
{
    while(1)
    {
        RGB_LED4= ON;
        vTaskDelay(800 / portTICK_RATE_MS);
        RGB_LED4 = OFF;
        vTaskDelay(200 / portTICK_RATE_MS);
    }
}

void UART1_task(void *pvParameters)
{
    int i = 0;
    while(1)
    {
        taskENTER_CRITICAL();
        USART_PRINTF_FLAG = 1;
        printf("UART1-%06d: FreeRTOS Test!\r\n",i);
        vTaskDelay(1000 / portTICK_RATE_MS);
        i ++;
        taskEXIT_CRITICAL();
    }
}

void UART2_task(void *pvParameters)
{
    int i = 0;
    while(1)
    {
        taskENTER_CRITICAL();
        USART_PRINTF_FLAG = 2;
        printf("UART2-%06d: FreeRTOS Test!\r\n",i);
        vTaskDelay(1000 / portTICK_RATE_MS);
        i ++;
        taskEXIT_CRITICAL();
    }
}

void Start_task(void *pvParameters)
{
    taskENTER_CRITICAL();

     xTaskCreate(
        (TaskFunction_t ) LED0_task,        
        (const char*    ) "LED0_task",      
        (uint16_t       ) LED0_STK_SIZE, 
        (void*          ) NULL,             
        (UBaseType_t    ) LED0_TASK_PRIO,   
        (TaskHandle_t*  ) &LED0Task_Handler
    ); 

    xTaskCreate(
        (TaskFunction_t) LED1_task,
        (const char *) "LED1_task",
        (uint16_t) LED1_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) LED1_TASK_PRIO,
        (TaskHandle_t *) &LED1Task_Handler
    );

    xTaskCreate(
        (TaskFunction_t) UART1_task,
        (const char *) "UART1_task",
        (uint16_t) UART1_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) UART1_TASK_PRIO,
        (TaskHandle_t *) &UART1Task_Handler
    );

    xTaskCreate(
        (TaskFunction_t) LED2_task,
        (const char *) "LED2_task",
        (uint16_t) LED2_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) LED2_TASK_PRIO,
        (TaskHandle_t *) &LED2Task_Handler
    );

    xTaskCreate(
        (TaskFunction_t) LED3_task,
        (const char *) "LED3_task",
        (uint16_t) LED3_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) LED3_TASK_PRIO,
        (TaskHandle_t *) &LED3Task_Handler
    );

        xTaskCreate(
        (TaskFunction_t) UART2_task,
        (const char *) "UART2_task",
        (uint16_t) UART2_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) UART2_TASK_PRIO,
        (TaskHandle_t *) &UART2Task_Handler
    );

    vTaskDelete(StartTask_Handler);
    taskEXIT_CRITICAL();
}

main.c

/***************************************************
**              STM32F103ZET6   工程模板
**      MDK5,JLink-V8, StdPeriph_Lib V3.5
**  基本配置 
**      1.时钟树配置,72MHz
**      2.精准1ms,10us延时函数
**      3.GPIO口重定向,实现类51的IO操作方式
**      4.USART1配置,波特率115200
**      5.USART1, TXD: PA9  RXD: PA10
**  作者:ALEX HUA
**  时间:2018/2/9
****************************************************
**  测试程序说明
**  1)*IDN? 2)*Help? 3) *Version? 4)*LED ON/OFF?
**  串口模版自带前三个命令,第四个命令为测试命令
**  以上命令发送均要带<CR><LF>,hex发送需要加0x0D,0x0A
**  以上命令发送均不区分大小写
****************************************************/
#include "conf.h"

int main (void)
{
    Configuration();
    LED_R       = OFF;          
    LED_G       = ON;   
    LED_B       = OFF;

    //GPIOD->ODR = 0x0000;
//  while (1)
//  {
//      if (cmdDealFlag == 1)
//      {           
//          DealWithUARTMess(RecData);
//          cmdDealFlag = 0;
//      }
//  }

    xTaskCreate(
        (TaskFunction_t) Start_task,
        (const char *) "Start_task",
        (uint16_t) START_STK_SIZE,
        (void *) NULL,
        (UBaseType_t) START_TASK_PRIO,
        (TaskHandle_t *) &StartTask_Handler
    );

    vTaskStartScheduler();


}

由于作者能力有限,有不妥之处欢迎指正,邮箱aaa@qq.com