江协科技STM32学习- P29 实验- 串口收发HEX数据包/文本数据包

       🚀write in front🚀  
🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​ 

💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚 

🚀Projeet source code🚀   

💾工程代码放在了本人的Gitee仓库:iPickCan (iPickCan) - Gitee.com

引用:

STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili

Keil5 MDK版 下载与安装教程(STM32单片机编程软件)_mdk528-CSDN博客

STM32之Keil5 MDK的安装与下载_keil5下载程序到单片机stm32-CSDN博客

0. 江协科技/江科大-STM32入门教程-各章节详细笔记-查阅传送门-STM32标准库开发_江协科技stm32笔记-CSDN博客

【STM32】江科大STM32学习笔记汇总(已完结)_stm32江科大笔记-CSDN博客

江科大STM32学习笔记(上)_stm32博客-CSDN博客

STM32学习笔记一(基于标准库学习)_电平输出推免-CSDN博客

STM32 MCU学习资源-CSDN博客

stm32学习笔记-作者: Vera工程师养成记

stem32江科大自学笔记-CSDN博客

术语:

英文缩写描述
GPIO:General Purpose Input Onuput通用输入输出
AFIO:Alternate Function Input Output复用输入输出
AO:Analog Output模拟输出
DO:Digital Output数字输出
内部时钟源 CK_INT:Clock Internal内部时钟源
外部时钟源 ETR:External Trigger 时钟源 External 触发
外部时钟源 ETR:External Trigger mode 1外部时钟源 External 触发 时钟模式1
外部时钟源 ETR:External Trigger mode 2外部时钟源 External 触发 时钟模式2
外部时钟源 ITRx:Internal Trigger inputs外部时钟源,ITRx (Internal trigger inputs)内部触发输入
外部时钟源 TIx:exTernal Input pin 外部时钟源 TIx (external input pin)外部输入引脚
CCR:Capture/Comapre Register捕获/比较寄存器
OC:Output Compare输出比较
IC:Input Capture输入捕获
TI1FP1:TI1 Filter Polarity 1Extern Input 1 Filter Polarity 1,外部输入1滤波极性1
TI1FP2:TI1 Filter Polarity 2Extern Input 1 Filter Polarity 2,外部输入1滤波极性2
DMA:Direct Memory Access直接存储器存取

正文:

0. 概述

从 2024/06/12 定下计划开始学习下江协科技STM32课程,接下来将会按照哔站上江协科技STM32的教学视频来学习入门STM32 开发,本文是视频教程 P2 STM32简介一讲的笔记。

本节我们来写一下串口收发数据包的代码

1.🚚第一个代码:串口收发HEX数据包

接线图

和上节的接线基本一样,只是在PB1口接了一个按键,用于控制。

我们在上节的Serial.c文件里加上HEX收发数据包的部分,定义的格式就和上一篇博客中说的HEX数据包接收固定包长,含包头包尾的这个思路一样,就按这个写状态机的思路写。

为了收发数据包,我们先定义两个缓冲区的数组。

这四个数据只存储发送或接收的载荷数据,包头包尾就不存了。

初始化的代码都不需要更改,把上节的这个函数删掉

然后我们先写一个send packet的函数。我们想要的效果是调用一下这个函数,Tx packet数组的四个数据就会自动加上包头报尾发送出去。

void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArry(Serial_TxPacket, 4);
	Serial_SendByte(0xFE);
}

实验结果:

接下来我们就来写一下接收数据包的代码

首先在接收中断函数里,我们就需要用状态机来执行接收逻辑了,这就按上面那个状态转移图来写。

首先我们要定义一个标志当前状态的变量s,在中断这里,我们可以在函数里面定义一个静态变量RxState当成这个状态变量s

然后根RxState的不同,需要进入不同的处理程序。

