搜索
bottom↓
回复: 19

火牛板学习RT-Thread Step by Step——第二篇:跑马灯,动态线程及静态线程

[复制链接]

出0入0汤圆

发表于 2011-12-2 16:33:51 | 显示全部楼层 |阅读模式
2011年12月2日。开始学习RT-Thread的第三天。
前两天花了点时间重构了RT-Thread的目录结构。
目录结构见:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5247738&bbs_page_no=1&bbs_id=3066

下面就开始学习创建线程。
RT-Thread的线程分为静态线程和动态线程。
要使用动态线程。必须在 rtconfig.h 中宏定义 RT_USING_HEAP,使能堆。

顾名思义,
静态线程的内存地址分配都必须事先定下来,不能进行回收分配。使用 rt_thread_init 对线程进行初始化操作。
动态线程使用 rt_thread_cteate 创建而来,需要由RT-Thread向堆中申请一片内存。当线程删除时 rt thread delete, 系统会回收该片内存。

静态线程不会有创建失败的可能性,在系统上电对其进行初始化后,其内存范围就确定且不可更改了。
动态线程在创建时,较为费时,而且可能由于堆用完等原因创建失败。其优点是RAM资源可回收再利用。

因此,结合我自己的理解,对线程使用的观点是:
重要的线程,以及一直使用的线程,可使用静态线程。
次要的线程,偶尔被使用的线程,可使用动态线程。

线程的几个状态时实时操作系统的基础,不做过多解释
1. 运行状态:当前线程正在使用CPU
2. 就绪状态:线程可以被运行,只是由于有优先级更高的线程正在占用CPU。当此线程成为最高优先级时,就进入运行态
3. 挂起状态:线程被挂起/阻塞,不会被运行。
4. 初始状态:线程初始化,或被删除的一个状态。
状态间的转换图:

线程状态的转换图 (原文件名:无标题.png)

第一个范例:跑马灯。
此范例将用到函数:
rt_thread_init  // 初始化一个静态线程
rt_thread_create// 创建一个动态线程
rt_thread_delay // 任务延时

一、在stm32f10x_conf.h文件中,配置LED灯的硬件IO口,如果是火牛板,如下:
/// LED硬件配置
#define LED_LEVEL                       1                                       ///< 0, 低电平点亮LED. 1, 高电平点亮LED

#define LED_NUM                         4                                       ///< 设置LED的数量, 该驱动最多允许16个LED灯.
#if  (LED_NUM > 16)
  #error "LED_NUM define error!"
#endif

#define LED0_PIN                        GPIO_Pin_8                              ///< 设置该LED的PIN口
#define LED0_PORT                       GPIOD                                   ///< 设置该LED的PORT口
#define LED0_CLK                        RCC_APB2Periph_GPIOD                    ///< 设置该LED的时钟模块

#define LED1_PIN                        GPIO_Pin_9
#define LED1_PORT                       GPIOD
#define LED1_CLK                        RCC_APB2Periph_GPIOD

#define LED2_PIN                        GPIO_Pin_10
#define LED2_PORT                       GPIOD
#define LED2_CLK                        RCC_APB2Periph_GPIOD

#define LED3_PIN                        GPIO_Pin_11
#define LED3_PORT                       GPIOD
#define LED3_CLK                        RCC_APB2Periph_GPIOD

typedef enum
{
  LED1 = 0,  // 4个LED灯的名字
  LED2 = 1,
  LED3 = 2,
  LED4 = 3,
} ledName_t;

二、在application.c文件中写一个线程
static void LedApp(void* parameter)
{
  while(1)
  {
    LedOn(LED1);
// 其本质是rt_thread_delay();
// 为了代码兼容性(我的底层驱动延时都是用的DelayMs函数),
// 用DelayMs函数调用了rt_thread_delay()
    DelayMs(500);
    LedOn(LED2);
    DelayMs(500);
    LedOn(LED3);
    DelayMs(500);
    LedOn(LED4);
    DelayMs(500);
    LedOff(LED1);
    DelayMs(500);
    LedOff(LED2);
    DelayMs(500);
    LedOff(LED3);
    DelayMs(500);
    LedOff(LED4);
    DelayMs(500);
  }
}

三、创建或初始化跑马灯线程
//使用静态线程, 需要预留好栈
static uint8_t ledThreadStack[512]; // 跑马灯线程用到的栈
static struct rt_thread ledThread;  // 跑马灯线程TCB控制块

