zl程序教程

您现在的位置是:首页 >  其它

当前栏目

freeRTOS移植和protues防真stm32

STM32 移植 freeRTOS
2023-09-14 09:16:38 时间
  • 准备freeRTOS源码和一个简单的工程

freeRTOS源码下载链接:

链接:https://pan.baidu.com/s/1hgyQqoDqDuETEHr_I80M8Q 
提取码:e890

另外还需要准备一个简单的工程,这里使用led闪烁的例子来完成移植

已移植好的stm32f103ve例程下载链接:

https://download.csdn.net/download/mygod2008ok/12234264

  • 开始移植

  1. 在led闪烁工程中新建一个文件夹,并命名为freeRTOS

2.将准备好的freeRTOS库中的源码全部复制

3. 粘贴到led闪烁工程中的freeRTOS文件夹中,并将portable中的文件仅保留以下4个

4.在工程中创建两个文件组freeRTOS_sourcet和freeRTOS_portable,并加入以下文件到工程,注意port.c选择M3里面的,因为stm32f1是m3系列

5. 另外要添加freeRTOS相关的文件路径到工程中

6.先编译一下,出现如下错误

7.少了FreeRTOSConfig.h文件,可以去下载一个,也可以到freeRTOS提供的Demo中复制一份过来,这里从DEMO中寻找

8.找到FreeRTOSConfig.h文件复制

9.粘贴到工程中的FreeRTOS中的include文件夹内

10.再次编译一下工程,会出现以下错误

11.按住CTRL+F键,输入xTaskGetCurrentTaskHandle后进行全局搜索

12.搜索结果如下

13.在FreeRTOSConfig.h中加入如下宏后再次编译一下

#define INCLUDE_xTaskGetCurrentTaskHandle 1

14.对port.c中的三个函数进行适配,也就是让启动文件分别能够指向这三个函数

15.再次编译一下,会出现以下错误

16.将stm32f10x_it.c中的SVC_Handler,PendSV_Handler,SysTick_Handler三个函数屏蔽掉,重新编译一下工程

17.在main文件中加入头文件task.h,然后编译一下,出现如下错误

18.双击跳转到出错处,并加入FreeRTOS.h头文件再次编译一下,编译通过

19.在main中创建以下2个任务,main.c如下

  /**
* @file main.c
* @author 仙剑情缘
* @version V1.0
* @data 20-Oct-2019
* @brief 串口USART2实验
* 
*  介绍配置USART2串口收发功能
*
*  
*  
*/
#include "stm32f10x_usart.h"
#include "stm32f10x.h"
#include <stdio.h>
#include "task.h"

/* 加入以下代码,支持printf函数,而不需要选择use MicroLIB */
#ifdef DEBUG
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
}  
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART2->SR&0X40)==0);
	USART2->DR = (u8) ch;      
		
	return ch;
}
#endif 


uint8_t rxBuf[40];
uint8_t rxLen;

/**
  * @brief  USART2串口初时化
  *        
  *         
  * @param  uint32_t baudrate[in]:设置波特率
  * @retval None
  */
void Usart2_Init(uint32_t baudrate)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	/* 初时化串口前,先将相应的时钟打开 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	
	
	/* 初时化USART2 TX PA2引脚设为复用推挽输出 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/* 初时化USART2 RX PA3引脚为浮空输入 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);/*!< 复位串口2 */
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);/*!< 停止复位 */
	
	/* USART2 NVIC初时化 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*!< 设置NVIC中断分组2:2位抢占优先级,2位响应优先级   0-3; */
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; /*!< USART2中断通道USART1_IRQn  */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; /*!< 抢占优先级3 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    /*!< 子优先级3 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  /*!<  IRQ使能通道 */
	NVIC_Init(&NVIC_InitStructure);   /*!< 初时化NVIC寄存器  */
	
	/* USART2初时化设置 */
	USART_InitStructure.USART_BaudRate = baudrate;   /*!<  设置波特率 */
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; /*!< 8位数据*/
	USART_InitStructure.USART_StopBits = USART_StopBits_1;   /*!< 1位停止位 */
	USART_InitStructure.USART_Parity = USART_Parity_No;   /*!< 无校验位 */
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  /*!< 收发模式*/
	USART_Init(USART2,&USART_InitStructure);  /*!< 初时化串口2 */
	
	/* 开启串口2接收中断 */
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
	/* 使能串口2 */
	USART_Cmd(USART2,ENABLE);

}