📤️📤️注意:这里一定是要用else if,如果只用3个并列的If,可能在状态转移的时候会出现问题,比如在状态0,你想转移的状态1就置RxState等于1,结果就会造成下面状态1的条件就立马满足了,这样会出现连续两个if都同时成立的情况,这个情况我们不希望出现。

🎵🎵🎵

所以这里使用else if,保证每次进来之后,只能选择执行其中一个状态的代码,或者你用switch case语句,也可以保证只有一个条件满足。

这就是状态选择的部分。然后就依次写每个状态执行的操作和状态转移条件就行了。

🔊🔊🔊这个程序还隐藏有一个问题,就是这个Serial_RxPacket数组,它是一个同时被写入,又同时被读出的数组。

🔊🔊🔊在中断函数里,我们会依次写入它,在主函数里,我们又会依次读出它。这会造成数据包之间可能会混在一起。比如读出的过程太慢了,前面两个数据刚读出来,等了一会儿才继续往后读取。这时后面的数据就有可能会刷新为下一个数据包的数据,也就是读出的数据可能一部分属于上一个数据包,另一部分属于下一个数据包

🔋🔋解决方法可以在接收部分加入判断,就是在每个数据包读取处理完毕后,再接收下一个数据包。当然,很多情况下其实还可以不进行处理,像这种hex数据包多是用于传输各种传感器的每个独立数据,比如陀螺仪的xyz轴数据,温湿度数据等等,它们相邻数据包之间的数据具有连续性,这样即使相邻数据包混在一起了,也没关系。所以这种情况下就不需要关心这个问题,具体到底怎么处理,还需要大家结合实际情况来操作了,这里就提一下这个可能存在的问题。大家了解一下就行了。

我们这个收发hex数据包的程序大概就讲完了。

接下来加上按键部分的代码,现象是按一下按键变换一下数据,发送到串口助手上。

定义一个变量

然后在主函数中实现按键的控制就行

UART.c

#include "stm32f10x.h"                  // Device header
#include "Uart.h"
#include <stdio.h>
#include <stdarg.h>

void UART_Init(void)
{
	
	//RCC使能外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //RCC使能UART时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //RCC使能GPIOA时钟
	
	//配置GPIO
	GPIO_InitTypeDef gpioInitStructure;
	gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		//GPIO为复用推挽输出模式
	gpioInitStructure.GPIO_Pin = GPIO_Pin_9;			//GPIOA_Pin9为UART1_Tx
	gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStructure);
	
	gpioInitStructure.GPIO_Mode = GPIO_Mode_IPU;		//GPIO为上拉输入
	gpioInitStructure.GPIO_Pin = GPIO_Pin_10;			//GPIOA_Pin9为UART1_Rx
	gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStructure);
	
	//配置UART
	USART_InitTypeDef USART_InitStruct;
	USART_StructInit(&USART_InitStruct);
	
	USART_InitStruct.USART_BaudRate = 9600;
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//不使用UART硬件流控
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;		//UART使能Tx发送
	USART_InitStruct.USART_Parity = USART_Parity_No;	//UART无奇偶校验
	USART_InitStruct.USART_StopBits = USART_StopBits_1;	//1位停止位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStruct);
	
	//使能UART中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	//NVIC配置UART中断优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;		//使能UART1_IRQ中断
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);
	
	
	//使能UART
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t data)
{
	USART_SendData(USART1, data);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待UART TXE标志位
	//写入之后等待TXE标志位置1,表示数据从TDR寄存器转移到了发送移位寄存器
	//如果不等待TDR数据移动到发送移位寄存器,下次写时就会覆盖上一次数据
	//该标志位在写DR寄存器时自动清除
}

void Serial_SendArry(uint8_t data[], uint8_t length)
{
	for(int i=0; i<length; i++)
	{
		Serial_SendByte(data[i]);
	}
}

void Serial_SendString(char *str)
{
	if(str)
	{
		while(*str != '\0')
		{
			Serial_SendByte(*str++);
		}
	}
}

