stm32学习笔记:USART串口通信

1、串口通信协议(简介+软硬件规则)

全双工:打电话。半双工:对讲机。单工:广播 

时钟:I2C和SPI有单独的时钟线,所以它们是同步的,接收方可以在时钟信号的指引下进行采样。串口、CAN和USB没有时钟线,需要双方约定一个采样频率,它们是异步的,并且需要加一些帧头帧尾等进行采样位置的对齐。

电平:1、单端->引脚的高低电平都是对GND的电压差,所以单端信号通信的双方必须要共地,就是把GND接在一起。2、

差分->它是靠两个差分引脚的电压差来传输信号的,在通讯的时候,可以不需要共地,可极大提高抗干扰特性,所以差分信号一般传输速度和距离都会非常高。

设备:点对点->老师单独找一位学生谈话;多设备->老师在教室里面对所有同学谈话,需要有一个寻址的过程,以确定通信的对象。寻址:给不同的设备编号,对应不同的学生的名字


 

 

 

 波特率:如果双方规定波特率为1000bps,表示1s要发送1000位,每一位的时间就是1ms。 发送方每隔1ms发送1位,接收方每隔1ms接收1位。波特率,它决定了每隔多久发送一位。

起始位:首先,串口的空闲状态是高电平,也就是没有数据传输的时候,引脚必须要置高电平,作为空闲状态,然后需要传输的时候,必须要先发送一个起始位,这个起始位必须是低电平,来打破空闲状态的高电平,产生一个下降沿,该下降沿就告诉设备这一帧数据要开始了。如果没有起始位,数据线就一直都是高电平,没有任何波动,这样接收方怎么知道要接收数据呢。

停止位:为下一个起始位做准备。如果没有停止位,那当我数据最后一位是0的时候,下次再发送新的一帧,就没有办法产生下降沿了。
例子,连续发送两个0x55,1个停止位和2个停止位

 校验位:串口使用的是一种叫奇偶校验的数据验证方法。奇偶校验可以判断数据传输是否出错。如果数据出错了,可以选择丢弃或者要求重传。

串口通信总结:TX引脚输出定时翻转的高低电平,RX引脚定时读取引脚的高低电平。每个字节的数据加上起始位,停止位,可选的校验位(无,奇,偶),打包成数据帧,一次输出在TX引脚,另一端RX引脚依次接收,这样就完成了字节数据的传递。

2、STM32内部的USART外设

USART外设就是串口通信的硬件支持电路。
常用配置:波特率9600或者115200,数据位8位,停止位1位,无校验
USART1:APB2总线的设备
USART2、USART3:APB1总线的设备

 

USART功能框图

发送数据寄存器和发送移位寄存器怎么工作的呢?
比如在某一时刻给TDR写入0x55数据

发送端
此时,硬件检测到你写入数据,它就会检查当前一位寄存器是不是有数据正在移位,如果没有,这个01010101就会立刻全部移动到发送移位寄存器,准备发送。当数据从TDR移动到移位寄存器时,会置一个标志位,叫TXE(TX Empty),发送寄存器空。如果该标志位置1,可在TDR写入下一个数据。注意,当TXE标志位置1时,数据还没有发送出去,只要数据从TDR转移到移位寄存器,TXE就会置1,此时可写入新的数据。然后发送移位寄存器就会在发生器控制的驱动下,向右移位,然后一位一位地把数据输出到TX引脚,正好与串口协议规定的低位先行一致。当数据移位完成时,新的数据就会再次自动地从TDR转移到发送移位寄存器里来。如果当前移位寄存器移位还没有完成,TDR的数据就会进行等待,一旦移位完成,就会立刻转移过来。有了TDR和移位寄存器的双重缓存,可以保证连续发送数据的时候,数据帧之间不会有空闲。简单来说,数据一旦从TDR转移到移位寄存器,管你有没有移位完成,就会把下一个数据放在TDR等待。一旦移位寄存器移动完成,新的数据就会立刻跟上。

接收端
数据从RX引脚通向接受移位寄存器,在接收器控制的驱动下,一位一位地读取RX电平,先放在最高位,然后向右移动,移位8次后就可以接受一个字节。

