STM8S 红外解码+低功耗处理

2023-05-16

NEC协议

红外遥控的编码目前广泛使用的是:NEC ProtocolPWM(脉冲宽度调制)和 PhilipsRC-5 ProtocolPPM(脉冲位置调制),下面是 NEC 协议的特征:

  1. 8 位地址和 8 位指令长度(控制码);
  2. 地址和命令 2 次传输(确保可靠性)
  3. PWM 脉冲位置调制,以发射红外载波的占空比代表 “0” 和 “1” ;
  4. 载波频率为 38Khz
  5. 位时间为 1.125ms2.25ms

NEC码的位定义:

  • 一个脉冲对应 560us 的连续载波
  • 一个逻辑 1 传输需要 2.25ms560us脉冲+1680us 低电平=2240us)
  • 一个逻辑 0 的传输需要 1.125ms560us 脉冲+560us 低电平=1120us)

红外接收头端的信号为:

  • 收到脉冲的时候为低电平,在没有脉冲的时候为高电平(即与发出的NEC码反向)
  • 逻辑 1 ( 560us 低+1680us 高)
  • 逻辑 0 ( 560us 低+560us 高)
    NEC码位定义

NEC 遥控指令的数据格式为:同步码头地址码地址反码控制码控制反码。从红外接收头端的角度来看:

  1. 同步码:由一个 9ms 的低电平和一个 4.5ms 的高电平组成
  2. 地址码地址反码:8位数据,遥控器的地址码要与红外接收头端的地址码要对应?
  3. 控制码控制反码:8位数据,键值相关
  4. 按照低位在前高位在后的顺序发送
  5. 采用反码是为了增加传输的可靠性(可用于校验)

以正点原子的STM32开发板为例,配带的遥控器的地址码为0x00:
红外波形

  • 地址码为0
  • 控制码为0x15(从接收端来看)
  • 连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平+97.94ms 高电平组成=110ms),如果在一帧数据发送完毕之后,按键仍然没有放开,则发射重复码,即连发码,可以通过统计连发码的次数来标记按键按下的长短/次数。

项目实践中的NEC码

一般给出的码值表是从发送端的角度来看的,而客户码实际上就是地址码+地址反码这一项(不一定构成反码),也就是说如果从接收端接收到的波形来看,83F4对应的是C12F(先发低位,再发高位);OK键15对应A8
遥控器码值

对应原理图

对应的原理图如下:
在这里插入图片描述

软件设计思路一

仿正点原子的做法,该方式不适合要做低功耗模式的需求:

  • 开启定时器对应通道输入捕获功能,默认上升沿捕获。定时器的计数频率为1MHz,自动装载值为10000,也就是溢出时间为10ms
  • 开启定时器 输入捕获中断溢出/更新中断,当捕获到上升沿产生捕获中断,当定时器计数溢出,产生更新中断 。
  • 当捕获到上升沿的时候,设置捕获极性为下降沿捕获(为下次捕获下降沿做准备),然后设置定时器计数值为0(清空定时器),同时设置变量RmtSta的为4值为1,标记已经捕获到上升沿
  • 当捕获到下降沿的时候,读取定时器的值赋给变量Dval,然后设置捕获极性为上升沿捕获(为下次捕获上升沿做准备),同时对变量RmtSta的位4进行判断:如果RmtSta位4为1,说明之前已经捕获到过上升沿,那么对Dval进行判断,300-800(560)之间,说明接收到的是数据0;1400-1800(1680)之间说明接收到的数据为1;2200-2600(2500),说明是连发码;4200-4700(4500)说明为同步码;分析后甚至相应的标志位
  • 如果是定时器发生溢出中断,那么分析,如果之前接收到了同步码,并且是第一次溢出,标记完成一次按键信息采集(有两种情况,情况1:接收完码后一直处于高电平后产生溢出;情况2:处于连发码中97.94ms高电平这段时间产生溢出,正点原子例程用是否>130ms来判断是处于两种情况中的哪一种)
  • 接收码值的时候采用的是左移的方式,跟接收端看到的波形数值是一致的,所以是遥控器码值的反码

定时器捕获 + 外部中断(低功耗) 的方式时,会产生问题,猜测是在软件优先级一样的情况下,硬件优先级(根据中断向量表判断)高的外部中断常常打断了定时器的捕获,所以造成了有时解不了码的问题。

