嵌入式学习笔记——STM32的USART收发字符串及串口中断

2023-05-16

USART收发字符串及串口中断

  • 前言
  • 字符串的收发
    • 发送一个字符串
    • 接收字符串
      • 需求
    • 利用串口实现printf
  • 中断
    • 中断是什么
    • 串口的接收中断以及空闲中断
      • 实现代码
      • 实现效果
  • 总结
  • M4系列目录

前言

上一篇中,介绍了串口收发相关的寄存器,通过代码实现了一个字节的收发,本文接着上面的内容,通过功能函数实现字符串的收发,然后引入中断解决收发过程中while()死等的问题。

字符串的收发

发送一个字符串

根据昨天的字符发送函数,只需要稍作修改即可实现发送函数了,一个字符串的结尾会有一个’\0’作为结束符,所以再发送过程中,只需要判断当前发送的字符是不是结束符即可,如果不是结束符就将该位发送至电脑的串口调试助手,如果是结束符,那就意味着一个字符串发送完毕了。具体代码如下:

/*******************************************
*函数名    :Usart1_Send_Str
*函数功能  :串口1发送一个字符串函数
*函数参数  :u8 *str
*函数返回值:无
*函数描述  :
*********************************************/
void Usart1_Send_Str(u8 *str)
{
	while(*str != '\0')
	{
		Usart1_Send_Byte(*str);
		str++;
	}
}

接收字符串

发送字符串相对容易,接收这边,就需要借用C语言中的数组来帮忙了,因为数据是一个字符一个字符的发送过来的,每一次只能接收一个字符,所以需要使用一个数组来存接收到的位,而且串口助手在发送字符串的时候是不会给单片机发送结束符,所以还需要编程者自己规定结束符,当然,后面引入空闲中断之后就不需要这样操作了。这里笔者使用的是‘#’作为结束标志。具体实现代码如下:


/*******************************************
*函数名    :Usart1_Receive_Str
*函数功能  :串口1接收一个字节函数
*函数参数  :void
*函数返回值:u8 str
*函数描述  :
*********************************************/
void Usart1_Receive_Str(void)
{
	static u8 i=0;
	//等待接收完成
	while(!(USART1->SR & (1<<5)));
	//将数据寄存器的数据读取到数组
		Str_Buff[i] = USART1->DR;
		i++;
	if(Str_Buff[i-1]=='#')//如果检测到结束标志‘#’
	{
		Str_Buff[i-1]= '\0';//手动给字符串添加‘\0’结束符
		i=0;
		Usart1_Receive_Str_Flag=1;//接收完成的标志位置一
		Usart1_Send_Str(Str_Buff);//将接受的数组再发回串口助手
	}
}

需求

使用串口调试助手发送11打开1号小灯,10关闭一号小灯,21打开二号小灯,20关闭二号小灯。效果如下:
在这里插入图片描述
主函数代码:
在这里插入图片描述

利用串口实现printf

在C语言的学习中,使用频率最高的输出函数就是printf了,这个函数在单片机上也同样适用,只是要改一下输出的方向,所以也叫重定向。
在C中printf函数-----输出函数
输出方向:PC机------>屏幕
在单片机中printf-------输出函数
输出方向: 单片机---->PC机
关于具体的修改其实KEIL已经帮我们做好了,需要我们修改的只有一个,就是将“stdio.h”内的fputc,也就是字符输出函数,修改到和我们的字符串输出函数关联即可。具体代码如下:

 //printf的重定向函数
//fputc-----专门发送字符的函数h
int fputc(int c, FILE * stream)
{
	Usart1_Send_Byte(c);
	return c;
}