同样,因为串口协议规定是低位先行,所以接受移位寄存器是从高位往低位这个方向移动,当一个字节移位完成后,这一个字节的数据就会整体地转移到接收数据寄存器RDR里,在转移的过程中会置一个标志位,叫RXNE(RX Not Empty),接收数据寄存器非空。当我们检测到RXNE置1之后,就可以把数据读走。同时,这个标志位可以去申请中断,在收到数据时,直接进入中断函数。
这里也是两个寄存器进行缓存,当数据从移位寄存器转移到RDR时,就可以直接移位接受下一帧数据。

发送器控制:用来控制发送移位寄存器的工作
接受器控制:用来控制接收移位寄存器的工作

以下模块用于产生同步时钟信号,它是配合发送移位寄存器输出的,发送寄存器每移位一次,同步时钟电平就跳变一个周期,时钟告诉对方我移出去移位数据了 。该时钟只支持输出,不支持输入,因此两个USART之间不能实现同步的串口通信。
时钟作用
1、兼容别的协议,比如串口加时钟,与SPI协议相似,因此可兼容SPI
2、自适应波特率,如接收设备不确定发送设备给的是什么波特率,可通过测量时钟周期,再计算得到波特率。 

波特率发生器就是分频器,APB时钟进行分频,得到发送和接收移位的时钟。

串口的引脚

3、USART基本结构

‘>>’右移,表示数据低位先行
开关控制->配置完成时,用cmd开启USART外设

输入的采样频率和波特率一致,还要保证每次输入采样的位置,要正好处于每一位的正中间,只有在每一位的正中间采样,这样的高低电平读进来,才是最可靠的。如果采样点过于靠前或靠后,那有可能高低电平还正在翻转,电平不稳定或者稍有误差,数据就采样出错了。 

 

4、串口发送代码


4-1 基本流程
1、第一步开启时钟,把需要用到的USART和GPIO的时钟打开
2、第二步,GPIO初始化,把Tx配置成复用输出,Rx配置成输入
3、第三步,配置USART,直接使用一个结构体
4、如果你只需要发送的功能,就直接开启USART,初始化就结束了;如果你需要接收的功能,可能还需要配置中断,那就在开启USART之前,再加上ITConfig和NVIC的代码

 

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"int main(void)
{OLED_Init();Serial_Init();Serial_SendByte(0x41);while (1){}
}

serial.h

#ifndef __SERIAL_H
#define __SERIAL_Hvoid Serial_Init(void);
void Serial_SendByte(uint8_t Byte);#endif

serial.c

#include "stm32f10x.h"                  // Device headervoid Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  GPIO_InitTypeDef GPIO_InitStructure;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);//USARTUSART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  USART_InitStructure.USART_Mode = USART_Mode_Tx;    USART_InitStructure.USART_Parity = USART_Parity_No;  USART_InitStructure.USART_StopBits = USART_StopBits_1;  USART_InitStructure.USART_WordLength = USART_WordLength_8b;  USART_Init(USART1, &USART_InitStructure);//USARTUSART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{ USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); 
}

 

static void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 *//* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 ,默认使用串口1作为中断源*/NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure);
}// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断,接收数据寄存器非空,表示接收到数据就产生中断USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);

5、初始化完成后,如果要发送数据,调用一个发送函数即可;如果要接收数据,就调用接收的函数。如果要获取发送和接收的状态,就调用获取位的函数

4-2 整体代码
4-2-1 main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"int main(void)
{OLED_Init();//初始化串口Serial_Init();//发送数据,调用该函数后,TX引脚就会产生一个0x41对应的波形,//可将该波形发送给其他支持串口的模块,也可以通过USB转串口的模块发送到电脑端Serial_SendByte(0x41);uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};Serial_SendArray(MyArray, 4);//传入数组的首地址,指定传输4个字节  Serial_SendString("\r\nNum1=");Serial_SendNumber(111, 3);printf("\r\nNum2=%d", 222);char String[100];  //定义字符串sprintf(String, "\r\nNum3=%d", 333);  //打印字符串Serial_SendString(String);  //发送字符串Serial_Printf("\r\nNum4=%d", 444);Serial_Printf("\r\n");while (1){}
}
4-2-2 Serial.c

取某一位就是–>数字 / 10^x % 10
/ 10^x 去掉右边
% 10 去掉左边