remote.h代码

#ifndef _REMOTE_H_
#define _REMOTE_H_

#include "stm8s.h"

#define REMOTE_IDH  0x0C
#define REMOTE_IDL  0xF3
extern u8 RmtCnt;//按键按下的次数
void Clk_Init(void);
void Remote_Init(void);
u8 Remote_Scan(void);

#endif

remote.c代码

#include "remote.h"

//选用16MHz的HSI作为主时钟源
void Clk_Init(void){

    CLK_DeInit();//设置为默认值
    CLK_HSICmd(ENABLE);//启用HSI
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//HSI分频
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);//CPU分频
}

//初始化PD3为浮空输入
void IR_GPIO_Init(void){

    GPIO_DeInit(GPIOD);//恢复指定端口
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);//设置PD3为浮空输入无中断
    
}

void TIM2_Init(void){
    
    TIM2_DeInit();
    TIM2_TimeBaseInit(TIM2_PRESCALER_16, 10000); //最大10ms溢出,1us加1,只有向上计数
    TIM2_ARRPreloadConfig(ENABLE);
    //TIM2_ClearFlag(TIM2_FLAG_UPDATE);//清除更新标志
    TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);//允许更新/溢出中断
    //Send_Str("TIM2_Cmd before \n");
    TIM2_Cmd(ENABLE);//开启定时器
    //Send_Str("TIM2_Cmd after \n");
    //TIM2_UpdateRequestConfig(TIM2_UPDATESOURCE_REGULAR);//中断源选择为只有溢出才能触发
    //TIM2_GenerateEvent(TIM2_EVENTSOURCE_UPDATE);//产生更新事件,不触发中断(此处即更新了预分频器)
    
    enableInterrupts(); //开启中断
    
    //CH2、上升沿捕获、IC2映射在TI2FP2上、捕获预分频为1、无滤波器且采样率=主时钟频率
    //TIM2_PWMIConfig(TIM2_CHANNEL_2, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0x00);
    //CH2、上升沿捕获、IC2映射在TI2FP2上、捕获预分频为1、无滤波器且采样率=主时钟频率
    TIM2_ICInit(TIM2_CHANNEL_2, TIM2_ICPOLARITY_RISING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0x00);
    TIM2_ITConfig(TIM2_IT_CC2, ENABLE);//捕捉比较2中断使能
    TIM2_ClearITPendingBit(TIM2_IT_CC1);
    TIM2_ClearFlag(TIM2_FLAG_CC1);
    //TIM2_CCxCmd(TIM2_CHANNEL_2, ENABLE);//输入捕获/比较输出使能
    
}

//TIM2为输入捕获
void Remote_Init(){
  
    IR_GPIO_Init();
    TIM2_Init();
    //printf("Remote Init \n");
}


//RmtSta来标识遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留	
//[4]:标记上升沿是否已经被捕获								   
//[3:0]:溢出计时器
u8 	RmtSta=0;	  	  
u16 Dval;		//下降沿时计数器的值
u32 RmtRec=0;	//红外接收到的数据	   		    
u8  RmtCnt=0;	//按键按下的次数	

/**
  * @brief Timer2 更新/上溢出/刹车 中断程序.
  * @param  None
  * @retval None
  */
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13){
  

    if(RmtSta&0x80){//RmtSta[7]是否置1,则上次有数据(引导码)被接收到了
    	
        RmtSta&=~0X10;//取消上升沿已经被捕获标记(将RmtSta[4]置0)
        if((RmtSta&0X0F)==0X00)//对RtmSta[3:0]进行判断,为0代表第一次溢出
            RmtSta|=1<<6;	//标记已经完成一次按键的键值信息采集(将RmtSta[6]位置1)
        if((RmtSta&0X0F)<14){//高电平持续时间<130ms,可能还处于连发码中的97.94ms高电平阶段
            RmtSta++;
        }else{//如果超过130ms,就表示遥控器上按键已经松开了
        
            RmtSta&=~(1<<7);					//清空引导标识
            RmtSta&=0XF0;						//清空计数器	
        }								 	   	
   }
   TIM2_ClearFlag(TIM2_FLAG_UPDATE);//清除更新标志
   TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
   
}
 
 

/**
  * @brief Timer2 捕获/比较 中断程序.
  * @param  None
  * @retval None
  */
INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14){
    
    BitStatus bs;
    bs = GPIO_ReadInputPin(GPIOD, GPIO_PIN_3);//读PD3的输入电平状态
    if (bs){//上升沿捕获
        TIM2_OC2PolarityConfig(TIM2_OCPOLARITY_LOW);//改为下降沿捕获
        TIM2_SetCounter(0x0000);//清空定时器的值
        RmtSta|=0X10;//RmtSta[4]位置1 标记上升沿已经被捕获 
        
    }else{//下降沿捕获
        Dval = TIM2_GetCounter();//读取CCR2也可以清CC2IF捕获标志位
        TIM2_OC2PolarityConfig(TIM2_OCPOLARITY_HIGH);//改为上升沿捕获
        if(RmtSta&0x10){//完成一次高电平捕获(如果RmtSta[4]为1)
            
            if(RmtSta&0X80){//接收到了引导码(如果RmtSta[7]为1)
                
                if(Dval>300&&Dval<800){			//560为标准值,560us(NEC中的0位)
                
                    RmtRec<<=1;					//将RmtRec这个数左移一位.这里采用的是低位在前,高位在后的算法
                    RmtRec|=0;					//接收到0
                    
                }else if(Dval>1400&&Dval<1800){	//1680为标准值,1680us(NEC中的1位)
                
                    RmtRec<<=1;					//左移一位.
                    RmtRec|=1;					//接收到1
                    
                }else if(Dval>2200&&Dval<2600){	//2500为标准值2.5ms,得到按键键值增加的信息(连发码)
                
                    RmtCnt++; 					//按键次数增加1次
                    RmtSta&=0XF0;				//清空计时器
                    
                }
            }else if(Dval>4200&&Dval<4700){		//4500为标准值4.5ms(引导码)
                RmtSta|=1<<7;					//RmtSta[7]位置1,标记成功接收到了引导码
                RmtCnt=0;						//清除按键次数计数器
                
            }
       }
       RmtSta&=~(1<<4);//RmtSta[4]位置0,即清除上升沿捕获标志
       
    }
    TIM2_ClearITPendingBit(TIM2_IT_CC2);
    
}

//处理红外键盘
//返回值:
//0,没有任何按键按下
//其他,按下的按键键值.
u8 Remote_Scan(void){        
	u8 sta=0;       
    u8 t1,t2;  
   
	if(RmtSta&(1<<6))//得到一个按键的所有信息了(RmtSta[7]位是否为1)
	{ 
	    t1=RmtRec>>24;			//得到地址码(u32的RmtRec码右移24位,只保留地址码的8位)无符号
	    t2=(RmtRec>>16)&0xff;	//得到地址反码(右移16位后只保留低8位)
 	    if((t1==REMOTE_IDH)&&t2==REMOTE_IDL)//检验遥控识别码(ID)及地址 
	    { 
	        t1=RmtRec>>8;//得到控制码
	        t2=RmtRec; 	//得到控制反码
	        if(t1==(u8)~t2)sta=t1;//键值正确
		}   
		if((sta==0)||((RmtSta&0X80)==0))//按键数据错误/遥控已经没有按下了
		{
		 	RmtSta&=~(1<<6);//清除接收到有效按键标识(RmtSta[7]位设为1)
			RmtCnt=0;		//清除按键次数计数器
		}
	}  
    return sta;
}

main.c代码

#include "stm8s.h"
#include "stdio.h"
#include "remote.h"
#include "uart.h"
#include "led.h"
#include "delay.h"
#include "gpio_init.h"

void main(void)
{
    
    u8 key;
    //u8 *str=0;
    Clk_Init();//主时钟初始化
    //UART_Init();//初始化串口设置 
    //LED_init();
    init_TIM1();
    Remote_Init();//IR解码涉及相关的初始化
    Default_GPIO_Init();
	//printf("all init \n");
    
    
    while(1){
        if(!GPIO_ReadInputPin(GPIOC, GPIO_PIN_6)){
            key=Remote_Scan();
            if(key&&RmtCnt==1){
                //printf("Number of key repeats:%d \n",RmtCnt);
                switch(key){
                    case 0:
                      //printf("str=ERROR \n");
                      break;
                    case 0x8A:
                      //printf("Press Power \n");
                      GPIO_WriteReverse(GPIOD, GPIO_PIN_5);
					  //LED_Reverse();
                      Delay100ms(20);//这里是delay.c中的函数
					  //LED_Reverse();
                      GPIO_WriteReverse(GPIOD, GPIO_PIN_5);
                      break;
                }    
            }

        }
        
    }
    
}