将此代码放到USART1.c中即可,不需要调用也不需要声明。
在这里插入图片描述
然后就是勾选KEIL的库,如下图所示,依次选择魔法棒、Target、然后将3所在位置的复选框锁定。
在这里插入图片描述
然后再在USART1.h中添加stdio.h。
在这里插入图片描述
最后在主函数中调用printf即可,printf主要是方便我们的后期调试,实用语法与C一致。
在这里插入图片描述
实际输出效果:
在这里插入图片描述
到这里,已经实现了字符串的收发,但是存在两个问题,
1是上位机发送数据到板子上必须要设置结束符,类似笔者此处的‘#’;
2是此代码在接收时会阻塞在等待接受完毕的while,这会导致其他的模块工作不正常,在while(1)内,一定要尽力避免死等的出现。
很明显,现在这个代码还不太令人满意,那么要怎么修改呢,在修改代码之前,需要先去了解一个新的东西——中断。
在这里插入图片描述

中断

首先,需要知道中断是个什么东西,它有什么作用,具体怎么使用,下面一一来进行介绍。

中断是什么

中断嘛,按照名字的第一反应是终止一件事,打断某些东西的感觉,实际上也差不多是这个意思,它终止和打断的就是前面编写的main函数里面运行的东西。
在这里插入图片描述
也就是说在程序正常运行过程中,出现了不正常的事件(异常),CPU会优先去处理这个异常,处理完之后再回到正常的程序中。这个异常事件就是中断。
中断的目的:由外设或者CPU创造一个异常事件(紧急事件)
紧急事件发生的时间和地点:未知
紧急事件是实时响应的,紧急事件不能执行太久(里面不能有延时 循环 阻塞程序)
下面我们来看一张图:
代码正常运行的时候是如下图所示的蓝色箭头方向,首先会依次向下执行初始化代码,然后进入while循环,始终在任务1与任务2之间循环运行。

任务1
任务2

------->任务2
如果我们在初始化中,初始化了中断,就会有一个对应的中断服务函数,当中断的条件满足了,程序就会暂时终止main函数里面的内容,去把中断服务函数里面的内容执行完毕了再回来运行main里面的内容。
在这里插入图片描述
同时,从上图可以看出,当中断被初始化后,任何时刻都可能满足中断的条件,也就是在任何位置都可能会跳出main里面的内容去执行中断服务函数里面的内容。因此说它产生的时间和地点是未知的。
此时代码的运行顺序就不固定了可能是从任务1跳出去执行任务3任务4后再回来执行任务2

4
5
1
2
3
任务1
任务3
任务4
任务2

也有可能是直接就先去执行任务3,任务4后再回来执行任务1和任务2,等等还有多种可能,也就是只要初始化中断后,任何时刻,只要中断信号满足了,CPU就需要优先解决中断事件。
这正是中断的意义所在,类似上面的串口接收,没有中断的话,需要一直死等,这会严重影响其他函数的运行,引入中断后,就可以通过中断来判断是否接收完成了。那么具体是怎么配置的呢。
通过上面的流程图,大致分析一下,首先,肯定需要在初始化中初始化中断,然后是需要一个中断服务函数来存放异常事件,此外还需要判断对应的中断事件有没有产生。

串口的接收中断以及空闲中断

本文主要是接着串口先体验一下中断的作用,关于STM32中断系统的详细介绍放到下一篇中。
在配置串口的接收和发送的时候,串口相关的有很多寄存器是直接跳过了的,这里面就有一部分是和中断相关的,
首先,来看控制寄存器1(USART1-CR[0])的第四到第八位都是中断相关的使能位,也就是说,只要在代码中配置了相关的位,就可以在其描述的时刻产生对应的中断信号,这里面常用的就是第4位的空闲中断和第5位的接收完成中断;第4位的中断信号是在接收完成后一段时间内再也没有数据接收了就会被触发,所以叫做空闲中断的使能;而第5是接收中断,也就是每次接收完一个字符后就会触发一次中断;编程者可以使用这两个中断实现非阻塞的串口数据接收。当接收中断产生的时候就读取接受的字符到数组,当产生空闲中断的时候就在数组末尾添加结束标志。这样就省去了结束符,也解决了接收死等的问题。
在这里插入图片描述
串口的接收中断:
触发条件是:串口的DR寄存器接收到了值,接收到触发信号后,会将信号传递给NVIC控制器,NVIC控制器会将CPU调到中断服务函数中使用。
串口的空闲中断:
触发条件:在串口接收数据过程中,如果有一段事件串口停止工作了会产生触发信号。
在串口工作结束的时候产生一次中断请求
接收到字符串的时候没有结束条件,可以使用空闲中断作为判断字符串结束的条件
只要使用串口的模块,大部分都需要接收数据,但是如果使用基础的串口函数都会造成阻塞