uint32_t Serial_Power(uint32_t x, uint32_t y)
{
	uint32_t ret = 1;
	
	while(y > 0)
	{
		ret *= x;
		y--;
	}

	return ret;
}

void Serial_SendNumber(uint32_t number, uint16_t length)
{
	int i = 0;
	uint8_t data;
	
	for(i=0; i<length; i++)
	{
		data = number/Serial_Power(10, length - i -1)%10 + '0';
		Serial_SendByte(data);
	}
}

/* 重写fputc()函数,重定向printf()到串口
 *
 */
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	
	return ch;
}



void Serial_Printf(char *format, ...)
{
	char buf[128];
	va_list arg;
	va_start(arg, format);
	vsprintf(buf, format, arg);
	va_end(arg);
	Serial_SendString(buf);
}

volatile uint8_t Seial_RxFlag = 0;
uint8_t Serial_RxPacket[4];
uint8_t Serial_TxPacket[4];



//中断服务函数
void USART1_IRQHandler()
{
	static uint8_t Uart_State;
	static uint8_t pRxPacket = 0;;
	uint8_t Seial_Data = 0;
	
	Seial_Data = USART_ReceiveData(USART1);
	
	if(Uart_State == 0)
	{
		if(Seial_Data == 0xFF)
		{
			Uart_State = 1;
		}
	}
	else if(Uart_State == 1)
	{
		Serial_RxPacket[pRxPacket] = Seial_Data;
		pRxPacket++;
		if(pRxPacket >= 4)
		{
			pRxPacket = 0;
			Uart_State = 2;
		}
	}
	else if(Uart_State == 2)
	{
		if(Seial_Data == 0xFE)
		{
			Uart_State = 0;
			Seial_RxFlag = 1;
		}
	}
	
	//清除UART RXNE 标志位
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

uint8_t Serial_GetRxFlag(void)
{
	uint8_t ret = 0;
	
	if(Seial_RxFlag)
	{
		ret = 1;
		Seial_RxFlag = 0;
	}
	
	return ret;
}

void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArry(Serial_TxPacket, 4);
	Serial_SendByte(0xFE);
}

man.c

#include "stm32f10x.h"                  // Device header
#include "oled.h"
#include "Countersensor.h"
#include "Encoder.h"
#include "Timer.h"
#include "AD.h"
#include "Delay.h"
#include "MyDMA.h"
#include "UART.h"
#include <stdio.h>

extern uint16_t Num;


int main(int argc, char *argv[])
{
	OLED_Init();
	OLED_ShowString(1, 1, "UART:");
	OLED_ShowString(1, 1, "           ");
	
	UART_Init();
	
	//printf("Hello World\r\n");
	//OLED_ShowString(2, 1, "RX:");
	
	Serial_TxPacket[0] = 0x01;
	Serial_TxPacket[1] = 0x02;
	Serial_TxPacket[2] = 0x03;
	Serial_TxPacket[3] = 0x04;
	Serial_SendPacket();
	
	while(1)                                                                                 
	{
		if(Serial_GetRxFlag() == 1)
		{
			OLED_ShowHexNum(1, 1, Serial_RxPacket[0], 2);
			OLED_ShowHexNum(1, 4, Serial_RxPacket[1], 2);
			OLED_ShowHexNum(1, 7, Serial_RxPacket[2], 2);
			OLED_ShowHexNum(1, 11, Serial_RxPacket[3], 2);
		}
	}
	
	return 1;
}

实验现象:

实验改进2,按下按键收发送数据:

main.c

#include "stm32f10x.h"                  // Device header
#include "oled.h"
#include "Countersensor.h"
#include "Encoder.h"
#include "Timer.h"
#include "AD.h"
#include "Delay.h"
#include "MyDMA.h"
#include "UART.h"
#include <stdio.h>
#include "Key.h"

extern uint16_t Num;