软件设计思路二

采用外部中断的方式来做,适合做低功耗模式,但没做对连发码处理。

  • 具体思路:将IR接收脚设置为下降沿触发,解码的整个过程都在中断服务函数里搞,高低电平的持续时间是在中断函数中通过等待IR接收脚的电平状态翻转得到的。
  • 接收码值的时候采用的是右移的方式,所以得到和遥控器的码值一致
  • stm8在进入中断服务函数时,不用对标志位进行清零,会自动进行清零
    在这里插入图片描述

remote.h代码

#ifndef _REMOTE_H_
#define _REMOTE_H_

#include "stm8s.h"

#define REMOTE_IDH  0x30
#define REMOTE_IDL  0xCF

extern u8 IR_Data[4];//存放红外线解码接收的数据
extern bool IR_State;//FALSE表示未接收到数据,TRUE表示接收到数据

void Clk_Init(void);
void Remote_Init(void);
u8 getKey(void);

#endif

remote.c代码

#include "remote.h"

u8 IR_Data[4];//记录地址码、地址反码、控制码、控制反码
bool IR_State;//TRUE表示接收完一个码值,FALSE表示没接收完
BitStatus NEC_IR;//对应IR接收脚的电平状态,后面没用上
u16 x;//保存定时器的数值

//选用1MHz的HSI作为主时钟源
void Clk_Init(void){

    CLK_DeInit();//设置为默认值
    CLK_HSICmd(ENABLE);//启用HSI
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//HSI分频 fMASTER
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV16);//CPU分频 fCPU
}

//初始化PD3为浮空输入
void IR_GPIO_Init(void){

    EXTI_DeInit();
    GPIO_DeInit(GPIOD);//恢复指定端口
    //GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);//设置PD3为浮空输入无中断
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_IN_FL_IT);//设置PD3为浮空输入开启中断
    EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_FALL_ONLY);//仅下降沿触发
   
}

void TIM2_Init(void){
    
    TIM2_DeInit();
    TIM2_TimeBaseInit(TIM2_PRESCALER_16, 65535); //最大10ms溢出,1us加1,只有向上计数;计数最大值对应自动装载值
    TIM2_ARRPreloadConfig(ENABLE);//直到更新事件后,ARR预装载寄存器的值才会被拷贝到影子寄存器中
    
    //TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);//允许更新/溢出中断
    //TIM2_Cmd(ENABLE);//开启定时器
    //enableInterrupts(); //开启中断
}

//TIM2为输入捕获
void Remote_Init(){
  
    IR_GPIO_Init();
    TIM2_Init();
    //printf("Remote Init \n");
}

//函数功能:测量高电平时间
u16 IR_GetTime_H(void){
    
    TIM2_SetCounter(0);//清空定时器的值
    TIM2_Cmd(ENABLE);//开启定时器
    while(GPIO_ReadInputPin(GPIOD, GPIO_PIN_3)){}//等待高电平结束
    x=TIM2_GetCounter();
    TIM2_Cmd(DISABLE);//关闭定时器
    return x;
    
}

//函数功能:测量低电平时间
u16 IR_GetTime_L(void){
    
    TIM2_SetCounter(0);//清空定时器的值
    TIM2_Cmd(ENABLE);//开启定时器
    while(!GPIO_ReadInputPin(GPIOD, GPIO_PIN_3)){}//等待低电平结束
    x=TIM2_GetCounter();
    TIM2_Cmd(DISABLE);//关闭定时器
    
    return x;
}

u8 getKey(void){
    u8 key=0;
    if((IR_Data[0]==REMOTE_IDH)&&IR_Data[1]==REMOTE_IDL){
        if(IR_Data[2]==(u8)~IR_Data[3]) key=IR_Data[2];//键值正确
    }
    return key;
}

