你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32关于FreeRTOS的移植

[复制链接]
STMCU小助手 发布时间:2021-11-13 23:00
一、源码处理
文件下载
1、官网下载源码

2020120408581471.png


2、找到相关的例程
20201204090007422.png


3、进入源码文件

20201204090449569.png


4、找到相关的文件

20201204090656435.png


keil、RVDS为需要的文件,MemMang为需要的内存文件

文件移植
1、在之前led灯程序基础上添加文件
注释:在正点原子开源工程里可以下载

  1. 创建文件并包含以下文件
复制代码
20201204091934949.png



2、将相关.h文件包含进去

20201204092059339.png


此时编译会报错
继续包含所需要的文件

20201204092223362.png


文件地址:

20201204092402786.png


3、修改相关文件

注释:正点原子给的工程例程是支持ucos的,所以我们需要把一些oc相关的删除掉
以下是修改之后程序代码:
sys.h

20201204092609682.png


usart.c

20201204092722544.png


原来是include.h,需要改成FreePTOS.h

delay.c

1:SysTIck_Handler()
  1. extern void xPortSysTickHandler(void);

  2. //systick中断服务函数,使用ucos时用到
  3. void SysTick_Handler(void)
  4. {        
  5.     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  6.     {
  7.         xPortSysTickHandler();        
  8.     }
  9. }
复制代码

2:delay_init

  1. oid delay_init()
  2. {
  3.         u32 reload;
  4.         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLK
  5.         fac_us=SystemCoreClock/1000000;                                //不论是否使用OS,fac_us都需要使用
  6.         reload=SystemCoreClock/1000000;                                //每秒钟的计数次数 单位为M  
  7.         reload*=1000000/configTICK_RATE_HZ;                        //根据configTICK_RATE_HZ设定溢出时间
  8.                                                                                                 //reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右        
  9.         fac_ms=1000/configTICK_RATE_HZ;                                //代表OS可以延时的最少单位           

  10.         SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;           //开启SYSTICK中断
  11.         SysTick->LOAD=reload;                                                 //每1/configTICK_RATE_HZ秒中断一次        
  12.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;           //开启SYSTICK   
  13. }
复制代码

3:两个延时函数

  1. //延时nus
  2. //nus:要延时的us数.        
  3. //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)                                                                              
  4. void delay_us(u32 nus)
  5. {               
  6.         u32 ticks;
  7.         u32 told,tnow,tcnt=0;
  8.         u32 reload=SysTick->LOAD;                                //LOAD的值                     
  9.         ticks=nus*fac_us;                                                 //需要的节拍数
  10.         told=SysTick->VAL;                                        //刚进入时的计数器值
  11.         while(1)
  12.         {
  13.                 tnow=SysTick->VAL;        
  14.                 if(tnow!=told)
  15.                 {            
  16.                         if(tnow<told)tcnt+=told-tnow;        //这里注意一下SYSTICK是一个递减的计数器就可以了.
  17.                         else tcnt+=reload-tnow+told;            
  18.                         told=tnow;
  19.                         if(tcnt>=ticks)break;                        //时间超过/等于要延迟的时间,则退出.
  20.                 }  
  21.         };                                                                                    
  22. }  
  23. //延时nms
  24. //nms:要延时的ms数
  25. //nms:0~65535
  26. void delay_ms(u32 nms)
  27. {        
  28.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  29.         {               
  30.                 if(nms>=fac_ms)                                                //延时的时间大于OS的最少时间周期
  31.                 {
  32.                            vTaskDelay(nms/fac_ms);                         //FreeRTOS延时
  33.                 }
  34.                 nms%=fac_ms;                                                //OS已经无法提供这么小的延时了,采用普通方式延时   
  35.         }
  36.         delay_us((u32)(nms*1000));                                //普通方式延时
  37. }

  38. //延时nms,不会引起任务调度
  39. //nms:要延时的ms数
  40. void delay_xms(u32 nms)
  41. {
  42.         u32 i;
  43.         for(i=0;i<nms;i++) delay_us(1000);
  44. }
复制代码

4、屏蔽中断

20201204093241632.png


5、最后编译一下,就创建成功啦!!!

创建任务并执行任务
创建任务分以下步骤:
  1. 设置任务优先级
  2. 设置任务堆栈大小
  3. 设置任务句柄
  4. 设置任务函数
复制代码
我创建了一个任务,使得两个灯同时闪烁,以及串口输出Halloword,以及在移植OLED屏幕的程序

OLED程序移植相对简单,只需要把相关文件夹进去就行
这是移植所需要的的一些相关文件:
20201204111212622.png