实现代码

首先来分析一下实现流程,伪代码:

串口1的初始化函数
{
   //打开时钟
   //GPIO控制器配置
   //USART1的控制器配置
    加上串口的接收中断使能
   //NVIC控制器的配置
    优先级分组   ------   主函数的初始化之上
    优先级合成
    优先级分配
    使能中断源
}

在nvic.c中写中断服务函数即可
Void 串口1的中断服务函数名(void)
{
   If(USART1->SR & (1<<5))  //开启了CR1中的接收中断使能
   {
     //清除标志位 //读取DR寄存器  同一个步骤
	}
}

首先,肯定是需要实现串口的基础收发功能的,这个步骤在之前已经实现了,然后再其基础上开启串口的接收中断使能和空闲中断使能,也就是使能对应寄存器的第4位和第5位。
操作代码如下:

		USART1->CR1  |= (1<<5);   //使能接收中断
		USART1->CR1  |= (1<<4);   //使能空闲中断

需要将这两行代码添加到如下图所示的位置。

其实到这里有关串口中断的配置已经完成了,但是为了方便后面的对中断的管理,还需要对中断进行分组和设置优先级,原因是在整个系统中,中断不可能只有一个,为了避免中断之间的冲突,就需要对中断的优先级进行管理,也正是为了方便管理,stm32的所有中断都有固定的命名,具体的管理和分组留到下一篇中在做介绍,在本文只需要知道这一段代码的作用就是设置中断分组、优先级,还有就是打开对应的中断使能即可。
代码如下:

//NVIC控制器配置
		u32 pri=NVIC_EncodePriority(7-2,0,0);//设置抢占优先级为0,响应优先级为0
		NVIC_SetPriority(USART1_IRQn,pri);   //将对应的优先级设置映射到对应的中断
		NVIC_EnableIRQ(USART1_IRQn);         //使能中断

此段代码的位置如下:
在这里插入图片描述
除此之外,还需要添加一句在所有的初始化之前的的中断分组函数

NVIC_SetPriorityGrouping(7-2);//设置中断的优先组别(111-110-101-100)

在这里插入图片描述
至此,有关串口中断的初始化部分就搞定了,然后就是中断服务函数,中断服务函数的名称也是固定的,必须使用.s文件内的命名才可以,否则会找不到的,而且中断服务函数在使用的时候不需要调用、声明,也没有返回值、形参。只需要按照.s的函数名命名即可。
具体代码如下:
还是需要在对应文件夹下新建Nvic.c和Nvic.h。并将Nvic.c添加到工程,在主函数的main.h添加Nvic.h的头文件。

#include "Nvic.h"
UsartStruct Usart1_Receive;//声明结构体
/*******************************
函数名:USART1_IRQHandler
函数功能:串口一的中断服务函数函数
函数形参:无
函数返回值:void
备注:
********************************/
void USART1_IRQHandler(void)
{
	if(USART1->SR & (1<<5))//判断接收中断
	{
		Usart1_Receive.Rebuf[Usart1_Receive.ReBytes] = USART1->DR;
		Usart1_Receive.ReBytes++;
 	}
	if(USART1->SR & (1<<4))//判断空闲中断
	{
		USART1->SR;
		USART1->DR;//清除标志位
		Usart1_Receive.Rebuf[Usart1_Receive.ReBytes]='\0';
		Usart1_Receive.ReBytes=0;
		Usart1_Receive.UsartFlag=1;
	}
}