int main(int argc, char *argv[])
{
	OLED_Init();
	Key_Init();
	
	OLED_ShowString(1, 1, "UART:");
	OLED_ShowString(1, 1, "           ");
	
	UART_Init();
	
	//printf("Hello World\r\n");
	//OLED_ShowString(2, 1, "RX:");
	
	Serial_TxPacket[0] = 0x01;
	Serial_TxPacket[1] = 0x02;
	Serial_TxPacket[2] = 0x03;
	Serial_TxPacket[3] = 0x04;
	Serial_SendPacket();
	
	uint8_t Key_Num = 0;
	
	while(1)                                                                                 
	{
		
		Key_Num = Key_GetNum();
		if(Key_Num == 1)
		{
			Serial_TxPacket[0]++;
			Serial_TxPacket[1]++;
			Serial_TxPacket[2]++;
			Serial_TxPacket[3]++;
			
			OLED_ShowString(1, 1, "Tx Packet:");
			OLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);
			OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);
			OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);
			OLED_ShowHexNum(2, 11, Serial_TxPacket[3], 2);
		}
		
		if(Serial_GetRxFlag() == 1)
		{
			OLED_ShowString(3, 1, "Rx Packet:");
			OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);
			OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);
			OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);
			OLED_ShowHexNum(4, 11, Serial_RxPacket[3], 2);
		}
	}
	
	return 1;
}

实验结果:

2🚚.第二个程序:串口收发文本数据包

接线图:

在PA1口接了一个LED,用于指示。

我们在上一个工程的基础上改,按键部分的代码就不要了。

接下来就按上节讲过的文本数据包接收的思路来写,这里是可变包长,含包头包尾。

我们这里就只写接收的部分,因为发送的话不方便像hex数组一样一个个更改的。所以发送就直接在主函数里sendstring或者printf就行了,非常简单。

所以这个发送数据包的函数就不要了

接收部分我们来来实现一下。

数组的长度给多点,防止溢出,给个100,这要求单条指令最长不能超过一百个字符。

之后是中断的状态机部分,参考上面状态转移图写。

接下来就把LED部分的代码加进来就行

先是判断字符串是不是等于我们规定的指令再执行相应的操作。判断字符串要用到字符串处理函数,要包含头文件#include "string.h"。

在这里我们判断两个字符串是否相等,需要用到strcmp函数,如果不知道这个函数的用法可以去翻一下我的C语言复习专栏,在这篇博文中我详细介绍了字符串处理函数。

🔊🔊还有个问题需要说明,同样还是之前的个问题。如果连续发送数据包程序处理不及时,可能导致数据包错位

🔊🔊在这里,文本数据包,每个数据包是独立的,不存在连续,这如果错位了问题就比较大。所以在程序这里我们可以修改一下,等每次处理完成之后,再开始接收下一个数据包

我们可以这样在中断函数中等待包头的时候再加一个条件,如果数据等于包头并且Serial_RxFlag等于等于0才执行接收,否则就是发的太快了,还没处理完,就跳过这个数据包。

然后上面这个读取标志位之后立刻清零的函数先删掉。

运行结果

UART.c

#include "stm32f10x.h"                  // Device header
#include "Uart.h"
#include <stdio.h>
#include <stdarg.h>