重定向fputc跟printf有什么关系呢?
这是因为fputc是printf函数的底层实现,printf函数在打印的时候就是不断调用fputc函数一个个打印的,我们把fputc函数重定向到串口,那printf自然久输出到串口。

 #include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);  //USART1的外设时钟时APB2RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //开启GPIO时钟//初始G化PIOGPIO_InitTypeDef GPIO_InitStructure;/* 将PA9配置为复用推挽输出,供USART的Tx使用 *///TX引脚是USART外设控制的输出脚,所以要选复用推挽输出,RX引脚是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);//初始化USARTUSART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;  //Init函数内部会自动算好9600对应的分频系数,然后写到BRR寄存器USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //不用流控USART_InitStructure.USART_Mode = USART_Mode_Tx;    //只有发送模式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);//使能USARTUSART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{ //将Byte变量写入到TDRUSART_SendData(USART1, Byte);//等待TXE置1,表明TDR数据已经转移到移位数据寄存器,要不然如果数据//还在TDR进行等待,我们再写入数据就会产生数据覆盖,所以在数据发送之后,还需要等待以下标志位//如果TXE标志位==RESET,就一直循环,直到SET,结束等待,标志位置1后,不需要手动清零,//当下一次SendData时,该标志位自动清零while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); 
}//uint8_t *Array这是一个uint8_t 的指针类型,指向待发送数组的首地址,传递数组需要使用指针
//length由于数组无法判断是否结束,所以需要再传递一个length进来
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++)  //数据0,对应空字符,是字符串结束标志位,如果不等于0,就是还没有结束,进行循环,如果等于0,就是结束,停止循环{Serial_SendByte(String[i]);}
}
//返回值为 x的y次方
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y --){Result *= X;  //X的Y次方}return Result;
}
//发送一个数字,最终能在电脑显示字符串形式的数字
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');  //目前循环,参数会以10进制从高位到低位依次发送,再加上偏移量//假设length为2,当i=0时,发送的是10位,当i=1时,发送的是个位//从高位到低位依次发送}
}
//
//单个串口重定向,只能有一个串口用来打印
//printf重定向,fputc是printf的底层,将fputc函数重定向到了串口,那printf自然就输出到串口
int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}//多个串口重定向,可多个串口用来打印
//封装sprintf
void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}
4-2-3 Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);#endif

程序现象:就看串口助手软件

5、串口接收代码

5-1 查询

在主函数里不断判断RXNE标志位,如果置1,表明收到数据,再调用ReceiveData,读取DR寄存器即可

//查询while(1){if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET){RxData = USART_ReceiveData(USART1);  //读完DR寄存器,该标志位自动清除OLED_ShowHexNum(1,1,RxData,2);}}
5-2 中断
/*===================================================*//* 串口接收 可使用 查询和中断两种方法 以下是中断*///开启中断,选择RXNE,表示这一个字节的数据就会整体地转移到接收数据寄存器RDR里USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//中断优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVICNVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/*===================================================*//*==============中断接收和变量的封装====================*/
uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}
//中断函数的名字在启动文件里面(startup_stm32f10x_md.s)
void USART1_IRQHandler(void)
{//先判断标志位if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){//将接收寄存器里的数据放到自定义变量里Serial_RxData = USART_ReceiveData(USART1);//读完数据后置标志位1Serial_RxFlag = 1;//如果读取DR,则自动清除标志位,否则,手动清除标志位USART_ClearITPendingBit(USART1, USART_IT_RXNE);  }
}
5-3-2 Serial.c
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t Serial_RxData;
uint8_t Serial_RxFlag;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;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);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);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;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);/*===================================================*//* 串口接收 可使用 查询和中断两种方法 以下是中断*///开启中断,选择RXNE,表示这一个字节的数据就会整体地转移到接收数据寄存器RDR里USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//中断优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVICNVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/*===================================================*/USART_Cmd(USART1, ENABLE);
}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void Serial_SendArray(uint8_t *Array, uint16_t Length)
{uint16_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i ++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y --){Result *= X;}return Result;
}void Serial_SendNumber(uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i ++){Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');}
}int fputc(int ch, FILE *f)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}/*==============中断接收和变量的封装====================*/
//对Serial_RxFlag变量封装get函数,实现读后自动清除的作用
uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1){Serial_RxFlag = 0;return 1;}return 0;
}
//对Serial_RxData变量封装get函数
uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}
//中断函数的名字在启动文件里面(startup_stm32f10x_md.s)
void USART1_IRQHandler(void)
{//先判断标志位if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){//将接收寄存器里的数据放到自定义变量里Serial_RxData = USART_ReceiveData(USART1);//读完数据后置标志位1Serial_RxFlag = 1;//如果读取DR,则自动清除标志位,否则,手动清除标志位,此处手动清除没影响USART_ClearITPendingBit(USART1, USART_IT_RXNE);  }
}
/*==========================================================*/
5-3-3 Serial.h
#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);#endif

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

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