其中NRF24L01.c是无线通信模块的,我还在肝中,有需要请私信我。
主函数:

  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "lcd.h"

  8. //任务优先级
  9. #define START_TASK_PRIO                1
  10. //任务堆栈大小        
  11. #define START_STK_SIZE                 128  
  12. //任务句柄
  13. TaskHandle_t StartTask_Handler;
  14. //任务函数
  15. void start_task(void *pvParameters);


  16. //任务优先级
  17. #define LED0_TASK_PRIO                2
  18. //任务堆栈大小        
  19. #define LED0_STK_SIZE                 50  
  20. //任务句柄
  21. TaskHandle_t LED0Task_Handler;
  22. //任务函数
  23. void led0_task(void *pvParameters);

  24. //任务优先级
  25. #define USART0_TASK_PRIO                3
  26. //任务堆栈大小        
  27. #define USART0_STK_SIZE                 50  
  28. //任务句柄
  29. TaskHandle_t USART0Task_Handler;
  30. //任务函数
  31. void usart0_task(void *pvParameters);


  32. //任务优先级
  33. #define TEMPER0_TASK_PRIO                4
  34. //任务堆栈大小        
  35. #define TEMPER0_STK_SIZE                 50  
  36. TaskHandle_t TEMPER0Task_Handler;
  37. //任务函数
  38. void TEMPER0_task(void *pvParameters);


  39. //任务优先级
  40. #define LCD_TO_TASK_PRIO                5
  41. //任务堆栈大小        
  42. #define LCD_TO_STK_SIZE                 50  
  43. //任务句柄
  44. TaskHandle_t LCD_TOTask_Handler;
  45. //任务函数

  46. void LCD_TO_task(void *pvParameters);
  47. //任务句柄

  48. TaskHandle_t TEMPER0Task_Handler;
  49. //任务函数

  50. void temper0_task(void *pvParameters);
  51. int main(void)
  52. {
  53.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4         
  54.         delay_init();                                            //延时函数初始化         
  55.         uart_init(115200);                                        //初始化串口
  56.         LED_Init();
  57.         //初始化LED
  58.         LCD_Init();
  59.         POINT_COLOR=RED;
  60.         //初始化LCD
  61.         
  62.         //创建开始任务
  63.     xTaskCreate((TaskFunction_t )start_task,            //任务函数
  64.                 (const char*    )"start_task",          //任务名称
  65.                 (uint16_t       )START_STK_SIZE,        //任务堆栈大小
  66.                 (void*          )NULL,                  //传递给任务函数的参数
  67.                 (UBaseType_t    )START_TASK_PRIO,       //任务优先级
  68.                 (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
  69.     vTaskStartScheduler();          //开启任务调度
  70. }

  71. //开始任务任务函数
  72. void start_task(void *pvParameters)
  73. {
  74.     taskENTER_CRITICAL();           //进入临界区
  75.     //创建LED0任务
  76.     xTaskCreate((TaskFunction_t )led0_task,            
  77.                 (const char*    )"led0_task",           
  78.                 (uint16_t       )LED0_STK_SIZE,
  79.                 (void*          )NULL,                                
  80.                 (UBaseType_t    )LED0_TASK_PRIO,        
  81.                 (TaskHandle_t*  )&LED0Task_Handler);   
  82.     //创建usart0任务
  83.     xTaskCreate((TaskFunction_t )usart0_task,     
  84.                 (const char*    )"usart0_task",   
  85.                 (uint16_t       )USART0_STK_SIZE,
  86.                 (void*          )NULL,
  87.                 (UBaseType_t    )USART0_TASK_PRIO,
  88.                 (TaskHandle_t*  )&USART0Task_Handler);
  89.                 //创建temper0任务
  90.     xTaskCreate((TaskFunction_t )temper0_task,     
  91.                 (const char*    )"temper_task",   
  92.                 (uint16_t       )TEMPER0_STK_SIZE,
  93.                 (void*          )NULL,
  94.                 (UBaseType_t    )TEMPER0_TASK_PRIO,
  95.                 (TaskHandle_t*  )&TEMPER0Task_Handler);
  96.                                 
  97.         xTaskCreate((TaskFunction_t )LCD_TO_task,     
  98.                 (const char*    )"LCD_TO_task",   
  99.                 (uint16_t       )LCD_TO_STK_SIZE,
  100.                 (void*          )NULL,
  101.                 (UBaseType_t    )LCD_TO_TASK_PRIO,
  102.                 (TaskHandle_t*  )&LCD_TOTask_Handler);
  103.                                 
  104.     vTaskDelete(StartTask_Handler); //删除开始任务
  105.     taskEXIT_CRITICAL();            //退出临界区
  106. }


  107. //LED0任务函数
  108. void led0_task(void *pvParameters)
  109. {
  110.     while(1)
  111.     {
  112.         LED0=~LED0;
  113.                                 if(LED0==1)
  114.                                         printf("灯灭\r\n");
  115.                                 else
  116.                                         printf("灯亮\r\n");
  117.         vTaskDelay(1000);
  118.     }
  119. }   


  120. //usart0任务函数
  121. void usart0_task(void *pvParameters)
  122. {
  123.         
  124.                         while(1)
  125.                         {        
  126.                                 printf("hello lee");
  127.                                 printf("\r\n");
  128.                                 vTaskDelay(1000);
  129.                         }
  130. }

  131. //temper0任务函数(暂时为LED1翻转)
  132. void temper0_task(void *pvParameters)
  133. {
  134.                                        
  135.                         while (1)
  136.                         {        
  137.                                 LED1=~LED1;
  138.                                 vTaskDelay(1000);                        
  139.                         }
  140. }

  141. void LCD_TO_task(void *pvParameters)
  142. {
  143.         u8 lcd_id[12];
  144.         sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);        
  145.         while (1)
  146.                 {        
  147.                 LCD_ShowString(30,40,210,24,24,"WarShip STM32 ^_^");
  148.                 LCD_ShowString(30,70,200,16,16,"TFTLCD TEST");
  149.                 LCD_ShowString(30,90,200,16,16,"DARKSTARS");
  150.                  LCD_ShowString(30,110,200,16,16,lcd_id);                //显示LCD ID
  151.                 LCD_ShowString(30,130,200,12,12,"2020/12/4");
  152.                 vTaskDelay(1000);        
  153.                 }
  154. }
复制代码

20201204135314206.png


20201204135923571.gif


20201204140800832.gif





总结
通过这次系统的移植,我感受到系统的魅力,有了系统之后,许多程序就能并行运行了,这样我们就能完成更加高效,更加同步的信息处理和信息传输。对于高刷新率的信息处理,移植系统无疑是更好的选择。




收藏 评论0 发布时间:2021-11-13 23:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版