【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析

2023-05-16

目录

驱动原理分析

L293D功能分析

代码分析

驱动原理分析

小车采用两片L293D芯片控制四个车轮,原理图如下:

因为L293D可分别控制两路电机,为了方便理解L293D芯片的工作原理,拿L293D的一侧功能引脚举例说明,图1中U1芯片的左半侧是一路电机控制引脚,EN1是电机T1的使能端,IN1和IN2是电机的输入,OUT1和OUT2是电机的输出。如果将EN1置于高电平,电机就完全受IN1和IN2这两个引脚控制,即如果IN1为高,IN2为低电机全速正转,反之IN1为低,IN2为高电机全速反转。那么当引入EN1这个使能引脚之后,其逻辑关系如下:不管电机正转还是反转,EN1为高电平时,电机转速不受影响;但EN1为低电平时,输出处于高阻态,即不能输出控制电压,通过这个引脚可以控制小车的转速。

本实验原理图就U1为例,L293D芯片的EN1与EN2使是使能端,将EN1与EN2连接是为了使一路PWM同时控制两个电机(显然电机方向相同)。

为了方便更容易理解L293D这款驱动芯片,引用了L293D-DC-MOTOR这篇博文,具体内容如下:

L293D功能分析

L293D是一款双通道H桥电机驱动器,能够驱动一对DC电机或一个步进电机,这意味着它可以单独驱动最多两个电机,因此非常适合构建两轮机器人平台,芯片功能引脚分布如下,并对该芯片各模块功能进行分析:

电源

L293D电机驱动器IC实际上有两个电源输入引脚,即“Vcc1”和“Vcc2”。Vcc1用于驱动应为5V的内部逻辑电路,Vcc2是驱动H桥的电源,该电源可以为4.5V至36V,他们都共用一个地线。

输出引脚

L293D电动机驱动器的电动机A和B的输出通道引出到引脚 OUT1,OUT2 和 OUT3,OUT4。IC上的每个通道均可向直流电动机提供高达600mA的电流。

对于L293D的每个通道,有两种类型的控制引脚,这些引脚使我们可以同时控制直流电动机的速度和旋转方向。

方向控制

我们可以控制电动机是向前还是向后旋转,这些引脚实际上控制L293D的IC内部的H桥电路的开关,该IC的每个通道都有两个方向控制引脚。IN1,IN2引脚控制马达A的旋转方向,同时IN3,IN4控制马达B。

可以通过在这些引脚上施加逻辑高电平(5V)或逻辑低电平(0V/接地)来控制电机的旋转方向。下图说明了如何完成此操作。

速度控制

速度控制引脚即控制ENA和ENB的打开和关闭来控制电动机A和B的速度。将这些引脚拉至高电平将使电动机旋转,将其拉至低电平将使其停止。借助脉冲宽度调制(PWM),我们实际上可以控制马达的速度。

那么如何用程序实现呢,写程序之前首先要明白小车的四个电机的运行方式,根据上述原理图U1控制左边的前后电机;U2控制右面的前后电机。我们可以命名为左前电机为L_F_motor;左后电机为L_B_motor;右前电机为R_F_motor;右后电机为R_B_motor。根据上述接线方式,右前和右后,左前和左后的控制信号是一样的,我们可以得到在做方向运动时的电机转向如下图所示。

代码分析

我们根据上述规律编写代码:

首先建立一个全局变量的头文件:globalvariable.h

#ifndef __GLOBALVARIABLE_H //防止重复定义
#define __GLOBALVARIABLE_H
/**************头文件申明******************/
#include "stm32f10x.h"
/*********电机驱动GPIO相关宏定义**********/
/*********左侧双电机正转+反转GPIO相关宏定义**********/
#define L_MOTOR_F_GPIO        GPIOG      //left motor foreward
#define L_MOTOR_F_PIN         GPIO_Pin_11     
#define L_MOTOR_F_SET         GPIO_SetBits(L_MOTOR_F_GPIO , L_MOTOR_F_PIN)
#define L_MOTOR_F_RESET       GPIO_ResetBits(L_MOTOR_F_GPIO , L_MOTOR_F_PIN)