Nvic.h

#ifndef _NVIC_H__
#define _NVIC_H__
#include "stm32f4xx.h"
#define	RBUF_MAX				50
typedef struct
{
	void (*Usart_Recelve_Process)(void);//串口数据处理函数
	u8 	Rebuf[RBUF_MAX];        //串口接收数据数组
	u16 ReBytes;                //串口接收数据长度 
	u8 	UsartFlag;				//串口接收到数据标志位
	
}UsartStruct;
extern UsartStruct Usart1_Receive;//外部声明
#endif

实现效果

为了方便看见效果,这里写了一个小需求,使用串口调试助手发送“open”,打开LED1和LED2,并通过printf返回小灯状态,发送“close”,关闭LED1和LED2。
注意需要使用到“String.h”里面的字符串处理函数,要将这个头文件添加到main.h
具体的main.c内容如下:

#include "main.h"

int main(void)
{
/*------------------变量定义区--------------------------*/

/*------------------初始化外设区------------------------*/
	NVIC_SetPriorityGrouping(7-2);//设置中断的优先组别(111-110-101-100)
	Led_Init();
	Key_Init();
	Usart1_Init(115200);
	printf("系统初始化完毕\r\n");
/*------------------单次运行区--------------------------*/	
	
	while(1)//防止程序跑飞
	{
/*------------------主循环区--------------------------*/	
		if(Usart1_Receive.UsartFlag==1)
		{
			Usart1_Receive.UsartFlag=0;
			if(strcmp((const char*)Usart1_Receive.Rebuf,"open")==0 )
			{
				LED_1_ON;
				LED_2(1);
				printf("小灯已打开\r\n");
			}
			if(strcmp((const char*)Usart1_Receive.Rebuf,"close")==0)
			{
				LED_1_OFF;
				LED_2(0);
				printf("小灯已关闭\r\n");
			}
		}
	}
}

最终运行效果:
在这里插入图片描述
在这里插入图片描述

总结

本文主要是进一步完善串口的收发功能函数,并引出串口中断的相关使用办法,由于基础的串口接收时会有阻塞作用,会导致while(1)内的其他功能无法正常运行,就像流水灯、按键扫描这些都会收到影响,所以就引入了串口中断,当对应的中断信号到了,说明已经接收到了数据,此时CPU跳出去先把数据接收,再回来继续运行while(1)的内容,这样就巧妙地回避了一直等待接受的过程。这一篇中代码有些多,写的也有些混乱,大家有建议可以指出,以错误之处也欢迎提出。

M4系列目录

1.嵌入式学习笔记——概述
2.嵌入式学习笔记——基于Cortex-M的单片机介绍
3.嵌入式学习笔记——STM32单片机开发前的准备
4.嵌入式学习笔记——STM32硬件基础知识
5.嵌入式学习笔记——认识STM32的 GPIO口
6.嵌入式学习笔记——使用寄存器编程操作GPIO
7.嵌入式学习笔记——寄存器实现控制LED小灯
8.嵌入式学习笔记——使用寄存器编程实现按键输入功能
9.嵌入式学习笔记——STM32的USART通信概述
10.嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置
11.嵌入式学习笔记——STM32的USART收发字符串及串口中断
12.嵌入式学习笔记——STM32的中断控制体系
13.嵌入式学习笔记——STM32寄存器编程实现外部中断
14.嵌入式学习笔记——STM32的时钟树
15.嵌入式学习笔记——SysTick(系统滴答)
16.嵌入式学习笔记——M4的基本定时器
17.嵌入式学习笔记——通用定时器
18.嵌入式学习笔记——PWM与输入捕获(上)
19.嵌入式学习笔记——PWM与输入捕获(下)
20.嵌入式学习笔记——ADC模数转换器
21.嵌入式学习笔记——DMA
22.嵌入式学习笔记——SPI通信
23.嵌入式学习笔记——SPI通信的应用
24嵌入式学习笔记——IIC通信

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

