编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

STM32F103移植RTOS的Proteus仿真

wxchong 2025-02-15 17:45:19 开源技术 28 ℃ 0 评论


从Proteus8.7开始,Labcenter Electronics公司在CPU仿真中加入了对CortexM3内核的支持,STM32F103系列单片机的大部分基础功能都可以在新版本的Proteus中仿真实现,经过多次调试,终于在8.7版本的proteus中实现了RTOS的移植,下面记录下移植过程。

项目仿真使用的CPU型号是STM32F103R6,截止RTOS移植前,项目已经实现了GPIO控制、SPI输出(管脚模拟的方式)、数码管显示(使用串口同步功能)、以及串口(异步)通信功能。电路如图 1所示。其中黄色的LED灯模拟GPIO输出功能;APA102真彩RGB灯来仿真SPI接口;串口通信用Proteus自带的终端测试,用到了USART1;数码管驱动使用的是74HC595,应用了USART2的同步功能。按键功能使用了74ls148芯片来实现,但是这次测试并没有添加到RTOS任务中。


STM32f103的开发环境使用的是Keil MKD5,资源库是使用的
STM32F10x_AN2824_FW_V4.0.0官方库。RTOS移植前的代码已经实现了stm32的GPIO控制、EXTI中断、定时器中断、spi接口、串口等功能。RTOS移植前的项目代码结构如图 2所示。


STM32项目模板就不做详细的介绍了,跟普通的硬件开发流程一样。下面详细说下RTOS移植过程。RTOS的下载地址是
https://freertos.org/index.html,下载到本地的文件内容如图 3所示:FreeRTOS文件夹包含了RTOS基础代码,FreeRTOS-Plus文件夹里面的代码是RTOS增强功能,如tcp、fat等,这个项目主要使用基础功能。


打开FreeRTOS\Source文件夹,这里面包含了需要移植的大部分代码。如图 4所示,需要移植的源文件有:include里面的所有文件,portable里面两个源文件一个头文件,以及图 4里面标红的list.c、queue.c、task.c。由于在这个项目里没有使用诸如任务间消息传递、动态增删任务等功能,所以在Source根目录下的其他源文件不需要移植,如果有需要,的自行添加到项目中。


\\FreeRTOSv10.1.1\FreeRTOS\Source\portable文件夹中包含了编译器相关的接口和内存管理代码,由于本项目使用的是MDK5,所以只保留Keil跟RVDS,再加一个内存管理接口代码的文件夹MemMang,其他的内容删掉,并且将RVDS中的源文件复制到Keil中,如图 5。Portable中需要添加到项目中的两个源文件及一个头文件分别是MemMang文件夹中的heap_3.c以及\\portable\Keil\ARM_CM3中的portmacro.h和port.c。


最后,复制一个FreeRTOSConfig.h头文件到FreeRTOS\Source\include目录中。FreeRTOSConfig.h的原始路径是


这样,freeRTOS文件夹中就包含了移植所需要的所有源文件,然后把freeRTOS文件夹复制到项目目录中。移植完毕后,我的项目目录结构如图 6所示。


代码复制完毕,下一步,将复制的文件添加到项目中,具体步骤就不啰嗦了,添加完毕后的项目结构如图 7。


文件添加以后,不要忘记重新指定下MDK项目的编译器include路径,将rtos头文件的路径添加进项目,要不然会出编译错误,如图 8。


所有准备工作做完,就可以修改代码,代码修改共分为几个部分,包括:

添加头文件

在程序中,添加rtos需要的头文件

重新实现三个中断函数。

在FreeRTOSConfig.h头文件中,添加如下三行#define语句,用xPortPendSVHandler、SysTick_Handler、SVC_Handler重新实现PendSV_Handler、SysTick_Handler、SVC_Handler三个中断函数,由于原stm32f10x_it.c 源文件中已经有这三个中断函数的定义了,所以需要将原来的定义屏蔽掉,这里使用了__weak关键字。

添加任务代码

内存管理参数修改

由于freeRTOS的多任务调度,是占用了STM32内存系统的堆空间,所以需要对内存参数进行修改。如图 10,其中#define configTOTAL_HEAP_SIZE默认的是17K(17*1024),由于STM32F103R6总共才10K RAM,所以我这改成了8*1024。这是使用heap_1.c、heap_2.c、heap_4.c的情况,heap_5.c测试未成功,原因未知。如果跟前面移植步骤一样,使用的是heap_3.c的话,heap_3.c内存管理方式跟其它几种都不一样,堆空间是使用的startup_stm32f10x_ld.s中的配置,所以需要修改启动文件中关于堆设置的代码,我这里将原始的200改成了2000,如图 9。



