STM32笔记—USART

课外知识插入:STM32单片机extern全局变量_stm32全局变量-CSDN博客

如果你把temple定义在A中,然后让A.h和B.h包含在includes.h中,然后把includes.h放在A.c和B.c中单个编译是没有问题的,但是链接的时候会出现问题,

“Symbol temple mulTIply defined(by A.o and B.o)”

这个变量被多次定义了!!!

在A中定义temple变量后,在B中用extern 声明一下例如:

1.在A中定义temple并且赋值:u16 temp2=0;2.在B中声明extern u16 temp2;

这里只是声明,不再赋值,否则会报错!

Symbol temp2 mulTIply defined (by catch_pwm.o and app.o)

这里要注意变量定义和变量声明的区别:
变量定义使用“数据类型+变量名称”的形式,编译器需要给它分配内存单元的;
而变量声明使用“extern 变量类型+变量名称”的形式,是告诉编译器我这个变量将在其他外部C文件中定义,我这里只是在外部用它。编译器就不会给它分配内存空间,而等到真正遇到变量定义时再给它分配内存空间。

        比如在一个 my.c文件中,我定义了char name[10];那么在别的文件中只要用extern
char name[],外部声明就可以了,告诉编译器这个变量我已经定义过了,具体怎样,你慢慢找吧。这符合常理,因为char是编译器能自主识别的类型。

一、USART功能概述

        任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。        

        RX:接收数据串行输。通过过采样技术来区别数据和噪音,从而恢复数据。
        TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时,TX引脚处于高电平。总线在发送或接收前应处于空闲状态。
   
     ● 一个起始位
        ● 一个数据字(8或9位),最低有效位在前
        ● 0.5,1.5,2个的停止位,由此表明数据帧的结束
        ● 使用分数波特率发生器 —— 12位整数和4位小数的表示方法。
        ● 一个状态寄存器(USART_SR)
        ● 数据寄存器(USART_DR)
        ● 一个波特率寄存器(USART_BRR),12位的整数和4位小数
        ● 一个智能卡模式下的保护时间寄存器(USART_GTPR)

        下列引脚在硬件流控模式中需要:
               nCTS: 清除发送,若是高电平,在当前数据传输结束时阻断下一次的数据发送。

               nRTS: 发送请求,若是低电平,表明USART准备好接收数据

二、USART 特性描述

         字长可以通过编程USART_CR1寄存器中的M位,选择成8或9位(见图249)。在起始位期间,TX脚处于低电平,在停止位期间处于高电平。
        空闲符号被视为完全由’1’组成的一个完整的数据帧,后面跟着包含了数据的下一帧的开始位(‘1’的位数也包括了停止位的位数)。断开符号 被视为在一个帧周期内全部收到’0’(包括停止位期间,也是’0’)。在断开帧结束时,发送器再插入1或2个停止位(‘1’)来应答起始位。
        发送和接收由一共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟。

 三、发送器

        发送器根据M位的状态发送8位或9位的数据字。当发送使能位(TE)被设置时,发送移位寄存器中的数据在TX脚上输出,相应的时钟脉冲在CK脚上输出。
        字符发送
        在USART发送期间,在TX引脚上首先移出数据的最低有效位。在此模式里,USART_DR寄存器包含了一个内部总线和发送移位寄存器之间的缓冲器。
        每个字符之前都有一个低电平的起始位;之后跟着的停止位,其数目可配置。
        USART支持多种停止位的配置:0.5、1、1.5和2个停止位。
        注: 在数据传输期间不能复位TE位,否则将破坏TX脚上的数据,因为波特率计数器停止计数。正在传输的当前数据将丢失。

        可配置的停止位
        随每个字符发送的停止位的位数可以通过控制寄存器2的位13、12进行编程。
        1. 1个停止位:停止位位数的默认值。
        2. 2个停止位:可用于常规USART模式、单线模式以及调制解调器模式。
        3. 0.5个停止位:在智能卡模式下接收数据时使用。
        4. 1.5个停止位:在智能卡模式下发送和接收数据时使用。
        空闲帧包括了停止位。
        断开帧是10位低电平,后跟停止位(当m=0时);或者11位低电平,后跟停止位(m=1时)。不可能传输更长的断开帧(长度大于10或者11位)。

 配置步骤:
        1. 通过在USART_CR1寄存器上置位UE位来激活USART
        2. 编程USART_CR1的M位来定义字长。
        3. 在USART_CR2中编程停止位的位数。
        4. 如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中的描述配置DMA寄存器。
        5. 利用USART_BRR寄存器选择要求的波特率。
        6. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
        7. 把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。
        8. 在USART_DR寄存器中写入最后一个数据字后,要等待TC=1,它表示最后一个数据帧的传输结束。当需要关闭USART或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

        单字节通信
        清零TXE位总是通过对数据寄存器的写操作来完成的。TXE位由硬件来设置,它表明:
        ● 数据已经从TDR移送到移位寄存器,数据发送已经开始
        ● TDR寄存器被清空
        ● 下一个数据可以被写进USART_DR寄存器而不会覆盖先前的数据

        如果TXEIE位被设置,此标志将产生一个中断。
        如果此时USART正在发送数据,对USART_DR寄存器的写操作把数据存进TDR寄存器,并在当前传输结束时把该数据复制进移位寄存器。
     
   如果此时USART没有在发送数据,处于空闲状态,对USART_DR寄存器的写操作直接把数据放进移位寄存器,数据传输开始,TXE位立即被置起。
        当一帧发送完成时(停止位发送后)并且设置了TXE位,TC位被置起,如果USART_CR1寄存器中的TCIE位被置起时,则会产生中断。

        在USART_DR寄存器中写入了最后一个数据字后,在关闭USART模块之前或设置微控制器进入低功耗模式(详见下图)之前,必须先等待TC=1。
      
  使用下列软件过程清除TC位:
        1.读一次USART_SR寄存器;
        2.写一次USART_DR寄存器。