嵌入式学习笔记——STM32的USART收发字符串及串口中断 的相关文章

  • https://ac.nowcoder.com/acm/problem/14269(Sum 牛客网)

    位运算 43 组合数学 43 树状数组 xff1a 题解 xff1a 我们如果直接计算操作2的话会很困难 xff0c 我们可以直接考虑一个数的二进制位对答案做出的贡献 xff0c 显然二进制位为0时就不会有任何贡献 xff0c 当我们知道所
  • 异或的路径(牛客网)

    异或路径 43 位运算 43 考虑贡献 题解 xff1a 我们要求所有点对构成的所有路径的异或权值总和 xff0c 肯定不能暴力 xff0c 我们可以知道 xff0c 先搞一个数组d i 表示i节点到根节点1的路径上边权异或和 xff0c
  • TCP为什么采用三次握手而不是两次握手

    希仁版 计算机网络 中的例子是这样的 xff0c 已失效的连接请求报文段 的产生在这样一种情况下 xff1a client发出的第一个连接请求报文段并没有丢失 xff0c 而是在某个网络结点长时间的滞留了 xff0c 以致延误到连接释放以后
  • linux生成可执行文件的命令

    linux生成带调试的可执行文件命令行 xff1a g span class token operator 43 43 span span class token operator span g main span class token
  • git rebase origin/develop

    1 进行git rebase origin develop之前需要进行 lt git add gt lt git commit gt 操作先将修改给提交到暂存区 2 执行git rebase origin develop时候有冲突的话需要自
  • linux---文件描述符和重定向

    文件描述符 进程就是通过struct file结构体来描述打开的文件 xff0c 使用struct file fd array 来存储我们的文件 那什么是文件描述符呢 xff1f 什么是文件描述符 xff1a 文件描述符就是struct f
  • git合并多个commit

    git合并多个commit
  • 深度学习资料

    深度学习资料
  • cmake总结

    cmake 用CMakeList txt产生makefile xff0c make 使用makefile编译可执行程序
  • kuangbin连通图专题,Network of Schools (POJ - 1236,tarjan算法求缩点+缩点的入度与出度的运用)

    kuangbin 题意是有N个学校 每个学校可能向几个学校进行数据传输 xff08 单向的 xff09 问 至少需要把一个文件给几个学校可以使给的N个学校都收到文件 再问在加几个通信线路可以使各个学校之间都能直接或间接的传递文件 一个强连通
  • endnote 文献保留前三个作者

    1 问题描述 xff1a endnote使用GBT7714文献格式 xff0c 显示文献的全部作者 2 想要达到的效果 xff1a 最多显示三个作者 3 解决方法 xff1a 还不知道怎么弄 xff0c 看看以后再来补充 xff0c 心情烦
  • RTK_LIB 源码、可执行文件、rtkget、观测文件、星历文件(精密星历、广播星历)、精密钟差文件介绍

    1 RTK LIB开源程序下载 xff1a 点开rtklib链接 xff1a 下载最新版本的可执行文件和程序源码 2 GNSS数据处理需要的文件 2 1 伪距定位 xff1a spp 观测数据 xff08 0 xff09 导航星历 广播星历
  • RTKLIB ppp rtk_post

    1 实时ppp xff1a IGS MGEX数据处理中心的播发的实时轨道钟差产品 xff0c 结合广播星历 xff0c 实现实时定位 2 事后的 xff08 近似实时 xff09 xff1a 下载精密星历 钟差产品 xff0c 结合其他的精
  • 4.使用静态库、动态库,常见问题解决

    使用动态库的流程 xff08 ORBSLAM3实例 xff09 xff1a 在调用动态库或静态库的 cpp文件添加库的头文件 xff08 可以包含路径 xff0c 也可以在cmakelist文件加头文件搜索路径 xff09 span cla
  • vscode查看代码更新历史

    开源代码推出新版本后 xff0c 如何查看代码更改信息 1 首先打开vscode xff0c 点击左侧的插件管理器 xff0c 进入插件面板 xff0c 搜索Git Graph并安装 2 点击下图图标 xff0c 即可进入Git Graph
  • git更新代码

    一 git一般有很多分支 xff0c 我们clone到本地的时候一般都是master分支 xff0c 那么如何切换到其他分支呢 xff1f 主要命令如下 xff1a 1 查看本地分支文件信息 xff0c 确保更新时不产生冲突 span cl
  • linux---硬链接和软链接

    文件系统 磁盘上文件读写存储与查找系统 xff08 管理 xff09 就是文件系统 xff0c 在每一个分区都会存在自己的文件系统 在这里我们有swap交换分区和文件分区 xff0c 我们这里只介绍文件分区 在文件分区都会有上图中的分块管理
  • char类型数组

    字符数组 xff08 一维 二维 xff09 字符数组是数组元素为char类型的一种数组 凡是适合数组的定义和赋值 xff0c 也都适合于字符数组 由于C语言没有提供字符串类型 xff0c 字符串一般用一维字符数组来存放 xff0c 而二维
  • ubuntu18.04 安装腾讯会议

    腾讯会议现在以及上线了Linux版本 xff0c 可以直接在腾讯会议官网下载linux 版本 xff0c 在官网点击免费下载 xff0c 可以直接下载Linux版本 腾讯会议下载链接 选择Linux版本 xff0c x86 64版本 xff
  • 2.树莓派系统备份

    树莓派使用SD卡来装载系统 xff0c 如果SD卡丢失或者损坏 xff0c 那么树莓派上的数据都会丢失 xff0c 所以一定要备份好SD卡 这篇文章可以帮你备份你的树莓派系统 主要内容为备份SD卡 xff0c 制作树莓派系统镜像以及在需要的

