FreeRTOS学习笔记——基础知识与移植(STM32F103)

2023-05-16

1.1 前后台系统:

    早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。

     简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。


1.2 RTOS系统:

       RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。实时操作系统又分为硬实时和软实时。硬实时要求在规定的时间内必须完成操作 ,硬实时系统不允许超时,在软实时里面处理过程超时的后果就没有那么严格。
       在实时操作系统中,我们可以把要实现的功能划分为多个任务,每个任务负责实现其中的一部分,每个任务都是一个很简单的程序,通常是一个死循环。
       RTOS操作系统:FreeRTOS,UCOS,RTX,RT-Thread,DJYOS等。
       RTOS操作系统的核心内容在于:实时内核。

可剥夺型内核:

     RTOS的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其他任务,这个是内核的多任务管理能力。多任务管理给人的感觉就好像芯片有多个CPU,多任务管理实现了CPU资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时应用。
     RTOS中的经典代表作:FreeRTOS,而FreeOS的内核是可剥夺型的,所以我们简单提一下什么是可剥夺型内核,关于FreeRTOS内核的详细内容我们会在后续的视频中专门讲解的。
     可剥夺内核顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。


2.1 FreeRTOS系统简介:

       FreeRTOS是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。FreeRTOS提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
       FreeRTOS是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的,FreeRTOS结构简洁,可读性很强!最主要的是非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。

为什么学FreeRTOS

1、因为FreeROTS开源。
2、FreeRTOS免费
3、FreeRTOS是很多第三方组件钦定的系统!

2.2 FreeRTOS相关资料查找:

1、FreeRTOS官网:http://www.freertos.org/。
2、开源电子网:www.openedv.com。
3、其他论坛。

FreeRTOS 移植

2.2.1 向工程中添加相应文件
1、添加FreeRTOS 源码
在基础工程中新建一个名为FreeRTOS 的文件夹,如图2.2.1.1 所示:


创建FreeRTOS 文件夹以后就可以将FreeRTOS 的源码添加到这个文件夹中,添加完以后如图2.2.1.2 所示:


在1.3.2 小节中详细的讲解过portable 文件夹,我们只需要留下keil、MemMang 和RVDS这三个文件夹,其他的都可以删除掉,完成以后如图2.2.1.3 所示:


2、向工程分组中添加文件
打开基础工程,新建分组FreeRTOS_CORE 和FreeRTOS_PORTABLE,然后向这两个分组中添加文件,如图2.2.1.4 所示:


分组FreeRTOS_CORE 中的文件在什么地方就不说了,打开FreeRTOS 源码一目了然。重点来说说FreeRTOS_PORTABLE 分组中的port.c 和heap_4.c 是怎么来的,port.c 是RVDS 文件夹下的ARM_CM3 中的文件,因为STM32F103 是Cortex-M3 内核的,因此要选择ARM_CM3中的port.c 文件。heap_4.c 是MemMang 文件夹中的,前面说了MemMang 是跟内存管理相关
的,里面有5 个c 文件:heap_1.c、heap_2.c、heap_3.c、heap_4.c 和heap_5.c。这5 个c 文件是五种不同的内存管理方法,就像从北京到上海你可以坐火车、坐飞机,如果心情好的话也可以走路,反正有很多种方法,只要能到上海就行。这里也一样的,这5 个文件都可以用来作为FreeRTOS 的内存管理文件,只是它们的实现原理不同,各有利弊。这里我们选择heap_4.c,至于原因,后面会有一章节专门来讲解FreeRTOS 的内存管理,到时候大家就知道原因了。这里就先选择heap_4.c,毕竟本章的重点是FreeRTOS 的移植。

3、添加相应的头文件路径
添加完FreeRTOS 源码中的C 文件以后还要添加FreeRTOS 源码的头文件路径,头文件路径如图2.2.1.5 所示:


头文件路径添加完成以后编译一下,看看有没有什么错误,结果会发现提示打不开“FreeRTOSConfig.h”这个文件,如图2.2.1.6 所示:


这是因为缺少FreeRTOSConfig.h 文件,这个文件在哪里找呢?你可以自己创建,显然这不是一个明智的做法。我们可以找找FreeRTOS 的官方移植工程中会不会有这个文件,打开FreeRTOS 针对STM32F103 的移植工程文件,文件夹是CORTEX_STM32F103_Keil,打开以后如图2.2.1.7 所示:


果然!官方的移植工程中有这个文件,我们可以使用这个文件,但是建议大家使用我们例程中的FreeRTOSConf.h 文件,这个文件是FreeRTOS 的系统配置文件,不同的平台其配置不同,但是我们提供的例程中的这个文件肯定是针对ALIENTEK 开发板配置正确的。这个文件复制到什么地方大家可以自行决定,这里我为了方便放到了FreeRTOS 源码中的include 文件夹下。FreeRTOSConfig.h 是何方神圣?看名字就知道,他是FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪的,关于FreeRTOS 的配置文件FreeRTOSConfig.h 后面也会有一章节来详细的讲解。到这里我们再编译一次,没有错误!如图2.2.1.8 所示:


如果还有错误的话大家自行根据错误类型查找和修改错误!

2.2.2 修改SYSTEM 文件
SYSTEM 文件夹里面的文件一开始是针对UCOS 而编写的,所以如果使用FreeRTOS 的话就需要做相应的修改。本来打算让SYSTEM 文件夹也支持FreeRTOS,但是这样的话会导致SYSTEM 里面的文件太过于复杂,这样非常不利于初学者学习,所以这里就专门针对FreeRTOS修改了SYSTEM 里面的文件。
1、修改sys.h 文件
sys.h 文件修改很简单,在sys.h 文件里面用宏SYSTEM_SUPPORT_OS 来定义是否使用OS,我们使用了FreeRTOS,所以应该将宏SYSTEM_SUPPORT_OS 改为1。

//0,不支持os
//1,支持os
#define SYSTEM_SUPPORT_OS 1 //定义系统文件夹是否支持OS
2、修改usart.c 文件
usart.c 文件修改也很简单,usart.c 文件有两部分要修改,一个是添加FreeRTOS.h 头文件,默认是添加的UCOS 中的includes.h 头文件,修改以后如下:
//如果使用os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" //os 使用
#endif
另外一个就是USART1 的中断服务函数,在使用UCOS 的时候进出中断的时候需要添加OSIntEnter()和OSIntExit(),使用FreeRTOS 的话就不需要了,所以将这两行代码删除掉,修改以后如下:
void USART1_IRQHandler(void) //串口1 中断服务程序
{
    u8 Res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        Res =USART_ReceiveData(USART1); //读取接收到的数据
        if((USART_RX_STA&0x8000)==0) //接收未完成
    {
    if(USART_RX_STA&0x4000) //接收到了0x0d
    {
        if(Res!=0x0a)USART_RX_STA=0; //接收错误,重新开始
        else USART_RX_STA|=0x8000; //接收完成了
    }
    else //还没收到0X0D
    {
        if(Res==0x0d)USART_RX_STA|=0x4000;
        else
        {
            USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
            USART_RX_STA++;
            if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
        }
    }
    }
}
}
3、修改delay.c 文件
delay.c 文件修改的就比较大了,因为涉及到FreeRTOS 的系统时钟,delay.c 文件里面有4个函数,先来看一下函数SysTick_Handler(),此函数是滴答定时器的中断服务函数,代码如下:
extern void xPortSysTickHandler(void);
//systick 中断服务函数,使用OS 时用到
void SysTick_Handler(void)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();
    }
}
FreeRTOS 的心跳就是由滴答定时器产生的,根据FreeRTOS 的系统时钟节拍设置好滴答定时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用FreeRTOS 的API 函数xPortSysTickHandler()。delay_init()是用来初始化滴答定时器和延时函数,代码如下:
//初始化延迟函数
//SYSTICK 的时钟固定为AHB 时钟,基础例程里面SYSTICK 时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK 的时钟频率改为AHB 的频率!
//SYSCLK:系统时钟频率
void delay_init()
{
    u32 reload;
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
    fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us 都需要使用
    reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M
    reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ 设定溢出
    //时间reload 为24 位寄存器,最大值:
    //16777216,在72M 下,约合0.233s 左右
    fac_ms=1000/configTICK_RATE_HZ; //代表OS 可以延时的最少单位
    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK 中断
    SysTick->LOAD=reload; //每1/configTICK_RATE_HZ 秒中断
    //一次
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}
前面我们说了FreeRTOS 的系统时钟是由滴答定时器提供的,那么肯定要根据FreeRTOS 的系统时钟节拍来初始化滴答定时器了,delay_init()就是来完成这个功能的。FreeRTOS 的系统时钟节拍由宏configTICK_RATE_HZ 来设置,这个值我们可以自由设置,但是一旦设置好以后我们就要根据这个值来初始化滴答定时器,其实就是设置滴答定时器的中断周期。在基础例程中滴答定时器的时钟频率设置的是AHB 的1/8,这里为了兼容FreeRTOS 将滴答定时器的时钟频率改为了AHB,也就是72MHz!这一点一定要注意!接下来的三个函数都是延时的,代码如下:
//延时nus
//nus:要延时的us 数.
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)
void delay_us(u32 nus)
{
    u32 ticks;
    u32 told,tnow,tcnt=0;
    u32 reload=SysTick->LOAD; //LOAD 的值
    ticks=nus*fac_us; //需要的节拍数
    told=SysTick->VAL; //刚进入时的计数器值
    while(1)
    {
        tnow=SysTick->VAL;
        if(tnow!=told)
        {
            //这里注意一下SYSTICK 是一个递减的计数器就可以了.
            if(tnow<told)tcnt+=told-tnow;
            else tcnt+=reload-tnow+told;
            told=tnow;
            if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
        }
    };
}
//延时nms,会引起任务调度
//nms:要延时的ms 数
//nms:0~65535
void delay_ms(u32 nms)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        if(nms>=fac_ms) //延时的时间大于OS 的最少时间周期
        {
            vTaskDelay(nms/fac_ms); //FreeRTOS 延时
        }
        nms%=fac_ms; //OS 已经无法提供这么小的延时了,
        //采用普通方式延时
    }
    delay_us((u32)(nms*1000)); //普通方式延时
}
//延时nms,不会引起任务调度
//nms:要延时的ms 数
void delay_xms(u32 nms)
{
    u32 i;
    for(i=0;i<nms;i++) delay_us(1000);
}
delay_us()是us 级延时函数,delay_ms 和delay_xms()都是ms 级的延时函数,delay_us()和delay_xms()不会导致任务切换。delay_ms()其实就是对FreeRTOS 中的延时函数vTaskDelay()的简单封装,所以在使用delay_ms()的时候就会导致任务切换。delay.c 修改完成以后编译一下,会提示如图2.2.2.1 所示错误:


图2.2.2.1 的错误提示表示在port.c、delay.c 和stm32f10x_it.c 中三个重复定义的函数:SysTick_Handler()、SVC_Handler()和PendSV_Handler(),这三个函数分别为滴答定时器中断服务函数、SVC 中断服务函数和PendSV 中断服务函数,将stm32f10x_it.c 中的三个函数屏蔽掉,如图2.2.2.2 所示:


再次编译代码,应该没有错误了,如果还是错误的话自行根据错误类型修改!至此,SYSTEM文件夹就修改完成了。

2.3 移植验证实验
2.3.1 实验程序设计
1、实验目的
编写简单的FreeRTOS 应用代码,测试FreeRTOS 的移植是否成功。鉴于大家还没正式学习FreeRTOS,可以直接将本实验代码复制粘贴到自己的移植工程中。
2、实验设计
本实验设计四个任务:start_task()、led0_task ()、led1_task ()和float_task(),这四个任务的任务功能如下:
start_task():用来创建其他三个任务。
led0_task ():控制LED0 的闪烁,提示系统正在运行。
led1_task ():控制LED1 的闪烁。
float_task():简单的浮点测试任务,用于测试STM32F4 的FPU 是否工作正常。
3、实验工程
FreeRTOS 实验2-1 FreeRTOS 移植实验。
4、实验程序与分析
●任务设置

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
/************************************************
ALIENTEK 战舰STM32F103 开发板 FreeRTOS 实验2-1
FreeRTOS 移植实验-库函数版本
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32 资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数
#define LED0_TASK_PRIO 2 //任务优先级
#define LED0_STK_SIZE 50 //任务堆栈大小
TaskHandle_t LED0Task_Handler; //任务句柄
void led0_task(void *p_arg); //任务函数
#define LED1_TASK_PRIO 3 //任务优先级
#define LED1_STK_SIZE 50 //任务堆栈大小
TaskHandle_t LED1Task_Handler; //任务句柄
void led1_task(void *p_arg); //任务函数
● main()函数
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
    delay_init(); //延时函数初始化
    uart_init(115200); //初始化串口
    LED_Init(); //初始化LED
    //创建开始任务
    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(); //开启任务调度
}
● 任务函数
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); //进入临界区
    //创建LED0 任务
    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);
    //创建LED1 任务
    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);
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL(); //退出临界区
}
//LED0 任务函数
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}
//LED1 任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}
测试代码中创建了3 个任务:LED0 测试任务、LED1 测试任务和浮点测试任务,它们的任务函数分别为:led0_task()、led1_task()。led0_task()和led1_task()任务很简单,就是让LED0 和LED1 周期性闪烁。由于我们只是用测试代码来测试FreeRTOS 是否移植成功的,所以关于具体的函数的调用方法这些不要深究,后面会有详细的讲解!

2.3.2 实验程序运行结果分析
编译并下载代码到STM32F103 开发板中,下载进去以后会看到LED0 和LED1 开始闪烁,
LED0 均匀闪烁,那是因为我们在LED0 的任务代码中设置好的LED0 亮500ms,灭500ms。
LED1 亮的时间短,灭的时间长,这是因为在LED1 的任务代码中设置好的亮200ms,灭800ms。

FreeRTOS模板

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS学习笔记——基础知识与移植(STM32F103) 的相关文章

  • 一起尝试写一个自己的小软件

    一起尝试写一个自己的小软件 xff0c 有时候写个小软件 xff0c 会耗费一两个小时 xff0c 有时候耗费几个小时 xff0c 甚至几天 xff0c 但是在写小软件的过程中 xff0c 咱们都是沉浸在软件写好后的美妙体验中 xff0c
  • 网页被挂马了怎么办呢

    首先 xff0c 咱们了解一下网页挂马是什么意思 xff1a 网页挂马指的是把一个木马程序上传到一个网站里面然后用木马生成器生一个网马 xff0c 再上到空间里面 xff01 再加代码使得木马在打开网页时运行 xff01 接下来讲怎么办 如
  • 公司里最看重的是发展机会

    公司里最看重的是发展机会 xff0c 而不是现在的工资 xff0c 这是很多老板都喜欢说的 说的多了 xff0c 咱么那就相信了 虽然说 xff0c 很大程度上 xff0c 今后的日子怎么过 xff0c 取决于现在的想法和奋斗 xff0c
  • 处在八零末期,九零早期,缝隙中的人

    处在八零末期 xff0c 九零早期 xff0c 缝隙中的人 思想既可以与八零年代的人相似 xff0c 又有九零年代那种无法脱掉的稚气 这就是89年 90年出生的人 的特性
  • 马上就下班回家了,让我再写一篇

    马上就下班回家了 xff0c 让我再写一篇 xff0c 写博客让我突然静下来了 同时都纷纷离开了 快了 xff0c 快了 xff0c 马上写好了
  • 我知道自己的未来需要什么

    我知道自己的未来需要什么 xff0c 现在的路就在眼前 xff0c 争取一把 xff0c 奋斗一段时间 xff0c 未来光明坦途正在招手 下班了 xff0c 下次再来
  • 走马观花之《视觉SLAM十四讲》

    1 视觉SLAM 系统概述 SLAM 是Simultaneous Localization and Mapping 的缩写 xff0c 中文译作 同时定位与地图构建 它是指搭载特定传感器的主体 xff0c 在没有环境先验信息的情况下 xff
  • 硬件工程师必会模块之MOS管构成的基本门逻辑电路—看芯片手册框图必备技能

    本文你可以获得什么 xff1f MOS管构成的缓冲器Buffer和漏极开路们OD门是数字电路非常重要的概念 xff0c 怎么构成的 xff1b 反相器 xff0c 线与逻辑怎么玩 xff0c 又怎么用呢 xff1f 根据原理图 xff0c
  • 关于信号量的作用范围

    最近在搞信号量的时候产生了怀疑 xff0c 信号量的作用范围和信号量在任务的位置时候有关系呢 xff1f 答案是有的 xff0c 其实信号量的作用范围是指的从信号量开始到程序的跳转点为止 xff0c 比如一个任务中 xff0c 把信号量放在
  • UNIX 环境高级编程之我见

    UNIX环境高级编程 xff08 第二版 xff09 xff08 人民邮电出版社 xff09 美 W Richard Stevens amp Stephen A Rago 著 本书的主要结构分为以下几个部分 xff1a xff08 1 xf
  • xShell连接ubuntu不成功

    操作环境 xff1a xShell6 43 vm15 43 ubuntu18 04 xShell中以root身份连接虚拟机中的ubuntu时 xff0c 连接不上 xff0c 见下图 xff1a 密码输入的也是对的 xff0c 也能够双向p
  • mac brew install

    brew cask install myprogram base darren 64 Darren 2 project brew cask install docker Error Unknown command cask brew ins
  • mac/linux 系统批量计算文件md5命令

    find type f print0 xargs 0 md5
  • 链表-设计链表

    leetcode 707 设计链表 注意 xff1a 面向对象的思想 这是创建一个自己的链表 xff0c dummyhead和 size初始化都在构造函数中 xff0c 同时自己的链表类也需要定义自己的节点 struct LinkNode链
  • KVM虚拟机使用桥接方式时和宿主机无法通信的解决方案

    KVM虚拟机使用桥接方式时和宿主机无法通信的解决方案 应用场景 虚拟机客户机安装完成后 xff0c 需要为其设置网络接口 xff0c 以便和主机网络 xff0c 客户机之间的网络通信 事实上 xff0c 如果要在安装时使用网络通信 xff0
  • android 电池充电状态记录

    摘抄源码记录下 http androidxref com 9 0 0 r3 xref frameworks native include batteryservice BatteryServiceConstants h This file
  • python 输入三个变量,然后按小到大输出(解析)

    python 实例解析 xff08 1 xff09 vim 2 python py x 61 int input 39 please input x 39 y 61 int input 39 please input y 39 z 61 i
  • Linux系统调用Hook姿势总结

    http www cnblogs com LittleHann p 3854977 html 主题 Linux 相关学习资料 http xiaonieblog com post 61 121 http hbprotoss github io
  • 利用WireShark进行DNS协议分析

    一 准备工作 系统是Windows 8 1Pro 分析工具是WireShark1 10 8 Stable Version 使用系统Ping命令发送ICMP报文 二 开始工作 打开CMD exe键入 ping www oschina net
  • DNS协议详解及报文格式分析

    DNS协议详解及报文格式分析 Posted on 2017 06 18 by Jocent No Comments 目录 一 DNS协议理论知识 1 1 域名结构1 2 域名服务器1 3 域名解析过程 二 DNS协议报文格式 2 1 头部2

随机推荐

  • 解密微信数据库文件解析

    图解说明 xff1a 微信大量数据存储在本地比如 xff1a 联系人 xff08 包含好友地区 电话 通过那种方式添加 xff09 聊天内容 xff08 图片 文字 语音 视频 位置 名片 其他app分享链接 xff09 聊天室 收藏信息
  • qgroundcontrol二次开发环境搭建

    参考考qgroundcontrol官方文档 xff0c 做一些准备工作 xff1a https dev qgroundcontrol com master en getting started index html 1 按官方文档下载qgr
  • Android通过注解来初始化控件

    Android通过注解来初始化控件 对于Android大神的思想与能力我只能膜拜与学习了 xff0c 这里就从大神哪里学来的通过注解来初始化控件简单的概述一下 xff0c 省去了那么繁琐的findViewById步骤 xff08 找到了还要
  • KEIL MDK 工程中头文件包含的路径详解

    xff08 参考工程详见https download csdn net download tianzhijiaoxin 87464281 xff09 文章目录 前言一 include lt h gt 与include 34 h 34 的区别
  • 51-单片机---定时器0和定时器1---8位自动重装载(模式2)-16位定时计数(模式1)

    16位定时计数 xff08 工作方式1 xff09 初始化函数 void timer init TMOD 61 0x01 TH0 61 0x4C TL0 61 0x00 EA 61 1 ET0 61 1 TR0 61 1 初始化定时器运行
  • 算法基础21-图的最短路问题通解

    最短路问题通解 单源最短路所有边权都是正数朴素Dijkstra算法堆优化版Dijkstra算法 存在负权边bellman fordspfaspfa判断是否存在负权环路 单源最短路小结 多源汇最短路floyd 总结 想一想各种最短路算法模版和
  • Visual Studio 2008学习过程(之二)与MATLAB混合编程

    Visual Studio 2008学习过程 之二 MATLAB混合编程 上一篇我写的是我初识VisualStudio2008的过程 后来我又用它开发了几个小程序 至于怎么做的 过两天我再写 这篇文章我就写写VS和MATLAB联合开发程序的
  • HIVE迁移教程X86架构到ARM架构(CPU:鲲鹏920)

    centos8的hive迁移教程 1安装新的centos8环境 2 安装实验所需软件 2 1 安装OpenJDK yum span class token function install span java 1 8 0 openjdk 配
  • C++滑动窗口算法

    滑动窗口算法在一个特定大小的字符串或数组上进行操作 xff0c 而不在整个字符串和数组上操作 xff0c 这样就降低了问题的复杂度 xff0c 从而也达到降低了循环的嵌套深度 如下题 给你两个长度相同的字符串 xff0c s 和 t 将 s
  • C++和js交互方案对比

    c 43 43 和js交互方案对比 一 xff1a nodejs技术 nodejs技术是基于V8引擎的一套前后端交互技术 nan h为c 43 43 提供了与js交互的一系列V8 API 参考链接 缺点 xff1a 在Node js中 xf
  • C++实现HTTP服务

    一个多平台的系统基本架构 xff08 如下图 xff09 xff0c 数据库部分我们以后可以使用HDFS和MapReduce进行分布式存储 xff0c 之前大致介绍了js和c 43 43 交互的几种方式对比 xff0c 考虑到拓展性和访问效
  • gstreamer获取视频采集卡的数据

    gstreamer获取视频采集卡的视频数据 gstreamer可以用于采集硬件视频数据 xff0c 转码 xff0c 播放 xff0c 传输等 xff0c 但由于框架相对于FFmpeg较为小众 xff0c 所以资料较少 xff0c 整理一份
  • 使用c++来实现一个简单的数据库功能

    使用c 43 43 来实现一个简单的文件数据库功能 功能点1 xff1a 建表 1 创建和表同名的文件 2 在文件中存储表的信息 xff0c 包括attribute的name xff0c 数量 xff0c 类型 xff0c 是否唯一 3 添
  • 【性能优化】cpu时间抖动问题的解决修复

    问题描述 xff1a 边缘设备的cpu在低占有率时 xff0c 进程运行时间抖动较大 xff0c 在高占有率时 xff0c 运行时间抖动更稳定 低占有率运行情况图 xff1a 相同处理逻辑循环中 xff0c 两次处理的时间间隔 xff1a
  • pointRCNN 结果可视化

    由于pointRCNN源码的训练和inference很详细 xff0c 但是没有可视化的代码 xff0c 本文介绍其3d框结果的可视化方法 1 跑通pointRCNN https github com sshaoshuai PointRCN
  • C/C++学习笔记——C提高: 函数指针和递归函数

    函数指针 函数类型 通过什么来区分两个不同的函数 xff1f 一个函数在编译时被分配一个入口地址 xff0c 这个地址就称为函数的指针 xff0c 函数名代表函数的入口地址 函数三要素 xff1a 名称 参数 返回值 C语言中的函数有自己特
  • 算法基础22-最小生成树

    最小生成树 primkruskal prim 链接 acwing上一个关于prim很好的题解 prim 算法干的事情是 xff1a 给定一个无向图 xff0c 在图中选择若干条边把图的所有节点连起来 要求边长之和最小 在图论中 xff0c
  • C/C++学习笔记——C提高:预处理

    预处理的基本概念 C语言对源程序处理的四个步骤 xff1a 预处理 编译 汇编 链接 预处理是在程序源代码被编译之前 xff0c 由预处理器 xff08 Preprocessor xff09 对程序源代码进行的处理 这个过程并不对程序的源代
  • C/C++学习笔记——C提高:动态库的封装和使用

    库的基本概念 库是已经写好的 成熟的 可复用的代码 每个程序都需要依赖很多底层库 xff0c 不可能每个人的代码从零开始编写代码 xff0c 因此库的存在具有非常重要的意义 在我们的开发的应用中经常有一些公共代码是需要反复使用的 xff0c
  • FreeRTOS学习笔记——基础知识与移植(STM32F103)

    1 1 前后台系统 xff1a 早期嵌入式开发没有嵌入式操作系统的概念 xff0c 直接操作裸机 xff0c 在裸机上写程序 xff0c 比如用51单片机基本就没有操作系统的概念 通常把程序分为两部分 xff1a 前台系统和后台系统 简单的