void LedAppInit(void)
{
//////静态线程初始化使用 _init函数
////  rt_thread_init(&ledThread,
////    "LedApp",              // 线程名称
////    LedApp, RT_NULL,       // 线程函数及入口参数
////    ledThreadStack,        // 线程栈地址
////    sizeof(ledThreadStack),// 线程栈大小
////    25,                    // 线程优先级
////    8);                                           // 同优先级时的轮询时间片
////
////  rt_thread_startup(&ledThread); // 进入就绪态

//动态线程创建使用 _create函数
  rt_thread_t thread;
  thread = rt_thread_create(
      "led1",                           // 线程名称
      LedApp, RT_NULL,                   // 线程函数及入口参数
      512,                     // 要动态分配的线程栈大小
      20,                                           // 线程优先级
      5  );                                       // 同优先级时的轮询时间片
  if (thread != RT_NULL) rt_thread_startup(thread);         // 进入就绪态
  else assert_param(0);  // 创建失败则报错
}

四、在main.c文件中
在HardwareInit()函数中
调用 LedInitAll(); 初始化所有的LED灯
在ApplicationInit()函数中
调用 LedAppInit(); 完成线程的初始化或创建

五、编译和下载,就能看到跑马灯了。

STM32_RTThread 跑马灯ourdev_700974RCJJT7.rar(文件大小:3.26M) (原文件名:STM32_RTThread_V100.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-12-2 16:42:18 | 显示全部楼层
不错,支持

出0入0汤圆

发表于 2011-12-2 17:28:47 | 显示全部楼层
占位学习

出0入0汤圆

发表于 2011-12-2 18:57:01 | 显示全部楼层
马甲

出0入0汤圆

发表于 2011-12-2 20:48:14 | 显示全部楼层
这个必须学习,必须顶!

出0入0汤圆

发表于 2011-12-2 21:06:33 | 显示全部楼层
不错!

出0入9汤圆

发表于 2011-12-2 21:41:38 | 显示全部楼层
好,mark

出0入0汤圆

发表于 2011-12-2 23:18:20 | 显示全部楼层
这个ok.f教程太好了, 支持一下。。

出0入0汤圆

发表于 2011-12-3 10:41:54 | 显示全部楼层
支持!

出0入0汤圆

发表于 2011-12-8 09:02:51 | 显示全部楼层
楼主 设置为100表示10ms, 设置为1000表示1ms. 这个不明白。请说下。

出0入0汤圆

发表于 2011-12-8 09:06:12 | 显示全部楼层
******************************************************************************
  * @brief  系统嘀嗒时钟初始化为RT-Thread配置的周期. 其中断处理函数见"rt_hw_timer_handler.c".
  *         参考RT_TICK_PER_SECOND. 设置为100表示10ms, 设置为1000表示1ms.//        1s=1000=1000ms   100
  * @param  None
  * @retval None
  ******************************************************************************
  */
void SysTickInit(void)
{
  RCC_ClocksTypeDef rcc_clocks;
  uint32_t       cnts;

  RCC_GetClocksFreq(&rcc_clocks);                //获取外接晶振
  cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND; // ms  RT_TICK_PER_SECOND  = 1000, 1ms sytick 中断一次  72000 &  0xFFFFFF

  SysTick_Config(cnts);
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
}

/**
  ******************************************************************************
  * @brief  毫秒延时函数
  * @param  time, 要延时的毫秒时间. 误差为最小系统嘀嗒时钟. 该函数不允许在中断中使用!
  *         例如, 系统嘀嗒时钟为10ms, 则使用DelayMs(1), 也将延时10ms.
  * @retval None
  ******************************************************************************
  */
void Delay_ms(uint32_t time)
{
  uint32_t base, tdly;

  base = 1000 / RT_TICK_PER_SECOND;                                             // 获取基值
  tdly = time / base;                                                           // 获取系统延时时间
  if (time % base) tdly++;                                                      // 有余数, 延时取大值
  rt_thread_delay(tdly);
}

出0入0汤圆

发表于 2011-12-8 09:07:01 | 显示全部楼层
100 应该是 1s

出0入0汤圆

 楼主| 发表于 2011-12-8 12:09:31 | 显示全部楼层
RT_TICK_PER_SECOND   
设置的是每秒有多少个系统节拍。设为100就是:每秒有100个系统节拍。
那系统节拍时间就是 1000ms/100 = 10ms

出0入0汤圆

发表于 2011-12-29 13:59:55 | 显示全部楼层
系列教程,支持!

出0入0汤圆

发表于 2012-2-16 20:25:12 | 显示全部楼层
回复【楼主位】draapho
-----------------------------------------------------------------------

跟着楼主学习,很好的东西~

出0入0汤圆

发表于 2012-4-17 08:03:00 | 显示全部楼层
mark,支持一下

出0入0汤圆

发表于 2012-6-5 11:54:49 | 显示全部楼层
谢谢分享引导入门,但是附件下不了

出0入0汤圆

发表于 2012-6-5 12:34:56 | 显示全部楼层
写得不错,

出0入0汤圆

发表于 2013-9-3 10:34:07 | 显示全部楼层
继续学习,支持
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 09:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表