#define L_MOTOR_R_GPIO        GPIOD      //left motor reversal
#define L_MOTOR_R_PIN         GPIO_Pin_6     
#define L_MOTOR_R_SET         GPIO_SetBits(L_MOTOR_R_GPIO , L_MOTOR_R_PIN)
#define L_MOTOR_R_RESET       GPIO_ResetBits(L_MOTOR_R_GPIO , L_MOTOR_R_PIN)
/*********右侧双电机正转+反转GPIO相关宏定义**********/
#define R_MOTOR_F_GPIO        GPIOG      //right motor foreward
#define R_MOTOR_F_PIN         GPIO_Pin_9     
#define R_MOTOR_F_SET         GPIO_SetBits(R_MOTOR_F_GPIO , R_MOTOR_F_PIN)
#define R_MOTOR_F_RESET       GPIO_ResetBits(R_MOTOR_F_GPIO , R_MOTOR_F_PIN)

#define R_MOTOR_R_GPIO        GPIOD      //right motor reversal
#define R_MOTOR_R_PIN         GPIO_Pin_0     
#define R_MOTOR_R_SET         GPIO_SetBits(R_MOTOR_R_GPIO , R_MOTOR_R_PIN)
#define R_MOTOR_R_RESET       GPIO_ResetBits(R_MOTOR_R_GPIO , R_MOTOR_R_PIN)
/*********左侧PWM使能CPIO初始化**********/
#define L_MOTOR_PWM_GPIO        GPIOD      //right motor reversal
#define L_MOTOR_PWM_PIN         GPIO_Pin_4     
#define L_MOTOR_PWM_SET         GPIO_SetBits(R_MOTOR_R_GPIO , R_MOTOR_R_PIN)
#define L_MOTOR_PWM_RESET       GPIO_ResetBits(R_MOTOR_R_GPIO , R_MOTOR_R_PIN)

/*********右侧PWM使能CPIO初始化**********/
#define R_MOTOR_PWM_GPIO        GPIOD      //right motor reversal
#define R_MOTOR_PWM_PIN         GPIO_Pin_2     
#define R_MOTOR_PWM_SET         GPIO_SetBits(R_MOTOR_PWM_GPIO , R_MOTOR_PWM_PIN)
#define R_MOTOR_PWM_RESET       GPIO_ResetBits(R_MOTOR_PWM_GPIO , R_MOTOR_PWM_PIN)

/*********电机运动函数**********/
/*********左侧电机前进运动函数**********/
#define L_MOTOR_GO           L_MOTOR_F_SET; L_MOTOR_R_RESET
#define L_MOTOR_BACK         L_MOTOR_F_RESET; L_MOTOR_R_SET
#define L_MOTOR_STOP         L_MOTOR_F_RESET; L_MOTOR_R_RESET

/*********右侧电机前进运动函数**********/
#define R_MOTOR_GO           R_MOTOR_F_SET; R_MOTOR_R_RESET
#define R_MOTOR_BACK         R_MOTOR_F_RESET; R_MOTOR_R_SET
#define R_MOTOR_STOP         R_MOTOR_F_RESET; R_MOTOR_R_RESET

/*********PWM周期时间为50ms,最小分辨率为1ms,设置默认占空比为40。**********/
#define SPEED_DUTY 40/

extern unsigned char time_5ms;//5ms计数器,作为主函数的基本周期
extern unsigned char time_1ms;//1ms计数器,作为电机的基本计数器
extern unsigned int speed_count;//占空比计数器 50次一周期

根据上述头文件中定义的引脚,我们需要建立一个sys.c文件夹对上述底层驱动进行初始化。

sys.h很简单,主要有:

#ifndef __SYS_H
#define __SYS_H
#include "globalvariable.h"

void initsysblock(void)
void delay_init(void);
void delay_ms(unsigned int time);
void delay_us(unsigned int time);

#endif

sys.c如下