代码修改完毕后,如果没有错误,就可以下载到电路中运行了,如图 11所示,这个电路里一共添加了四个任务,分别是LED、数码管、spi、串口任务,都已经正常的跑了起来。


最后一点要注意的是,由于RTOS的任务调度使用的是Systick定时器,所以在使用定时器的时候,要避开SYSTICK。我在这个项目里面是使用的TIME3作为自定义定时器。

附:项目运行的其它代码。


/***************const difinition****************/

int main(void)

{

u8 x=0;

int speed=10000;//电机速度

RCC_Configuration(); //SET RCC TO: HSI&56Mhz(8*7)

GPIOInit(); //GPIO初始化

seg7_init(); //同步串口初始化

NVIC_Configuration();

//设置systick时钟源

SysTick_CLKSourceConfig(
SysTick_CLKSource_HCLK_Div8);GPIO_ResetBits(GPIOD, GPIO_Pin_2);//PD2输出低电平,点亮ARMLED

Time3Init();

timer1PWM_Init();

Usart1_Init();

TIM_Cmd(TIM3, ENABLE);//启动定时器3

sSPI2_Init();

/******rtos task******/

xTaskCreate(led_task1,"LED_TASK1",40,NULL,3,NULL);

xTaskCreate(seg_task2,"seg_TASK2",40,NULL,2,NULL);

xTaskCreate(usart_task3,"usart_TASK3",40,NULL,2,NULL);

xTaskCreate(apa_task4,"apa_TASK4",40,NULL,2,NULL);

vTaskStartScheduler();

}

/**freeRTOS head**/

#include "FreeRtos.h"

#include "task.h"

#include "queue.h"


//FreeRTOSConfig.h

#define xPortPendSVHandler PendSV_Handler

#define xPortSysTickHandler SysTick_Handler

#define vPortSVCHandler SVC_Handler

....

//stm32f10x_it.c屏蔽库函数

void __weak SVC_Handler(void)

...


xTaskCreate(led_task1,"LED_TASK1",40,NULL,3,NULL);

xTaskCreate(seg_task2,"seg_TASK2",40,NULL,2,NULL);

xTaskCreate(usart_task3,"usart_TASK3",40,NULL,2,NULL);

xTaskCreate(apa_task4,"apa_TASK4",40,NULL,2,NULL);

vTaskStartScheduler();


#include "stm32f10x_gpio.h"


/*user lib*/

#include "user_misc.h"

#include "7seg.h"

#include "motostep.h"

#include "user_uart.h"

#include "tc72.h"


/**freeRTOS head**/

#include "FreeRtos.h"

#include "task.h"

#include "queue.h"


/*public varble */

u16 keyPC=0xFF;//portPC status readin

u8 led1_onoff=0xff;

u16 publicTIMER=0;//全局定时器

u16 recvDATA[maxUARTData];

u8 recvNewFLAG=0; //1 means new frame received


//功能:LED闪烁

void led_task1(void *aa);

void seg_task2(void *aa);

void usart_task3(void *aa);

void apa_task4(void *aa);

void d_welcom(void);


void led_task1(void *aa)

{

while(1)

{

LED1^=1;

vTaskDelay(50);

}

}


void seg_task2(void *aa)

{

u8 x=0;

while(1)

{

seg7_put(x);

vTaskDelay(20);

x++;

if(x>999)

x=0;

}

}


void usart_task3(void *aa)

{

u8 x=0;

while(1)

{

apaDIS(x);

vTaskDelay(20);

x++;

if(x>8)

x=0;

}

}


void apa_task4(void *aa)

{

while(1)

{

printf("\n\rho ho,usart ok"); ;

vTaskDelay(50);

}

}


void d_welcom(void)

{

printf("\r ====STM32 Vsm DEMO====\r");

printf("\r 1、USART TESTing");

printf("\r 2、motoSTEP S/T");

printf("\r 3、AD Sampling");

printf("\r 4、KEY TESTing");

printf("\re.g input func num ->\r#:");

}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表