注: TC位也可以通过软件对它写’0’来清除。此清零方式只推荐在多缓冲器通信模式下使用。

        

 四、接收器

1. 起始位侦测

2.字符接收

 五、分数波特率的产生

        发送器和接收器的波特率由波特率寄存器BRR里的DIV确定,计算公式:波特率 = fPCLK2/1 / (16 * DIV)

 如何从USART_BRR寄存器值得到USARTDIV
例1:
如果 DIV_Mantissa = 27 , DIV_Fraction = 12 (USART_BRR=0x1BC),

于是
Mantissa (USARTDIV) = 27
Fraction (USARTDIV) = 12/16 = 0.75
所以 USARTDIV = 27.75
例2:
要求 USARTDIV = 25.62,
就有:
DIV_Fraction = 16*0.62 = 9.92
最接近的整数是:10 = 0x0A
DIV_Mantissa = mantissa (25.620) = 25 = 0x19
于是,USART_BRR = 0x19A
例3:
要求 USARTDIV = 50.99
就有:
DIV_Fraction = 16*0.99 = 15.84
最接近的整数是:16 = 0x10 => DIV_frac[3:0]溢出 => 进位必须加到小数部分
DIV_Mantissa = mantissa (50.990 + 进位) = 51 = 0x33
于是:USART_BRR = 0x330,USARTDIV=51

六、USART中断

七、HEX数据包发送

        1.1固定包长,含包头包尾(包尾不是必须的)


        1.2可变包长,含包头包尾

1、包头包尾和数据载荷重复的问题,传输的数据本身是FF和FE,可能引起误判
        解决:限制载荷数据的范围,限幅(例如只发送0~100)
        如果无法避免数据与包头包尾重复,则尽量使用固定长度的数据包
        增加包头包尾的数量,尽量是其呈现出载荷数据出现不了的状态
2、包头包尾并不是全部都需要的,例如可以只要一个包头
3、固定包长和可变包长的选择问题
        对HEX来说,若载荷出现和包头包尾重复的情况,最好选择固定包长,避免接收错误。若不重复,可以选择可变包长
4、各种数据转化为数据流的问题
        数据包都是一个字节一个字节组成的,若想发送16位整型数据、32位整型数据,float、double、甚至是结构体(其内部都是由一个字节一个字节组成的),只需要用一个uint8_t的指针指向它,把数据当作字节数组发送即可。

接收HEX数据包

        每收到一个字节,函数都会进入一次中断,在中断函数中,可以拿到一个字节,但拿到字节之后,就得退出中断,故每拿到一个数据,都是一个独立的过程,而对数据包来说,有数据、包头、包尾三种状态,根据状态不同处理也不同。
原文链接:https://blog.csdn.net/qq_27928443/article/details/130088050

代码详解:

#include "Serial.h"
uint8_t Serial_Rx_Package[4];
uint8_t Serial_Tx_Package[4];void Serial_Init(void)
{//1.开启时钟//RCC库函数//存储器和总线构架APB2_usart1/gpioaRCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//复用重映射和调试I/O配置寄存器(AFIO_MAPR)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//0+2.GPIO初始化//10.2.3 函数GPIO_Init//GPIO_InitTypeDef GPIO_InitStructure; //GPIO_Init(GPIOA, &GPIO_InitStructure);//8.2.1 端口配置低寄存器(GPIOx_CRL) (x=A..E)GPIO_InitTypeDef GPIO_InitStructure;//USART复用功能重映射GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//USARTx_RX浮空输入或带上拉输入GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//USART1_TX PA9  USART1_RX PA10//3.USART初始化//25.3.1 USART 特性描述USART_InitTypeDef USART_InitStructure;					//定义结构体变量USART_InitStructure.USART_BaudRate = 9600;				//波特率USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制,不需要USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;	//模式,发送模式和接收模式均选择USART_InitStructure.USART_Parity = USART_Parity_No;		//奇偶校验,不需要USART_InitStructure.USART_StopBits = USART_StopBits_1;	//停止位,选择1位USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//字长,选择8位USART_Init(USART1, &USART_InitStructure);				//将结构体变量交给USART_Init,配置USART1//4.中断输出配置//21.2.5 函数USART_ITConfig//USART_IT_RXNE 接收中断//RXNE:读数据寄存器非空 (Read data register not empty)//0:数据没有收到;1:收到数据,可以读出。//对USART_DR的读操作可以将该位清零。USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//5.NVIC中断分组//NVIC_PriorityGroup_2	抢占优先级取值:0~3	响应优先级取值:0~3	//整个系统执行过程中,只设置一次中断分组,多次操作以最后一次设置为准。//针对每个中断,设置对应的抢占优先级和响应优先级。//如不设置中断优先级分组,则中断优先级分组默认为0,即0位抢占优先级,4位响应优先级。//13.2.3 函数NVIC_PriorityGroupConfigNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//6.NVIC初始化NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2U;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1U;NVIC_Init(&NVIC_InitStructure);//7.使能USART1//21.2.4 函数USART_CmdUSART_Cmd(USART1,ENABLE);}/*** 函    数:串口发送一个字节* 参    数:Byte 要发送的一个字节* 返 回 值:无*/
void Serial_SendByte(uint8_t Byte)
{//21.2.12 函数USART_SendDataUSART_SendData(USART1,Byte);//等待发送完成标志位21.2.22 函数USART_GetFlagStatus// USART_FLAG_TC:   Transmission Complete flag//0:发送还未完成;1:发送完成。while(RESET == USART_GetFlagStatus(USART1,USART_FLAG_TC));
}/*** 函    数:串口发送一个数组* 参    数:Array 要发送数组的首地址* 返 回 值:无*/
void Serial_SendArray(uint8_t* Array)
{uint16_t i = 0;if(i < sizeof(Array)/sizeof(Array[0])){Serial_SendByte(*(Array+i));依次调用Serial_SendByte发送每个字节数据}
}/*** 函    数:串口发送一个字符串* 参    数:String 要发送字符串的首地址* 返 回 值:无*/
void Serial_SendString(uint8_t* String)
{while(*String++){Serial_SendByte(*String);}
}/*** 函    数:使用printf需要重定向的底层函数* 参    数:保持原始格式即可,无需变动* 返 回 值:保持原始格式即可,无需变动*/
int fputc(int ch, FILE *f)
{Serial_SendByte(ch);			//将printf的底层重定向到自己的发送字节函数return ch;
}/*** 函    数:串口发送数字* 参    数:Number 要发送的数字,范围:0~4294967295* 参    数:Length 要发送数字的长度,范围:0~10* 返 回 值:无*/
uint32_t Serial_Pow(uint32_t m,uint32_t n)
{uint32_t result = 1;while(m--){result *= n;}return result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{	uint8_t j = 0;for(j = 0; j < Length; j++){//12345/10000 = 1%10 = 1//12345/1000 = 12%10 = 2//12345/100 = 123%10 = 3//12345/10 = 1234%10 = 4//12345/1 = 12345%10 = 5Serial_SendByte('0' + Number/Serial_Pow(10,Length-j-1));}}/*** 函    数:获取串口接收数据包标志位* 参    数:无* 返 回 值:串口接收数据包标志位,范围:0~1,接收到数据包后,标志位置1,读取后标志位自动清零*/
uint8_t Serial_Flag = 0;//接收结束标志位
uint8_t Get_Status_Serial_Flag(void)
{if(Serial_Flag == 1){Serial_Flag = 0;return 1;}else	{return Serial_Flag;}
}/*** 函    数:串口发送数据包* 参    数:无* 返 回 值:无* 说    明:调用此函数后,Serial_Tx_Package数组的内容将加上包头(FF)包尾(FE)后,作为数据包发送出去*/
void Serial_Send_Package(void)
{Serial_SendByte(0xFF);Serial_SendArray(Serial_Tx_Package);Serial_SendByte(0xFE);
}/*** 函    数:USART1中断函数* 参    数:无* 返 回 值:无* 注意事项:此函数为中断函数,无需调用,中断触发后自动执行*           函数名为预留的指定名称,可以从启动文件复制*           请确保函数名正确,不能有任何差异,否则中断函数将不能进入*			  DCD     USART1_IRQHandler          ; USART1*/void USART1_IRQHandler(void)
{uint8_t Serial_Station = 0;//位置判断标志uint8_t Serial_Package_Location = 0;//数据包位置if(USART_GetFlagStatus(USART1,USART_IT_RXNE) == RESET)//如果发生接收中断,说明数据从接收移位寄存器到了接收数据寄存器//RXNE位被置位。它表明移位寄存器的内容被转移到RDR。换句话说,数据已经被接收并且可以被读出。{//21.2.13 函数USART_ReceiveData返回USARTx最近接收到的数据//USART_DR寄存器[8:0]:数据值 (Data value)位8:0包含了发送或接收的数据。//uint16_t USART_ReceiveData(USART_TypeDef* USARTx)uint16_t Serial_Data = USART_ReceiveData(USART1);//读取接收到的数据if(Serial_Station == 0){if(Serial_Data == 0xFF){//说明找到了数据包头Serial_Station = 1;Serial_Package_Location = 0;//开始发送数据}else{Serial_Station = 0;//没有找到ff,就一直找}}else if(Serial_Station == 1)//就算传入FF也不会出循环{if(Serial_Package_Location < 4){Serial_Rx_Package[Serial_Package_Location++] = Serial_Data;//传输数据//传输一次就会置标志位}Serial_Station = 2;//说明数据发送完}else if(Serial_Station == 2){if(Serial_Data == 0xFE){//说明找到了数据包尾Serial_Station = 0;Serial_Flag = 1;//发送完成标志位}else{Serial_Station = 2;}}//21.2.25 函数USART_ClearITPendingBit清除USARTx的中断待处理位USART_ClearITPendingBit(USART1,USART_IT_RXNE);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/193401.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(七):FREERTOS移植

前言: 一般的GUI工程都需要一个操作系统,可能是linux,重量级的,也可能是FreeRTOS,轻量级的。 一句话理解那就是工程就是FreeRTOS task任务的集合。 一个main函数可以看到大框架: 很显然,除了第一个是硬件配置的初始化,中间最重要的部分就是要创建任务,把AWTK的应用…

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考…

产品运营的场景和运营策略

一、启动屏 1&#xff0e;概念 启动屏&#xff0c;特指 APP 产品启动时即显示的界面&#xff0c;这个界面一般会停留几秒钟时间&#xff0c;在这个时间内 APP 会在后台加载服务框架、启动各种服务 SDK 、获取用户地理位置、判断有无新版本、判断用户账户状态以及其他系统级别的…

python3.8 安装 ssl 模块 和 _ctypes 模块

这文章目录 前情提要安装 openssl-1.1.1重新编译安装 python3.8-rpath 编译选项介绍python3.8 跟 python3.10 的区别那要怎么解决这个问题呢&#xff0c;我想到有四种解决方案&#xff1a; 前情提要 我在之前给 python3.10 安装 ssl 模块后以为该步骤 “对于 python3.6、pytho…

使用docker部署ELK日志框架-Elasticsearch

一、ELK知识了解 1-ELK组件 工作原理&#xff1a; &#xff08;1&#xff09;在所有需要收集日志的服务器上部署Logstash&#xff1b;或者先将日志进行集中化管理在日志服务器上&#xff0c;在日志服务器上部署 Logstash。 &#xff08;2&#xff09;Logstash 收集日志&#…

自己动手实现一个深度学习算法——六、与学习相关的技巧

文章目录 1.参数的更新1&#xff09;SGD2&#xff09;Momentum3&#xff09;AdaGrad4&#xff09;Adam5&#xff09;最优化方法的比较6&#xff09;基于MNIST数据集的更新方法的比较 2.权重的初始值1&#xff09;权重初始值不能为02&#xff09;隐藏层的激活值的分布3&#xff…

Reids集群

目录 一、集群的概念 1.为什么要搭建集群&#xff1f; 2.Redis搭建集群是否需要考虑状态同步的问题&#xff1f; 二、Redis集群的模式 1.redis集群--主从模式 1.1什么是Redis的主从模式&#xff1f; 1.2.主从模式它们之间的数据是怎么实现一个同步的&#xff1f; 1.3.主…

机器人导航+OPENCV透视变换示例代码

透视变换又称四点变换&#xff0c;所以不能用于5边形这样的图形变换&#xff0c;不是真正的透视变换&#xff0c;但是这个方法可以把机器人看到的图像转换为俯视图&#xff0c;这样就可以建立地图&#xff0c;要不然怎么建立地图呢。 void CrelaxMyFriendDlg::OnBnClickedOk()…

开启创造力之门:掌握Vue中Slot插槽的使用技巧与灵感

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、s…

机器人制作开源方案 | 智能家庭防护机器人

作者&#xff1a;李尚堰 陈庆达 王立宽 尹婕 张永俊单位&#xff1a;哈尔滨剑桥学院指导老师&#xff1a;马文龙 韩轶男 一、设计背景 随着计算机技术、信息通讯、大数据、智能传感等科学技术的不断发展、融合以及在机器人领域的不断应用&#xff0c;服务机器人产业将呈现出快…

蓝眼开源云盘部署全过程(手动安装)

环境概述&#xff1a; 系统-Centos7.4 数据库-MySQL8 云盘系统-Tank4.0.1 前提&#xff1a;操作系统已完成安装&#xff0c;有外部网络。 一.安装数据库 cd到合适的目录进行下载安装操作&#xff0c;期间不要切换出去。 wget https://dev.mysql.com/get/mysql80-community-r…

STM32与ZigBee技术在智能家居无线通信中的应用研究

一、引言 智能家居系统是利用物联网技术将家庭各种设备进行互联互通&#xff0c;实现智能化控制和管理的系统。在智能家居系统中&#xff0c;无线通信技术起着至关重要的作用&#xff0c;而STM32微控制器和ZigBee技术则是实现智能家居无线通信的关键技术。本文将对STM32与ZigB…

51单片机应用从零开始(三)

51单片机应用从零开始&#xff08;一&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;二&#xff09;-CSDN博客 详解 KEIL C51 软件的使用建立工程-CSDN博客 详解 KEIL C51 软件的使用设置工程编绎与连接程序-CSDN博客 目录 1. 用单片机控制第一个灯亮 2. 认识单片…

Unity地面交互效果目录

大家好&#xff0c;我是阿赵。   之前写了几篇关于地形交互、地面轨迹、脚印效果实现的博文。虽然写的篇数不多&#xff0c;但里面也包含了不少基础知识&#xff0c;比如局部UV采样、法线动态混合、曲面细分等知识&#xff0c;这些都是可以和别的效果组合在一起&#xff0c;做…

STL—next_permutation函数

目录 1.next_permutation函数的定义 2.简单使用 2.1普通数组全排列 2.2结构体全排列 2.3string 3.补充 1.next_permutation函数的定义 next_permutation函数会按照字母表顺序生成给定序列的下一个较大的排列&#xff0c;直到整个序列为降序为止。与其相对的还有一个函数—…

WebMvcConfigurer配置详解

一、简介 WebMvcConfigurer配置类其实是Spring内部的一种配置方式&#xff0c;采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制&#xff0c;可以自定义一些Handler&#xff0c;Interceptor&#xff0c;ViewResolver&#xff0c;MessageConverter。基于ja…

使用手机作为电脑的麦克风和摄像头外设

工具 Iriun Iriun 电脑端安装&#xff1a;Iriun Android: Iriun 4K Webcam for PC and Mac - Apps on Google Play Apple: Iriun Webcam for PC and Mac on the App Store 基础功能免费&#xff0c;普通使用足够了。 付费功能&#xff1a; 使用 这里有介绍&#xff1a…

软件开发之路——关于架构师的一些书籍

文章目录 &#x1f4cb;前言&#x1f3af;什么是架构师&#x1f525;文末送书《高并发架构实战&#xff1a;从需求分析到系统设计》《中台架构与实现&#xff1a;基于DDD和微服务》《架构师的自我修炼&#xff1a;技术、架构和未来》《分布式系统架构&#xff1a;架构策略与难题…

基于STM32的LoRaWAN无线通信网络设计与实现

LoRaWAN (Long Range Wide Area Network) 是一种低功耗的无线通信技术&#xff0c;用于构建广域物联网。本篇文章将介绍基于STM32微控制器的LoRaWAN无线通信网络的设计与实现&#xff0c;并提供相应的代码示例。 概述 LoRaWAN的无线通信技术采用低功耗长距离传输&#xff0c;…

深度学习+opencv+python实现车道线检测 - 自动驾驶 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…