//外部中断PD中断服务函数
INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6){
    
    u16 time;
    u8 i,j,data=0;
    
    //stm8自动清除中断标志位,所以此处没写
    
    
    //NEC_IR = GPIO_ReadInputPin(GPIOD, GPIO_PIN_3);
    
    time=IR_GetTime_L();//得到低电平时间
    if(time<7000||time>10000)return; //标准时间: 9000us
    time=IR_GetTime_H();得到高电平时间
    if(time<3000||time>5500)return;  //标准时间4500us
    
    
    //正式解码NEC协议
    for(i=0;i<4;i++)
    {
        for(j=0;j<8;j++)
        {
             time=IR_GetTime_L();       //得到低电平时间
             if(time<400||time>700)return;    //标准时间: 560us
             
             time=IR_GetTime_H();       //得到高电平时间
             if(time>1400&&time<1800)         //数据1 1680us
             {
                data>>=1;
                data|=0x80;
             }
             else if(time>400&&time<700)   //数据0 560us
             {
                data>>=1;
             }
             else return;
        }
        IR_Data[i]=data; //存放解码成功的值
    }
    
    //解码成功
    IR_State=TRUE;
}

main.c代码

#include "stm8s.h"
#include "stdio.h"
#include "remote.h"
#include "uart.h"
#include "led.h"
#include "delay.h"
#include "gpio_init.h"