相关文章

docker完成redis 三主三从

文章目录 关闭防火墙启动docker后台服务新建6个docker容器redis实例创建并运行docker容器实例 进入容器redis-node-1并为6台机器构建集群关系链接进入6381作为切入点&#xff0c;查看集群状态主从容错切换迁移案例容错切换迁移 主从扩容案例为主节点6387分配从节点6388主从缩容…

一、MOJO环境部署和安装

以Ubuntu系统为例。 安装mojo-CLI curl https://get.modular.com | MODULAR_AUTHmut_fe303dc5ca504bc4867a1db20d897fd8 sh - 安装mojo SDK modular auth mojo modular auth install mojo 查看mojo版本号 mojo --version 输入mojo指令&#xff0c;进入交互编程窗口

On the Robustness of Backdoor-based Watermarkingin Deep Neural Networks

关于深度神经网络中基于后门的数字水印的鲁棒性 ABSTRACT 在过去的几年中&#xff0c;数字水印算法已被引入&#xff0c;用于保护深度学习模型免受未经授权的重新分发。我们调查了最新深度神经网络水印方案的鲁棒性和可靠性。我们专注于基于后门的水印技术&#xff0c;并提出了…

6、C语言:输入与输出

输入输出 标准输入输出getchar&putchar函数printf函数sprintf函数格式化输入——scanf函数 文件访问文件读写 错误处理&#xff1a;stderr和exit行输入和行输出常用函数字符串操作函数字符类别测试和转换函数存储管理函数数学函数随机数发生器函数其他 标准输入输出 getch…

2024年【氧化工艺】免费试题及氧化工艺作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 氧化工艺免费试题根据新氧化工艺考试大纲要求&#xff0c;安全生产模拟考试一点通将氧化工艺模拟考试试题进行汇编&#xff0c;组成一套氧化工艺全真模拟考试试题&#xff0c;学员可通过氧化工艺作业模拟考试全真模拟…

洛谷 P1439 【模板】最长公共子序列【线性dp+dp模型转换】

原题链接&#xff1a;https://www.luogu.com.cn/problem/P1439 题目描述 给出 1,2,…,n 的两个排列 P1​ 和 P2​ &#xff0c;求它们的最长公共子序列。 输入格式 第一行是一个数 n。 接下来两行&#xff0c;每行为 n 个数&#xff0c;为自然数 1,2,…,n 的一个排列。 输…

2023 年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷 B部分解析

2022 年全国职业院校技能大赛高职组云计算赛项试卷部分解析 【赛程名称】第一场&#xff1a;模块一 私有云、模块二 容器云【任务 1】私有云服务搭建[5 分]【题目 1】1.1.1 基础环境配置[0.2 分]【题目 2】1.1.2 Yum 源配置[0.2 分]【题目 3】1.1.3 配置无秘钥 ssh[0.2 分]【题…

Keil5如何生成反汇编文件

Keil5如何生成反汇编文件 在Keil5界面下点击选项&#xff0c;选择“User”&#xff0c;勾选“After Build/Rebuild”中“RUN #1”&#xff0c;复制fromelf --text -a -c --outputxxx.dis xxx.axf 在Linker栏中找到“Linker Control string”里最后-o后的.axf文件&#xff0c;将…

Linux:nginx设置网站https

http和https的区别 http: 80 https: 443 这种协议比http协议要安全&#xff0c;因为传输数据是经过加密的 HTTPS简介 HTTPS其实是有两部分组成&#xff1a;HTTP SSL / TLS&#xff0c;也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过…

Nginx的安装配置和使用