随机推荐

  • ic_gvins编译及环境配置问题解决

    RTK VIO松组合 对惯导精度要求较高 1 环境配置和编译 安装依赖项 span class token comment gcc 8 span span class token function sudo span span class
  • EVO画图设置

    一 绘图设置 1 更改背景色和网格 span class token comment 白色网格 span evo config span class token builtin class name set span plot seabor
  • GINS_OB环境配置

    1 程序简介 武大开源GNSS INS松组合IMU预积分有考虑地球自传和不考虑两种形式可以灵活设置GNSS中断时间IMU可以和里程计进行融合 2 环境配置 span class token comment gcc 8 g 43 43 8 s
  • OB_GINS程序框架

    1 程序运行 span class token builtin class name cd span OB GINS span class token comment 编译好的可执行文件 xff1a bin ob gins xff0c 参数
  • KEIL、MDK中关于__LINE__宏 printf 的显示不正确的问题

    span class token operator gt span define span class token function DEBUG span span class token punctuation span log span
  • VINS-回环检测与重定位

    参考博客 pose graph分析1 pose graph分析2 pose graph分析3
  • 源码安装naviagtion,但是出现[move_base-2] process has died 运行错误的解决办法

    今天开始记录ros遇到的问题 安装navigation可以使用两种方法 第一种 xff1a sudo apt get install ros kinetic navigation 这种安装方法最简单 xff0c 新手或者不需要动naviag
  • linux---静态库和动态库的制作和使用

    静态链接和动态链接 静态链接 xff1a 生成可执行代码 xff0c 链接静态库 xff08 与代码位置有关的链接方式 xff09 xff0c 需要将代码拷贝到我们的源代码中才能运行 动态链接 xff1a 生成可执行代码 xff0c 链接动
  • 加一

    加一 描述 给定一个由整数组成的非空数组所表示的非负整数 xff0c 在该数的基础上加一 最高位数字存放在数组的首位 xff0c 数组中每个元素只存储单个数字 你可以假设除了整数 0 之外 xff0c 这个整数不会以零开头 示例 1 输入
  • STM32bootloader原理解释

    STM32bootloader原理解释 一 STM32的常规启动流程 STM32的内部flash地址起始于0x8000000 xff0c 一般情况下 xff0c 程序文件就从此地址开始写入 此外STM32是基于Cortex M3内核的微控制
  • 模糊PID基本原理及matlab仿真实现(新手!新手!新手!)

    有关模糊pid的相关知识就把自己从刚接触到仿真出结果看到的大部分资料总结一下 xff0c 以及一些自己的ps 以下未说明的都为转载内容 1 转自 https blog csdn net weixin 36340979 article det
  • VMware+ubuntu+win10笔记本实现笔记本连接WIFI且ubuntu既可以上网又能连接开发板

    背景 最近在学习imx6ull开发板的时候 xff0c 发现开发板通过网线连接笔记本电脑却无法ping通ubuntu xff0c 于是捣鼓了很久终于可以了 xff0c 却又发现ubuntu不能上网了 xff0c 经过一番查找资料和尝试 xf
  • 在windows上用vscode打造比vc++6.0好用的C/C++ IDE,适用编程小白

    准备 xff1a 1 安装MinGW xff0c 添加gcc gdb等编译调试工具bin目录 头文件Include目录 库lib的路径到系统环境变量 xff0c 安装LLVM 添 加Clang编译器所在bin目录到系统环境变量 具体操作百度
  • C语言数据结构——线性表的链式存储结构

    文章目录 线性表的链式存储结构1 基本概念2 设计与实现3 优点和缺点 线性表的链式存储结构 1 基本概念 链式存储定义 xff1a 为了表示每个数据元素与其直接后继元素之间的逻辑关系 xff0c 每个元素除了存储本身的信息之外 xff0c
  • 智能车浅谈——硬件篇

    目录 初识小车硬件系统1 电源系统线性电源开关电源 2 人机交互系统3 MCU最小系统4 传感器系统摄像头电感编码器 5 驱动系统 机械结构 17届完赛代码智能车系列文章汇总 前言 xff1a 作为一名老三本玩家 xff0c 笔者深知一些同
  • 智能车浅谈——图像篇

    文章目录 前言认识图像基本含义图像类型数字图像彩色图像灰度图像黑白图像 小结 图像处理图像压缩二值化固定阈值法大津法 图像降噪 xff08 腐蚀 xff09 寻边线 总结17届完赛代码17届完赛代码智能车系列文章汇总 前言 前面已经记录了智
  • 智能车浅谈——手把手让车跑起来(电磁篇)

    文章目录 前言材料准备备赛组车模硬件 练习组车模硬件方案 整车原理赛道信息获取及转向原理工字电感运放模块转向原理元素判断 电机及舵机控制原理 代码实现效果欣赏总结17届完赛代码智能车系列文章汇总 前言 电磁寻迹小车 之前智能车系列已经做了一
  • 手把手教你OneNET数据可视化

    文章目录 前言OneNET实现数据可视化效果一览发布项目 xff08 5 17更新 xff09 总结 前言 之前介绍了Hi3861使用MQTT协议接入OneNET实现数据的上传以及命令的下发 xff0c 本文主要是介绍一下如何使用OneNE
  • linux---进程间通信(ipc)之管道

    进程间通信方式 管道共享内存消息队列信号量本地套接字等等都能作为我们进程间通信的方法 操作系统提供进程间通信方式的原因 因为对于我们进程来说 xff0c 每一个进程都是相互独立的 xff0c 具有独立性 xff0c 如果我们需要两个不同的进
  • 嵌入式学习笔记——STM32的USART收发字符串及串口中断

    USART收发字符串及串口中断 前言字符串的收发发送一个字符串接收字符串需求 利用串口实现printf 中断中断是什么串口的接收中断以及空闲中断实现代码实现效果 总结M4系列目录 前言 上一篇中 xff0c 介绍了串口收发相关的寄存器 xf