void UART_Init(void)
{
	
	//RCC使能外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //RCC使能UART时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //RCC使能GPIOA时钟
	
	//配置GPIO
	GPIO_InitTypeDef gpioInitStructure;
	gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		//GPIO为复用推挽输出模式
	gpioInitStructure.GPIO_Pin = GPIO_Pin_9;			//GPIOA_Pin9为UART1_Tx
	gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStructure);
	
	gpioInitStructure.GPIO_Mode = GPIO_Mode_IPU;		//GPIO为上拉输入
	gpioInitStructure.GPIO_Pin = GPIO_Pin_10;			//GPIOA_Pin9为UART1_Rx
	gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStructure);
	
	//配置UART
	USART_InitTypeDef USART_InitStruct;
	USART_StructInit(&USART_InitStruct);
	
	USART_InitStruct.USART_BaudRate = 9600;
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//不使用UART硬件流控
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;		//UART使能Tx发送
	USART_InitStruct.USART_Parity = USART_Parity_No;	//UART无奇偶校验
	USART_InitStruct.USART_StopBits = USART_StopBits_1;	//1位停止位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStruct);
	
	//使能UART中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	//NVIC配置UART中断优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;		//使能UART1_IRQ中断
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);
	
	
	//使能UART
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t data)
{
	USART_SendData(USART1, data);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待UART TXE标志位
	//写入之后等待TXE标志位置1,表示数据从TDR寄存器转移到了发送移位寄存器
	//如果不等待TDR数据移动到发送移位寄存器,下次写时就会覆盖上一次数据
	//该标志位在写DR寄存器时自动清除
}

void Serial_SendArry(uint8_t data[], uint8_t length)
{
	for(int i=0; i<length; i++)
	{
		Serial_SendByte(data[i]);
	}
}

void Serial_SendString(char *str)
{
	if(str)
	{
		while(*str != '\0')
		{
			Serial_SendByte(*str++);
		}
	}
}

uint32_t Serial_Power(uint32_t x, uint32_t y)
{
	uint32_t ret = 1;
	
	while(y > 0)
	{
		ret *= x;
		y--;
	}

	return ret;
}

void Serial_SendNumber(uint32_t number, uint16_t length)
{
	int i = 0;
	uint8_t data;
	
	for(i=0; i<length; i++)
	{
		data = number/Serial_Power(10, length - i -1)%10 + '0';
		Serial_SendByte(data);
	}
}

/* 重写fputc()函数,重定向printf()到串口
 *
 */
int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	
	return ch;
}



void Serial_Printf(char *format, ...)
{
	char buf[128];
	va_list arg;
	va_start(arg, format);
	vsprintf(buf, format, arg);
	va_end(arg);
	Serial_SendString(buf);
}

volatile uint8_t Seial_RxFlag = 0;
uint8_t Serial_RxPacket[128];
uint8_t Serial_TxPacket[4];