void main(void)
{
    u8 key;
    //bool Power_Over_Flag=FALSE;
    //u8 *str=0;
    Clk_Init();//主时钟初始化
    
    //LED_init();
    init_TIM1();
    Remote_Init();//IR解码涉及相关的初始化
    UART_Init();//初始化串口设置
    enableInterrupts(); //开启中断
    
    Default_GPIO_Init();
	printf("all init \n");
    
    while(1){
       
        if(!GPIO_ReadInputPin(GPIOC, GPIO_PIN_6)){
            
            if(IR_State){
                IR_State=FALSE;
                key=getKey();
                switch(key){
                    case 0:
                        printf("other remote \n");
                        break;
                    case 0x51:
                        printf("Press Power \n");
                        GPIO_WriteReverse(GPIOD, GPIO_PIN_5);
                        //LED_Reverse();
                        Delay100ms(20);
                        //LED_Reverse();
                        GPIO_WriteReverse(GPIOD, GPIO_PIN_5);
                        //Power_Over_Flag=TRUE;
                        break;
                
                }
            }
            
        }
        halt();
    }
    
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM8S 红外解码+低功耗处理 的相关文章

  • ros多线程管理

    单线程Spinning ros spin 是最简单的单线程自旋 它会一直调用直到结束 用法 ros spin ros spinOnce 另一个单线程spinning是ros spinOnce 它定期调用等待在那个点上的所有回调 用法 ros
  • (每日一读2019.10.24)一种基于通用优化方法的多传感器全局里程计估计框架(VINS-Fusion)

    参考博文 萌新学VINS Fusion 一 特征跟踪 萌新学VINS Fusion 二 特征跟踪 摘要 精确的状态估计是自主机器人的一个基本问题 为了实现局部精确和全局无漂移状态估计 通常将具有互补特性的多个传感器融合在一起 局部传感器 摄
  • (每日一读2019.10.25)一种基于通用优化方法的多传感器局部里程计估计框架(VINS-Fusion)

    摘要 为了提高机器人的鲁棒性和自主性 越来越多的传感器被安装在机器人上 我们已经看到了不同平台上安装的各种传感器套件 例如地面车辆上的立体摄像机 手机上带有IMU 惯性测量单元 的单目摄像机以及空中机器人上带有IMU的立体摄像机 虽然过去已
  • Gazebo模型下载以及配置--解决Gazebo黑屏原因

    前往ExBot ROS专区下载Gazebo模型 https bitbucket org osrf gazebo models downloads 下载后把文件放在 gazebo下的models文件夹中 span class token fu
  • 相机内外参数以及畸变参数

    关于大佬们的一些见解 下面是引用知乎的一段文字 xff1a 我们从单目视觉说起 平时我们都说要做视觉识别 测量云云 xff0c 然后我们就会去拍照 xff0c 再对数字图像做各种处理 xff0c 颜色处理 灰度化 滤波 边缘检测 霍夫变换
  • cmake学习4--自定义编译选项

    CMake 允许为项目增加编译选项 xff0c 从而可以根据用户的环境和需求选择最合适的编译方案 例如 xff0c 可以将 MathFunctions 库设为一个可选的库 xff0c 如果该选项为 ON xff0c 就使用该库定义的数学函数
  • ROS与C++学习1

    ROS与C 入门教程 构建工作空间 构建Catkin包 搭建开发环境 catkin make 编写简单发布节点和订阅节点 编写简单服务端和客户端 使用类方法作为回调函数 使用Timers类 编写高级的发布器和订阅器 Callbacks和Sp
  • IAR的UI界面优化

    显示行数 Tools Options 点击 Editor Tab size xff1a 设置Tab键占用多少个空格Indent size xff1a 应该是设置过行时缩进多少个空格Insert tab xff1a 选了之后在删除Tab时 x
  • MYNTEYE小觅双目摄像头深度版+VINS测试

    小觅双目深度版性能分析 今年 xff08 18年 xff09 11月9号小觅智能科技的深度版双目相机上市 xff0c 于是我在12月初花了2999软妹币购买了120度视角的相机 其中我比较感兴趣的是 双目 43 惯导 43 结构光 的多传感
  • QT+ROS开发

    Qt Creator for ROS 如果想在Qt上进行ros包的开发和GUI界面开发 建议采用下面的方法 http fumacrom com 1mipW Setup Qt Creator for ROS Setup Ubuntu to a
  • PX4、APM无人机仿真连接QGC地面站记录(udp连接、更改home点等)

    文章目录 一 PX41 gazebo 仿真2 连接地面站3 更改 Home点 二 APM 仿真1 执行仿真指令2 连接地面站3 更改 Home 点 本文仅记录仿真指令 xff0c 搭建安装不在此 一 PX4 首先给飞控源码和子目录权限 sp
  • LeetCode 解题笔记(一)总

    文章目录 一 常用技巧二 常用翻译三 题目x 其他9 回文数 2021 12 0911 盛最多水的容器 2022 01 0515 三数之和 2022 01 14 17 电话号码的字母组合 2022 01 1520 有效的括号 2021 12
  • LeetCode 解题笔记(二)数组篇

    文章目录 一 基础篇26 删除排序数组中的重复 2022 01 16122 买卖股票的最佳时机 II 2022 01 17189 轮转数组 2022 01 18217 存在重复元素 2022 01 19136 只出现一次的数字 2021 1
  • LeetCode 解题笔记(四)链表

    文章目录 一 总结二 题目237 删除链表中的节点 xff08 2022 03 10 xff09 19 删除链表的倒数第 N 个结点 xff08 2022 03 11 xff09 206 反转链表 xff08 2022 03 18 xff0
  • QT Quick QML 实例之 Popup 弹出界面

    QT Quick QML 实例之 Popup 弹出界面 一 演示二 实现过程1 居中弹出2 正下方弹出 所有的热爱都要不遗余力 xff0c 真正喜欢它便给它更高的优先级 xff0c 和更多的时间吧 xff01 GIT工程文件在这里 QmlL
  • QGC(GGroundControl) 系统核心架构图

    关于QGC地面站其它文章请点击这里 QGC地面站 UML 核心类图 xff1a xff08 点击图片放大看效果更好 xff09 核心系统分析图 xff1a xff08 点击图片放大看效果更好 xff09 工程结构 xff1a 整个 QGC
  • Qt 国际化翻译,函数外部字符串、Map 翻译(QT_TRANSLATE_NOOP)

    文章目录 1 Qt 的翻译流程2 利用 QT TRANSLATE NOOP 翻译 GitHub 源码 QmlLearningPro xff0c 选择子工程 xff1a TranslationsDemo pro QML 其它文章请点击这里 Q
  • IAR新建工程

    下载库函数 本文介绍基于 IAR 43 官方标准固件库 xff0c 来新建 STM8S003F 工程 xff0c STM8S 的标准固件库可以到 ST 的官方网站中找到并下载 xff1a ST官网 1 在搜索栏上搜索 STM8S003F x
  • RTSP 推流和拉流记录(运行代码)

    文章目录 1 RTSP 推流2 RTSP 拉流 1 RTSP 推流 用C 43 43 11 实现的RTSP服务器和推流器 xff0c 链接如下 RtspServer GitHub原地址 xff1a https github com PHZ7
  • FFmpeg 中 RTSP推流桌面和Android设备延时测试

    文章目录 1 FFMPEG 推流 xff1a 1 1 FFmpeg 源码准备1 2 RTSP 推流服务器 2 执行流程2 1 启动服务器2 2 执行桌面推流2 3 播放 3 安卓测试 1 FFMPEG 推流 xff1a 1 1 FFmpeg

随机推荐