#include "sys.h"
/*********************************************************
名 称:void initsysblock(void)
功 能:外设底层驱动初始化函数
参 数:None
返回值:None
**********************************************************/
void initsysblock(void)
{
    /**************功能外设宏定义******************/
     GPIO_InitTypeDef           GPIO_InitStructure;
     NVIC_InitTypeDef           NVIC_InitStructure;
     TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;

    /**************程序上电先将GPIO设置为默认值******************/
    GPIO_DeInit(GPIOD);//恢复GPIO的相应寄存器为默认值
GPIO_DeInit(GPIOG);
    /**************程序上电先将定时器设置为默认值******************/
    TIM_DeInit(TIM2);
    /**************定时器时钟开启******************/ 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    /**************GPIO时钟开启******************/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG , ENABLE);
/**************四轮控制引脚GPIO的配置******************/   

    GPIO_InitStructure.GPIO_Pin   =     L_MOTOR_F_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(L_MOTOR_F_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   =     R_MOTOR_F_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(L_MOTOR_F_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   =     L_MOTOR_R_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(L_MOTOR_R_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   =     R_MOTOR_R_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(R_MOTOR_R_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   =     R_MOTOR_PWM_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(R_MOTOR_PWM _GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   =     R_MOTOR_PWM_PIN;
    GPIO_InitStructure.GPIO_Mode  =     GPIO_Mode_Out_PP;      
    GPIO_InitStructure.GPIO_Speed =     GPIO_Speed_2MHz;
    GPIO_Init(R_MOTOR_PWM _GPIO, &GPIO_InitStructure);

/**************中断的配置*******************/   
    NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


/********************定时器配置************************/    
//这个就是自动装载的计数值,由于计数是从0开始的,周期为100us
    TIM_TimeBaseStructure.TIM_Period = (100-1);//10kHz
    // 这个就是预分频系数,当由于为0时表示不分频所以要减1
    TIM_TimeBaseStructure.TIM_Prescaler =(72-1);//1MHz
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    //向上计数
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);    //写寄存器
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM2, ENABLE);  //计数器使能,开始工作

/********************相关延时函数************************/   
//主要利用系统滴答定时器,不占用定时器和CPU资源// 
void delay_init(void)
{
   SysTick->CTRL&=0xfffffffb;//控制寄存器,选择外部时钟即系统时钟的八分之一(HCLK/8;72M/8=9M)
}
/********************1us延时函数************************/    
void delay_us(u32 Nus)   
{   
SysTick->LOAD=Nus*9;          //时间加载    72M主频     
SysTick->CTRL|=0x01;             //开始倒数      
while(!(SysTick->CTRL&(1<<16))); //等待时间到达   
SysTick->CTRL=0X00000000;        //关闭计数器   
SysTick->VAL=0X00000000;         //清空计数器        
} 
/********************1ms延时函数************************/    

void delay_ms(u32 Nms)
{
	while(Nms--)
	{
		delay_us(1000);
	}
}

其次建立一个电机驱动头文件:motor.h

#ifndef __MOTOR_H_
#define __MOTOR_H_

extern unsigned int speed_count;//占空比计数器 50次一周期
extern char left_speed_duty;
extern char right_speed_duty;

void CarMove(void);
void CarGo(void);
void CarBack(void);
void CarLeft(void);
void CarRight(void);
void CarStop(void);
void MotorInit(void);
#endif

我们首先在头文件中声明几个变量用于后面电机驱动函数的编写

unsigned int speed_count=0;//占空比计数器50次一周期
char left_speed_duty=SPEED_DUTY;
char right_speed_duty=SPEED_DUTY;

unsigned char counter_5ms = 0;//5ms计数器,作为主函数的基本周期
unsigned char counter_1ms = 0;//1ms计数器,作为电机的基本计数器

char ctrl_comm = COMM_STOP;//控制指令
unsigned char continue_time=0;

并在globalvariable.h中对变量SPEED_DUTY赋值。

#define SPEED_DUTY 40//默认占空比 按1ms最小分辨率 周期50ms计算。

那么speed_count是如何计数的,主要是利用定时器TIM2进行50毫秒的周期计数。

那么问题又来了,我们所定义的counter_1ms在计数一次的时候是如何做到1毫秒计时的,我们在配置定时器时关于STM32定时器,TIMx(1-8),在库设置默认的情况下,都是72M的时钟;名为TIMx的有八个,其中TIM1和TIM8挂在APB2总线上,而TIM2-TIM7则挂在APB1总线上。其中TIM1&TIM8称为高级控制定时器(advanced control timer)。APB2可以工作在72MHz下,而APB1最大是36MHz。我们此前在sys.c文件中对TIM2进行了定时器中断的函数配置,终端周期是100us,计算公式为Tout=((arr+1)*(psc+1))/Tclk。也就是定时时间是重装载值和分频系数的乘积除以定时器的输入时钟频率。也就是100*72/72000000=100us。那么我们利用如下配置对TIM2中断处理函数TIM2_IRQHandler的进行编写,该函数主要实现50毫秒的计数。

void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
        counter_1ms++;
				if(counter_1ms>=10)//100usz计数一次,计数10次为1ms
				{
					counter_1ms = 0;
					speed_count++;
					counter_5ms++;
					if(speed_count >= 50)
					{
						speed_count = 0;
					}
					CarMove();
				}
    }
}

那么我们如何利用PWM来控制小车的运动呢?看下图:

通过这种方式我们就实了通过PWM控制L293D使能端对电机进行调速控制。

下面是电机驱动motor.c文件

#include "motor.h"
#include " globalvariable.h "
#include "stm32f10x.h"
/********************根据占空比驱动电机转动************************/    
void CarMove(void)
{   
L_MOTOR_PWM_SET;
R_MOTOR_PWM_SET;
	if(right_speed_duty > 0)//向前
	{
		if(speed_count < right_speed_duty)//speed_count在累加与设定值40进行比较,如果小于40,电机执行正转,否则停止。这里就是PWM的控制思想。
		{
			R_MOTOR_GO;
		}else                //停止
		{
			R_MOTOR_STOP;
		}
	}
else if (right_speed_duty < 0)//向后
	{
		if(speed_count < (-1)right_speed_duty)
		{
			R_MOTOR_BACK;
		}else                //停止
		{
			R_MOTOR_STOP;
		}
	}
	else                //停止
	{
		L_MOTOR_STOP;
	}
	if(left_speed_duty > 0)//向前
	{
		if(speed_count < left_speed_duty)
		{
			L_MOTOR_GO;
		}	else                //停止
		{
			L_MOTOR_STOP;
		}
	}
	else if(left_speed_duty < 0)//向后
	{
		if(speed_count < (-1)* left_speed_duty)
		{
			L_MOTOR_BACK;
		}	else                //停止
		{
			L_MOTOR_STOP;
		}
	}
	else                //停止
	{
		R_MOTOR_STOP;
	}

上述函数就是确定left_speed_duty和right_speed_duty的值与利用定时器产生的speed_count的进行比较来产生PWM波形控制小车四个电机的运行方式。speed_count是TIM2计时器每毫秒计数一次,50毫秒为一个周期循环计数,left_speed_duty和right_speed_duty的值则是初始赋予40,也就是占空比的设定。

下面根据上述运动方式对小车的运动函数进行定义,即前进左右四个轮子都正转,向后左右两个轮子都反转,左转左面轮子后转、右面轮子向前转,右转左面轮子向前、右面轮子向后转。

#define SPEED_DUTY 40//默认占空比 按1ms最小分辨率 周期50ms计算

/********************向前运动函数************************/    
void CarGo(void)
{
	left_speed_duty=SPEED_DUTY;
	right_speed_duty=SPEED_DUTY;
}

/********************向后运动函数************************/    
void CarBack(void)
{
	left_speed_duty=-SPEED_DUTY;
	right_speed_duty=-SPEED_DUTY;
}

/********************向左运动函数************************/    
void CarLeft(void)
{
	left_speed_duty=-20;
	right_speed_duty=SPEED_DUTY;
}

/********************向右运动函数************************/    
void CarRight(void)
{
	left_speed_duty=SPEED_DUTY;
	right_speed_duty=-20;
}

/********************停止运动函数************************/    
void CarStop(void)
{
	left_speed_duty=0;
	right_speed_duty=0;
}
/********************电机初始化************************/    
void MotorInit(void)
{
	MotorGPIO_Configuration();
	CarStop();
}

那么控制小车运动程序我们就分析完了,下节我们对小车的红外控制模块进行分析。

往期回顾:

一文看懂Modbus通信协议(上)

一文看懂数字PID

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

【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析 的相关文章

  • C#使用ProtoBuf

    1 Google ProtoBuf 经过测试 xff0c protobuf比json存储效率还是要高 xff0c 即时号称最快的fastjson也没有protobuf快 xff0c 这里为了使用 c 做一个客户端兼容 xff0c 所以也需要
  • 多线程如何实现高性能计数器(无锁)

    多线程协作免不了使用计数器 xff0c 通常的代码 xff0c c 43 43 一般会使用锁 xff0c 或者原子变量操作 xff1a std mutex mutexCounter int count void add std lock g
  • ubuntu18/20 下如何生成core文件

    ubuntu18 20 下如何生成core文件 一 设置 原理 xff1a https blog csdn net Sunnyside article details 118439302 原来在ubuntu14 ubuntu16上只需要一步
  • c++的字节序与符号位的问题

    看这样一道题 xff1a include lt stdio h gt int main void int w h int i 61 0xa1b2c3d4 char p 61 char amp i for int j 61 0 j lt 4
  • docker镜像之带vnc的ubuntu

    docker镜像 之 带vnc图形界面ubuntu 前言 xff1a 为了在图形界面中使用firefox xff0c 需要找一个带rdp或者vnc的ubuntu xff0c 最好是gnome的界面 xff0c 折腾了3天 xff0c 终于找
  • STM32中,关于中断函数调用全局变量的问题

    xfeff xfeff https blog csdn net leo liu006 article details 79334905 首先是问题的描述 xff1a 硬件单片机型号 xff0c STM32F103VET6 xff0c IDE
  • python使用selenium以及selenium-wire做质量与性能检测

    python天生就是适合用来做爬虫 xff0c 结合selenium真是如虎添翼 xff1b 1 安装库 pip install selenium pip install selenium wire 2 xff09 添加驱动 xff0c 比
  • 编写http workshop脚本从网页缓存里解析音乐

    前一篇文章 编写http workshop脚本从网站下载音乐 示范了如何使用HttpClient访问API 以及Json数据的解析 今天我们通过解析一个网页展示如何使用内置的LibXml2的功能解析HTML 提取我们关心的内容 这里随便搜了
  • pytorch环境搭建若干

    备注 xff1a 不要使用python3 11不支持 xff0c pip会说找不到合适的版本 xff1b python官网不提供旧版的下载了 xff0c 说是win7以后无法使用 xff0c 都是扯淡 xff0c 有其他地方可以下载pyth
  • ffmpeg常用方法

    FFmpeg 是一款开源的音视频处理工具 xff0c 可以处理各种格式的音视频文件 xff0c 并且可以进行格式转换 剪切 合并 添加水印等多种操作 下面是 FFmpeg 的一些常用命令及其用法 xff1a 视频转码 将一个视频文件转换为另
  • RFC2152 UTF-7 中文

    RFC2152 UTF 7 中文 翻译 xff1a 李静南 时间 xff1a 2006 03 29 EMAIL xff1a robin fox 64 sohu com 版权 xff1a 可以用于非商业用途自由转载 xff0c 但请保留本文档
  • 第九章0.4的CMakeLists.txt结构

    最开始看这一章的时候 xff0c 将CMakeLists txt部分跳过了 xff0c 没有看 后来看高博RGBD SLAM时候 xff0c 第一讲降到了cmake的用法 xff0c 发现有新的东西 xff0c 又回头看 xff1a 最原始
  • ROS 中setup.bash

    好久没写了 xff0c 最近搞了辆小车 xff0c 瞅了瞅ROS的相关内容 xff0c 没有写ROS的内容 xff0c 刚开始看 xff0c 写的话基本就成了书本粘贴 不过最近由ROS引出来的一些Linux相关的东西 xff0c 然后又回头
  • ros_hostname与ros_ip

    在ROS的环境变量中 xff0c 需要在 bashrc中设置的并不多 xff08 此处是指在wiki的基本教程中出现的 xff0c 大牛请无视 xff09 xff0c 大概只有三个 xff1a ROS MASTER URI ROS HOST
  • git图形化代码冲突处理

    当代码量少的时候使用 xff0c 使用vimdiff或者手动处理冲突 xff0c 都很方便 xff0c 但是当代码量大还是图形化处理更方便 xff0c 这里推荐使用kdiff3 首先下载kdiff3 xff0c 网上不好找的话 xff0c
  • Apache httpd 目录列表禁用配置(options indexes)

    Apache httpd服务器在缺省的情况下 xff0c 开启了基于目录列表的访问 xff0c 这是一个存在安全隐患的问题 xff0c 因此可以关闭这个功能 在Apache 2 4的版本中 xff0c 不在支持使用 indexes来配置 x
  • cmake学习笔记6-catkin的CmakeList.txt讲解

    https www jianshu com p 551d6949b49d 引用 cmake学习笔记 cmakelist txt创建项目示例 cmake的介绍和使用 Cmake实践 推荐cmake手册详解 严重推荐CMake构建系统的骨架 c
  • ROS中使用Intel RealSense D455或L515深度相机

    目的 在ROS平台上 xff0c 使用深度相机作为传感器设计自主避障机器人 1 安装驱动 测试环境 软件 xff1a Ubuntu 16 04 ROS Kinetic 硬件 xff1a Intel RealSense D455 或 L515
  • ROS机器人操作系统底层原理及代码剖析

    0 目的 本文介绍ROS机器人操作系统 xff08 Robot Operating System xff09 的实现原理 xff0c 从最底层分析ROS代码是如何实现的 1 序列化 把通信的内容 xff08 也就是消息message xff
  • RS232,RS485波形分析

    通过观察波形可以确定以下情况 xff1a 是否有数据接收或发送 xff1b 数据是否正确 xff1b 波特率是否正确 xff1b 一 串行数据的格式 异步串行数据的一般格式是 xff1a 起始位 43 数据位 43 停止位 xff0c 其中

随机推荐

  • GPU渲染管线之旅|05 图元处理、Clip/Cull, 投影和视图变换

    上一篇中我们讨论了关于 纹理和采样 xff0c 这一篇我们回到3D管线的前端 在执行完顶点着色之后 xff0c 就可以实际的渲染东西了 xff0c 对吗 xff1f 暂时还不行 xff0c 因为在我们实际开始光栅化图元之前 xff0c 仍然
  • 谈谈OpenCV中的四边形

    首先抛出一个问题 xff0c 给定一系列二维平面上的的点 xff0c 这些点是可以组成一个封闭的二维图形 因为这些点是矩形区域拍摄图像后识别得到的图形的边界点 xff0c 所以我们要抽象出来这个矩形 xff0c 也就是我们要反映出这个矩形
  • GPU渲染管线之旅|07 深度处理、模板处理

    在这一篇中 xff0c 我们来讨论Z pipline的前端部分 简称它为early Z 以及它是在光栅化中怎么起作用的 和上一篇一样 xff0c 本篇也不会按实际的管道顺序进行讨论 xff1b 我将首先描述基础算法 xff0c 然后再补充管
  • GPU渲染管线之旅|08 Pixel Shader

    在这一部分中 xff0c 我们来谈谈像素处理的前半部分 dispatch和实际的像素着色 事实上 xff0c 这部分是大多数图形开发者在谈到PS stage时所关心的内容 有关alpha blend和Late Z的内容则会下一篇文章中去探讨
  • MFC基于CSplitterWnd类的多窗口分割

    使用平台 xff1a win7 64bit 使用环境 xff1a VS2012 1 CSplitterWnd介绍 上图是从MSDN中截取的类的继承图表 xff0c CSplitterWnd类继承自CWnd类 这个类主要就是提供窗口分割的功能
  • OpenCV - 区域生长算法

    1 理论基础 区域生长算法的基本思想是将有相似性质的像素点合并到一起 对每一个区域要先指定一个种子点作为生长的起点 xff0c 然后将种子点周围领域的像素点和种子点进行对比 xff0c 将具有相似性质的点合并起来继续向外生长 xff0c 直
  • 不规则Contours内部像素的操作

    在findContours函数使用了之后 xff0c 有时候就会面临对Contours内部区域的访问 由于contours不一定是凸图形 xff0c 所以使用循环操作的时候总感觉不那么方便 比如在下图中 xff0c 已经使用findCont
  • ros代码中添加使用opencv库,cv::Mat和ros image之间的相互转换

    https blog csdn net sunyoop article details 78630024 ros中很多时候要用到图形处理 xff0c 这时就需要使用opencv库 xff0c 本篇主要将怎么在ros现成node上使用open
  • Ubuntu 16.04 使用

    这篇博客用来专门记录尝试搬迁工作环境到Linux下的使用笔记 xff0c 主要包含有常用软件的安装 xff0c 配置 1 安装输入法 ubuntu 16 04中支持ibus输入系统 1 系统 gt 首选项 gt IBus设置 在弹出的IBu
  • 牛顿迭代法求解方程

    说明 xff1a 该篇博客源于博主的早些时候的一个csdn博客中的一篇 xff0c 由于近期使用到了 xff0c 所以再次作一总结 原文地址 概述 牛顿迭代法 xff08 Newton s method xff09 又称为牛顿 拉夫逊 xf
  • OpenCV - 均值迭代分割

    题外话 之前在博客中写过一篇 区域生长 的博客 xff0c 区域生长在平时经常用到 xff0c 也比较容易理解和代码实现 xff0c 所以在很多情况下大家会选择这种方法 但是区域生长有一个最致命的点就是需要选取一个生长的种子点 为了交流学习
  • IMU原理及姿态融合算法详解

    IMU原理及姿态融合算法详解 一 组成 IMU全称是惯性导航系统 xff0c 主要元件有陀螺仪 加速度计和磁力计 其中陀螺仪可以得到各个轴的加速度 xff0c 而加速度计能得到x xff0c y xff0c z方向的加速度 xff0c 而磁
  • FrankMocap win10安装指导

    本文是相当于将github上frankmocap的安装指导进行了翻译 xff0c 增加了一下windows下安装遇到的坑以及注意事项 如果是linux系统应该安装官方的安装指导安装就可以 xff0c 可以直接参考官方安装指导 安装所有模块
  • ADRC学习(1)系统在调节过程中安排过渡过程的作用

    1 二阶系统的调节过程 考虑对于如下所示的二阶系统 x
  • 笔记本更换SSD后卡顿、假死、失去响应问题探究

    某些笔记本电脑将HDD更换为SSD后 xff0c 系统运行过程中会随机产生半分钟到一分钟的卡顿 xff08 假死 xff09 期间鼠标指针可以运动 xff0c 但所有程序均失去响应 xff0c 也无法打开新的程序 HDD硬盘指示灯常亮 xf
  • 机器人 齐次变换矩阵 位姿变换矩阵(RT矩阵) Matlab参数公式计算

    对于齐次位姿变换 xff08 RT矩阵 xff09 xff0c 有的时候手动计算公式参数太多比较麻烦 xff0c 因此利用matlab参量syms xff0c 可以方便一些 xff0c 可以用于计算机器人正运动学位姿矩阵的参数表示 xff0
  • UART串口校验方式(无校验、奇偶校验、固定校验)

    UART串口校验方式 xff08 奇偶校验 固定校验 无校验 xff09 串口通信校验方式奇偶校验位固定校验位 Stick 无校验位 校验位 xff1a 串口通信中的检错方式 串口在接收数据时 xff0c 如果无检验位 xff0c 则只要检
  • 更改LXDE的语言为中文

    之前给旧笔记本安装了Debian8 43 LXDE嘛 xff0c 运行比较流畅 安装过程中本想选择中文的 xff0c 但是安装界面中旧有中文乱码 xff0c 所以还是选了英语 等装好了系统 xff0c 把apt update 43 upgr
  • 干掉Nouveau安装Linux Nvidia显卡驱动

    https blog csdn net misiter article details 7652731 干掉Nouveau安装Linux Nvidia显卡驱动 首先说明下什么是Nouveau xff0c 为什么有些系统安装N卡驱动的时候会提
  • 【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析

    目录 驱动原理分析 L293D功能分析 代码分析 驱动原理分析 小车采用两片L293D芯片控制四个车轮 xff0c 原理图如下 xff1a 因为L293D可分别控制两路电机 xff0c 为了方便理解L293D芯片的工作原理 xff0c 拿L