/**
* @brief  USART2串口发送函数
  *        
  *         
	* @param   uint8_t *buf[in]:待发送的数据buffer
* @param   uint16_t len:发送的数据长度
  * @retval None
  */
void USART2_Send_Data(uint8_t *buf,uint16_t len)
{
	for(uint16_t i = 0; i<len; i++)
	{
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET); /*!< 是否可以写数据到发送寄存器*/
		USART_SendData(USART2,buf[i]);
		while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); /*!<发送是否完成*/
	}	
}


/**

  * @brief  USART2串口中断函数

  *        

  *         

  * @param  None

  * @retval None

  */

void USART2_IRQHandler(void) 

{

	/* 暂存接收结果 */

	uint8_t result;

  /* @note

  *   - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun 

  *     error) and IDLE (Idle line detected) pending bits are cleared by 

  *     software sequence: a read operation to USART_SR register 

  *     (USART_GetITStatus()) followed by a read operation to USART_DR register 

  *     (USART_ReceiveData()).

  *   - RXNE pending bit can be also cleared by a read to the USART_DR register 

  *     (USART_ReceiveData()).

  */

	/* 检查是否为USART2接收中断 */

	if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)

	{

		 result = USART_ReceiveData(USART2);   

                 if(rxLen < 20)

		 {

			 rxBuf[rxLen] = result;

			 rxLen++;

		 }			 

	}

	/* 溢出发生时,先读SR,再读DR,解决中断不进入问题*/

	else if(USART_GetFlagStatus(USART2,USART_IT_ORE) == SET)

	{
		  USART_ClearFlag(USART2,USART_IT_ORE);
	    USART_ReceiveData(USART2);
	}


}


// 任务句柄
TaskHandle_t task2_handler;
/**
* 任务2
*/
void led2_task(void* t)
{
	
	while(1)
	{
		 if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_9))
				GPIO_ResetBits(GPIOB, GPIO_Pin_9 );  
		 else
			GPIO_SetBits(GPIOB, GPIO_Pin_9 ); 
		  printf("task2\n");
		 vTaskDelay(20);
	}
}



/**
* 任务1
*/
void led1_task(void* t)
{
	
	uint8_t i = 5;
	while(1)
	{
		 if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_8))
				GPIO_ResetBits(GPIOB, GPIO_Pin_8 );  
		 else
			GPIO_SetBits(GPIOB, GPIO_Pin_8 ); 
		  printf("task1\n");
		 vTaskDelay(10);
		 if(i > 0)
		 {
			 if(--i == 0)
			 {
				 vTaskDelete(task2_handler);
			 }
		 }
	}
}


/**
  * @brief  主函数,程序的入口
  *        
  *         
  * @param  None
  * @retval int:不用理会,对于嵌入式系统,永远都不会返回
  */
int main(void)
{
	Usart2_Init(9600);
	printf("%s","hello world");
//	assert_param(0);
	
	GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;    
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);  
	 
	xTaskCreate(led2_task, "LED2", configMINIMAL_STACK_SIZE, NULL, 3, &task2_handler );
	xTaskCreate(led1_task, "LED1", configMINIMAL_STACK_SIZE, NULL, 2, NULL );
	vTaskStartScheduler();
	
	for(;;)
	{
		if(rxLen >= 20)
		{
			USART2_Send_Data(rxBuf,20);
			rxLen = 0;
		}
		
	}
}

#if USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
	printf("\r\nfile path is %s,error line is %d\r\n",file,line);
	while(1);
}
#endif 

编译运行

如果这份文章对你们有帮助,请双击666