最近有好几个地方用到了nginx&#xff0c;但是一直还没时间记录下nginx的安装、配置和使用&#xff0c;这篇文章可以将这块内容整理出来&#xff0c;方便大家一起学习~ 安装 安装是相对简单一些的&#xff0c;直接使用yum即可。 yum install -y nginx 默认安装位置在/usr/sb…

Linux------进程的初步了解

目录 一、什么是进程 二、进程的标识符pid 三、getpid 得到进程的PID 四、kill 终止进程 五、父进程与子进程 六、目录中的进程 一、什么是进程 在windows中&#xff0c;我们查看进程很简单&#xff0c;打开任务管理器&#xff0c;就可以看到在运行的进程。这里我们还可以…

STM32H5 Nucleo-144 board开箱

文章目录 开发板资料下载 【目标】 点亮LD1&#xff08;绿&#xff09;、LD2&#xff08;黄&#xff09;和LD3&#xff08;红&#xff09;三个LED灯 【开箱过程】 博主使用的是STM32CubeMX配置生成代码&#xff0c;具体操作如下&#xff1a; 打开STM32CubeMX&#xff0c;File-…

Raspberry Pi 4B 蓝牙串口(SPP)配置与使用

Raspberry Pi 4B 蓝牙串口&#xff08;SPP&#xff09;配置与使用 文章目录 Raspberry Pi 4B 蓝牙串口&#xff08;SPP&#xff09;配置与使用1、蓝牙相关命令工具2、Linux中的蓝牙堆栈3、蓝牙串口配置4、蓝牙串口数据发送与接收 本文将详细介绍如何在Raspberry Pi 4B卡片电脑中…

快速入门java网络编程基础------Nio

一. NIO 基础 哔哩哔哩黑马程序员 netty实战视频 0.什么是nio&#xff1f; NIO&#xff08;New I/O&#xff09;是Java中提供的一种基于通道和缓冲区的I/O&#xff08;Input/Output&#xff09;模型。它是相对于传统的IO&#xff08;InputStream和OutputStream&#xff09;模型…

Spring boot - Task Execution and Scheduling @Async

SpringBoot的任务执行器 Spring Boot通过auto-configuration机制自动创建了任务执行器Task Execution&#xff0c;因此在SpringBoot项目中&#xff0c;你不需要任何配置、也不需要自己创建Task Execution就可以直接使用它。 Spring Boot通过auto-configuration机制创建的任务…

nodejs+vue+ElementUi银行贷款业务管理系统

银行贷款管理系统的主要实现功能包括&#xff1a;管理员&#xff1a;首页、个人中心、用户管理、银行管理、贷款信息管理、贷款申请管理、金额发布管理、还款信息管理、通知信息管理&#xff0c;用户&#xff1a;首页、个人中心、贷款信息管理、贷款申请管理、金额发布管理、还…

phpinfo和php -m 加载的php.ini不一致

目的&#xff1a; 将phpinfo在web中展示的php.ini和在命令行中展示的php.ini加载路径设置一致。 原本的php.ini加载路劲是&#xff1a; /usr/local/lib/php.ini 解决思路&#xff1a; &#xff08;1&#xff09;which php 查看服务器加载的php的位置&#xff0c;这里原来是&a…

差分算法模板

差分算法模板 一维差分一维insert函数(构造差分数组和实现区域加数操作)一维差分模板题 二维差分二维insert函数(构造差分数组和实现区域加数操作)二维差分模板题 一维差分 差分主要是计算出某个区域段的数分别加上一个数 先给定一个原数组a&#xff1a;a[1], a[2], a[3], a[n]…

CNN:Convolutional Neural Network(上)

目录 1 为什么使用 CNN 处理图像 2 CNN 的整体结构 2.1 Convolution 2.2 Colorful image 3 Convolution v.s. Fully Connected 4 Max Pooling 5 Flatten 6 CNN in Keras 原视频&#xff1a;李宏毅 2020&#xff1a;Convolutional Neural Network 1 为什么使用…

NumPy:从初识到实战,探索Python科学计算的无限可能

NumPy 在浩瀚的Python编程世界中&#xff0c;有一个强大的库如星辰般璀璨&#xff0c;它是数据科学家、机器学习工程师乃至量化金融分析师手中的利器——NumPy&#xff0c;它以其高效的数据处理能力和便捷的矩阵运算机制&#xff0c;在科研与工程领域中占据着举足轻重的地位。…