//中断服务函数
void USART1_IRQHandler()
{
	static uint8_t Uart_State = 0;
	static uint8_t pRxPacket = 0;;
	uint8_t Seial_Data = 0;
	
	Seial_Data = USART_ReceiveData(USART1);
	
	if(Uart_State == 0)
	{
		if(Seial_Data == '@')
		{
			Uart_State = 1;
		}
	}
	else if(Uart_State == 1)
	{
		if(Seial_Data == '\r')
		{
			Uart_State = 2;
			Serial_RxPacket[pRxPacket] = '\0';
			pRxPacket = 0;
		}
		else{
			Serial_RxPacket[pRxPacket] = Seial_Data;
			pRxPacket++;
		}
	}
	else if(Uart_State == 2)
	{
		if(Seial_Data == '\n')
		{
			Uart_State = 0;
			Seial_RxFlag = 1;
		}
	}
	
	//清除UART RXNE 标志位
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

uint8_t Serial_GetRxFlag(void)
{
	uint8_t ret = 0;
	
	if(Seial_RxFlag)
	{
		ret = 1;
		Seial_RxFlag = 0;
	}
	
	return ret;
}

void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArry(Serial_TxPacket, 4);
	Serial_SendByte(0xFE);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "oled.h"
#include "Countersensor.h"
#include "Encoder.h"
#include "Timer.h"
#include "AD.h"
#include "Delay.h"
#include "MyDMA.h"
#include "UART.h"
#include <stdio.h>
#include "Key.h"
#include "String.h"
#include "LED.h"

extern uint16_t Num;


int main(int argc, char *argv[])
{
	OLED_Init();
	Key_Init();
	LED_Init();
	
	OLED_ShowString(1, 1, "Rx:");
	
	
	UART_Init();
	
	//Serial_SendPacket();
	
	uint8_t Key_Num = 0;
	
	
	Serial_SendString("UART TEST\r\n");
	
	while(1)                                                                                 
	{
		
		if(Serial_GetRxFlag() == 1)
		{
			OLED_ShowString(2, 1, (char *)Serial_RxPacket);
			if(strcmp((char *)Serial_RxPacket, "LED_ON") == 0)
			{
				OLED_ShowString(3, 1, "                ");
				OLED_ShowString(3, 1, "LED_ON_OK");
				Serial_SendString("LED_ON_OK");
				LED1_On();
			}
			else if(strcmp((char *)Serial_RxPacket, "LED_OFF") == 0)
			{
				OLED_ShowString(3, 1, "                ");
				OLED_ShowString(3, 1, "LED_OFF_OK");
				Serial_SendString("LED_OFF_OK");
				LED1_Off();
			}
			else
			{
				OLED_ShowString(3, 1, "                ");
				OLED_ShowString(3, 1, "UN_SUPPORT_CMD");
				Serial_SendString("UN_SUPPORT_CMD");
			}
		}
	}
	
	return 1;
}

这就是我们第二个程序的现象。

本节的内容到这里就结束了,下节继续。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Quartz的使用

1.准备工作 建立Maven工程 2.引入Quartz的jar包 <dependencies><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency></dependencies>3…

黑马官网最新2024前端就业课V8.5笔记---CSS篇(2)

盒子模型 画盒子 目标:使用合适的选择器画盒子 新属性 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vi…

单片机串口接收状态机STM32

单片机串口接收状态机stm32 前言 项目的芯片stm32转国产&#xff0c;国产芯片的串口DMA接收功能测试不通过&#xff0c;所以要由原本很容易配置的串口空闲中断触发DMA接收数据的方式转为串口逐字节接收的状态机接收数据 两种方式各有优劣&#xff0c;不过我的芯片已经主频跑…

Android Studio 安装过程

以前用 Eclipse 开发&#xff0c;最近尝试 Android Studio 开发&#xff0c;发现 Android Studio 比 Eclipse 速度快多了&#xff0c;下面是安装 Android Studio 过程日志。 Gradle 下载地址&#xff1a;https://services.gradle.org/distributions/ https://developer.andro…

github.io出现的问题及解决方案

1. 你的连接不是专用连接 放假回家后打开自己的博客&#xff0c;发现无法打开博客&#xff0c;一开始以为是调样式时不小心搞坏了&#xff0c;打开别人的githunb.io博客发现都会出问题&#xff0c;并且用手机不连接wifi可以正常打开 解决办法&#xff1a; 方法一&#xff1a; …

商场应急管理措施和预案|基于springboot+vue的大型商场应急预案管理系统(源码+数据库+文档)

商场应急管理系统 目录 基于springbootvue的大型商场应急预案管理系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&…

【ACM出版,EI稳定检索】2024年人工智能、数字媒体技术与交互设计国际学术会议(ICADI 2024,11月29-12月1日)

2024年人工智能、数字媒体技术与交互设计国际学术会议&#xff08;ICADI 2024) 2024 International Conference on Artificial Intelligence, Digital Media Technology and Interaction Design 官方信息 会议官网&#xff1a;www.icadi.net 2024 International Conference o…

【Linux】命令行参数 | 环境变量

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 前几天在搞硬件&…

Stable diffusion 3.5本地运行环境配置记录

1.环境配置 创建虚环境 conda create -n sd3.5 python3.10Pytorch(>2.0) conda install pytorch2.2.2 torchvision0.17.2 torchaudio2.2.2 pytorch-cuda12.1 -c pytorch -c nvidiaJupyter能使用Anaconda虚环境 conda install ipykernel python -m ipykernel install --user …

CODESYS可视化星三角降压启动程序控制电气动画图

#一个用CODESYS可视化做的星三角降压启动程序控制电气动画图# 前言: 关于星三角降压启动控制,作为电气行业入门的必备知识点,涉及到电机本身特性导致的电压,电流(转矩),功率和转速等一系列的关系和变化,以及星型和三角形的绕组方式。本篇我们使用CODESYS结合程序和可视…

安装fpm,解决*.deb=> *.rpm

要从生成 .deb 包转换为 .rpm 包&#xff0c;可以按照以下步骤修改打包脚本 1. 使用 fpm 工具 fpm 是一个强大的跨平台打包工具&#xff0c;可以将 .deb 包重新打包成 .rpm&#xff0c;也可以直接从源文件打包成 .rpm。 安装 fpm sudo apt-get install ruby-dev sudo gem in…

C#的Event事件示例小白级剖析

1、委托Delegate 首先说一下delegate委托&#xff0c;委托是将方法作为参数进行传递。 // 定义了一个委托类型public delegate void MyDelegate(int num);// 定义了一个啥也不干的委托实例public MyDelegate m_delegate _ > {};// 定义了一个和委托相同格式的方法public …

力扣排序350题 两个元组的交集2

题目&#xff1a; 给你两个整数数组 nums1 和 nums2 &#xff0c;请你以数组形式返回两 数组的交集。返回结果中每个元素出现的次数&#xff0c;应与元素在两个 数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取 较小值&#xff09;。可以不考虑输出…

善用Git LFS来降低模型文件对磁盘的占用

将讲一个实际的例子&#xff1a;对于模型文件&#xff0c;动辄就是好几个G&#xff0c;而有的仓库更是高达几十G&#xff0c;拉一个仓库到本地&#xff0c;稍不注意直接磁盘拉满都有可能。 比如&#xff1a;meta-llama-3.1-8b-instruct&#xff0c;拉到本地后发现居然占用了60G…

CentOS 磁盘扩容

1. 查看要扩展的磁盘 df -h这个就是要扩展的磁盘空间&#xff0c;记住名称&#xff0c;后面会用到 2. 查看所有磁盘信息 fdisk -llsblk可以发现&#xff0c;500G 的硬盘已经安装到服务器但是没被使用&#xff0c;此时需要操作这块硬盘 3. 创建分区 fdisk /dev/vdb根据流程…

js中怎么把excel和pdf文件转换成图片打包下载

index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>文件转图片工具</title><!-- 本…

【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期

目录 1. start() (1) start() 的性质 (2) start() 和 Thread类 的关系 2. 终止一个线程 (1)通过共享的标记结束线程 1. 通过共享的标记结束线程 2. 关于 lamda 表达式的“变量捕获” (2) 调用interrupt()方法 1. isInterrupted() 2. currentThread() …

Metasploit渗透测试之在云服务器中使用MSF

概述 随着云计算的发展&#xff0c;对基于云的应用程序、服务和基础设施的测试也在不断增加。在对云部署进行渗透测试时&#xff0c;最大的问题之一是共享所有权。过去&#xff0c;在进行渗透测试时&#xff0c;企业会拥有网络上的所有组件&#xff0c;我们可以对它们进行全部…

2016年7月和8月NASA的气候成像(ATom)-1飞行活动期间测量的黑碳(BC)质量混合比(单位为ng BC / kg空气)

目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 简介 ATom: Black Carbon Mass Mixing Ratios from ATom-1 Flights 该数据集提供了在2016年7月和8月NASA的气候成像&#xff08;ATom&#xff09;-1飞行活动期间测量的黑碳&#xff08;BC&#xff09;质量混合比&…

关于各链 Meme Launchpad

随着Web3生态的迅猛发展&#xff0c;区块链领域诞生了大量创意无限的meme项目&#xff0c;逐渐引起了广泛关注。这些meme项目不仅展示了加密社区的活力与创造力&#xff0c;也为投资者提供了新的机会和玩法。 然而&#xff0c;meme项目的快速崛起也带来了筛选优质项目和发现市场…