CanFestival移植到STM32 F4芯片(基于HAL库)

本文讲述如何通过简单操作就可以把CanFestival库移植到STM32 F4芯片上,作为Slave设备。使用启明欣欣的工控板来做实验。


一 硬件连接

观察CAN报文需要专门的设备,本人从某宝上买了一个兼容PCAN的开源小板子,二十几块钱,通过USB接到电脑后就可以使用PCAN-View打开进行监控,非常方便,同时还带开关控制的120欧姆终端电阻,缺点是有时不太稳定,

![[Pasted image 20240831172709.png]]

这个小板子还需要通过CAN线和启明欣欣板子上的CAN口进行连接,如下图,这里连接的是CAN2,

![[Pasted image 20240831173148.png]]

工控板需要单独供电,不能依靠下载器的电,否则无法正常运行。最后打开小板子上的120欧姆电阻,开关拨到ON那一端就可以了。

PS:PCAN-View可以去PeakCAN官网下载,是免费软件;CAN线得是双绞线,H对H,L对L进行连接。


二 搭建CAN基础工程

硬件搭建好之后,先搭建一个CAN的基础工程,验证是否可以收发CAN消息,为后续移植打下基础。这里使用STM32CubeMX来操作。

打开STM32CubeMX,芯片选择STM32F407ZGT6,选好后创建工程。

配置时钟

在新界面里的Pinout & Configuration里选择RCC,然后高速时钟和低速时钟都选择Crystal/Ceramic Resonator

![[Pasted image 20240831181308.png]]

PS:启明欣欣的板子,其外部接了2个晶振,一个8M,一个32.768K,前者用于高速时钟,后者用于低速时钟,如果低速时钟没有外接晶振,那么就选disable。

此时点击Clock Configuration

![[Pasted image 20240831181611.png]]

然后按照红框里的步骤一个个更改,

![[Pasted image 20240831181644.png]]

第4步输入频率168后回车,CubeMX会自动调整,非常方便。另外,可以看到低速时钟LSE的输入频率是32.768K,这个也可以修改,需要结合实际。

这里要注意一下:配置完毕后APB1外设时钟是42M,APB1定时器时钟是84M,后面要用到。

设置SYS

回到Pinout & Configuration,然后点击SYS,右侧的选项按照如下进行选择,

![[Pasted image 20240831181843.png]]

PS:由于没有使用操作系统,所以这里的Timebase Source选择SysTick

开启CAN2

启明欣欣的CAN2对应的是PB12和PB13,其中PB12是RX,PB13是TX,先在Pinout view里右下角的搜索框中输入PB12,然后回车,就可以找到PB12,会闪烁,

![[Pasted image 20240831182433.png]]

点击该引脚,功能选择CAN2_RX,

![[Pasted image 20240831182632.png]]

同理找到PB13,将其设置为CAN2_TX,设置OK后会发现CAN2已经自动使能了。

![[Pasted image 20240831185148.png]]

这里设置一下CAN的通信速率,本教程使用500K,设置如上图红框,

  • Prescaler设置为6
  • Time Quanta in Bit Segment 1设置为7
  • Time Quanta in Bit Segment 2设置为6
  • ReSynchronization Jump Width设置为1

经过上述设置后,CAN的波特率就变成500K了。

设置原理:前面配置时钟时,APB1的外设时钟是42M,而CAN是属于APB1的外设,这样经过Prescaler的变频后就变成42M/6=7M,也就是7000K,然后除以(Time Quanta in Bit Segment 1 + Time Quanta in Bit Segment 2 + ReSynchronization Jump Width * 1),也就是7000K/14=500K

芯片手册上的波特率的计算原理如下,

![[Pasted image 20240831185438.png]]

可以看出上述配置并不是唯一选择,只要根据原理让波特率是500K就可以了。

最后是开启CAN2的接收中断,如下红框,勾选CAN2 RX0中断,

![[Pasted image 20240831185918.png]]

PS:RX0和RX1分别对应2个内部接收FIFO,这里选择FIFO0,后面会讲到如何设置

生成Keil工程

配置完毕,最后生成工程。

点击Project Manager,然后在Project里对红框标注的地方进行自定义修改

![[Pasted image 20240818090956.png]]

接着是Code Generator,按照如下勾选,也可以根据自己需要进行修改

![[Pasted image 20240818091151.png]]

设置完毕后点击右上角的GENERATE CODE来生成Keil工程

PS:Keil现在有社区版,个人使用是免费的,不用去破解了。

验证CAN通信

打开生成的Keil工程,然后先做以下配置,

  • 编译器使用V6版本

    ![[Pasted image 20240831190813.png]]

    如果使用的是老版的Keil,可能还得用V5版本的编译器

  • 取消勾选Browse Information,节约编译时间

    ![[Pasted image 20240831190907.png]]

  • 编译优化选项选择O1或O0,优化选项过高可能会造成调试时无法打断点

    ![[Pasted image 20240831190940.png]]

配置好之后,编译一下,保证工程可以顺利编译完成。

剩下是修改代码,主要参考这篇文章,不过该作者用的CAN1,这里再写一遍,在USER CODE BEGIN 4下面添加函数CANFilter_Config(),用于配置CAN2的过滤器,

void CANFilter_Config(void)
{CAN_FilterTypeDef  sFilterConfig;sFilterConfig.FilterBank = 0;                       // CAN过滤器编号,范围0-27sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   // CAN过滤器模式,掩码模式或列表模式,这里选择掩码模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  // CAN过滤器尺度,16位或32位,这里选择32位sFilterConfig.FilterIdHigh = 0x0000;                // 32位下,存储要过滤ID的高16位sFilterConfig.FilterIdLow  = 0x0000;                // 32位下,存储要过滤ID的低16位sFilterConfig.FilterMaskIdHigh = 0x0000;            // 掩码模式下,存储的是过滤器掩码的高16位sFilterConfig.FilterMaskIdLow  = 0x0000;            // 掩码模式下,存储的是过滤器掩码的低16位sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; // 报文通过过滤器的匹配后,存储到哪个FIFO,这里选择FIFO0sFilterConfig.FilterActivation = CAN_FILTER_ENABLE; // 激活过滤器sFilterConfig.SlaveStartFilterBank = 0;if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) {Error_Handler();}
}

选择FilterBank 0,配置成掩码模式,选择FIFO0来接收CAN报文(这个和前面选择RX0中断保持一致,如果使用FIFO1,那么前面就要勾选RX1中断)。掩码ID是全0,表示允许接收所有报文,芯片手册介绍如下,

![[Pasted image 20240831224249.png]]

PS:如果只想接收指定报文,那么就要配置掩码ID为非0,具体可以参考芯片手册。

然后添加CAN2的使能函数,

void CAN_Start_Init(void)
{if (HAL_CAN_Start(&hcan2) != HAL_OK) {Error_Handler();}if (HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) !=  HAL_OK){Error_Handler();}
}

还有发送函数,这个用来测试发送,

void CAN2_Send_Test(void)
{uint32_t TxMailbox;uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};CAN_TxHeaderTypeDef TxMessage;TxMessage.IDE = CAN_ID_STD;     // 设置ID类型,标准帧还是扩展帧,这里选择标准帧TxMessage.StdId = 0x111;        // 设置ID号TxMessage.RTR = CAN_RTR_DATA;   // 设置传输数据帧TxMessage.DLC = 4;              // 设置数据长度if (HAL_CAN_AddTxMessage(&hcan2, &TxMessage, data, &TxMailbox) != HAL_OK){Error_Handler();}
}

最后是CAN2接收中断的回调函数,用来测试接收,

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};HAL_StatusTypeDef  status;CAN_RxHeaderTypeDef RxMessage;if (hcan == &hcan2) {  status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);if (HAL_OK == status){; // to do something}}
}

添加好之后,在USER CODE BEGIN PFP下添加函数声明,接收中断的回调函数不用声明,

/* USER CODE BEGIN PFP */void CANFilter_Config(void);
void CAN_Start_Init(void);
void CAN2_Send_Test(void);/* USER CODE END PFP */

然后在main函数里调用这些函数,每隔1s发送一次CAN报文,

![[Pasted image 20240831225340.png]]

再次编译并烧录到板子里,然后重启运行,此时在PCAN-View上可以看到CAN报文,说明发送没问题,

![[Pasted image 20240831230812.png]]

接着验证接收,此时先进入debug模式,然后在CAN接收中断里打个断点,

![[Pasted image 20240831231041.png]]

使用PCAN-View来创建一条随意报文,数据是0x9988,

![[Pasted image 20240831231158.png]]

然后点击OK进行保存,最后选中创建的报文按空格进行发送,此时会进入断点,

![[Pasted image 20240831231403.png]]

把data数组添加到Keil的Watch窗口中,然后单步走一步,可以看到data数组里有数据了,如下,正是之前发送的报文数据,

![[Pasted image 20240831231533.png]]


三 移植CanFestival

有了第二节的基础工程后,本节讲述如何移植CanFestival,适用于STM32 F4系列芯片。

对象字典的配置

首先规划一下Slave设备的对象字典,具体如下,

  • 每隔3s发送一次心跳报文
  • 添加对象0x2000_00 (u8类型), 0x2001_00 (u16类型), 0x2002_00 (u32类型), 0x2003_00 (i32类型),0x2004_00 (i16类型),0x2005_00 (Visible String类型),总共6个对象
  • RPDO1:对应0x2000_00,0x2001_00和0x2002_00
  • TPDO1:对应0x2003_00,每隔500ms发一次

这里使用objdictgen来进行编辑,其地址是https://github.com/happybruce/objdictgen,经过本人优化后可以使用Python3启动。
PS:这个编辑器原本是在CanFestival里自带的,本人把其独立出来了。

双击objdictedit.py打开编辑器,然后在File下点击New,在弹出的界面里进行以下设置,
![[Pasted image 20241201214413.png]]

点击OK,进入新的主界面,然后根据下述步骤进行配置,

配置心跳报文

接着在0x1000-0x1029里找到0x1017,将其值设置为3000 (其单位是毫秒,16进制是0xBB8)
![[Pasted image 20241201214707.png]]

添加对象

在0x2000-0x5FFF里添加之前提到的6个对象,
![[Pasted image 20241202230355.png]]

配置RPDO1

设置RPDO1的映射,该对象索引是0x1600,如下,对应0x2000_00, 0x2001_00和0x2002_00
![[Pasted image 20241202225034.png]]

设置RPDO1的通信参数,该对象索引是0x1400,这里只配置COB ID和Inhibit Time (10ms)
![[Pasted image 20241202225258.png]]

当设备收到COB ID的为NodeId+0x200的报文,就会把报文里包含的值存入对应的对象里。

配置TPDO1

设置TPDO1的映射,该对象索引是0x1A00,如下,对应0x2003_00
![[Pasted image 20241202225614.png]]

设置TPDO1的通信参数,该对象索引是0x1800,如下,
![[Pasted image 20241202225824.png]]

COB ID是nodeid+0x180,传输类型是254,即0xFE,定时时间是500ms,即0x1F4

这样对象字典就配置好了。最后保存工程,并生成对应的代码,点击File->Build Dictionary生成slavedic.c和slavedic.h
![[Pasted image 20241202230906.png]]

这2个文件暂时留着备用

开启定时器

打开CubeMX工程,然后开启TIM3,时钟源选择内部时钟,预分频系数输入839,

![[Pasted image 20240901133442.png]]

为什么是839呢?CanFestival对定时器的要求是counter每隔10us加1,也就是100KHz,而前面配置时钟时定时器的时钟频率是84MHz,如果以100KHz为单位,那么84M就等于840x100K, 那么为了达到100KHz的频率,预分频系数就是840-1=839

最后打开定时器中断,
![[Pasted image 20240901134020.png]]

移植

首先使用git clone下载CanFestival,

git clone https://github.com/happybruce/CanFestival.git
cd CanFestival
git checkout develop

这个Github地址是本人的仓库,已经对代码进行了优化。

在工程目录Core下添加以下目录结构,

![[Pasted image 20240901125648.png]]

然后做以下拷贝,

  • 把CanFestival/src目录下的红框标注的文件拷贝到Core/CanFestival/src/下,红叉的不要拷贝

    在这里插入图片描述

  • 把CanFestival/include目录下的以下文件拷贝到Core/CanFestival/inc/下,还有cm4目录也拷贝过来,

    在这里插入图片描述

  • 把CanFestival/drivers/cm4目录下的cm4.h和cm4.c拷贝到Core/CanFestival/drv下

  • 把CanFestival/examples/CM4/od/下的slavedic.c和slavedic.h拷贝到Core/CanFestival/slavedic下

拷贝完毕后打开Keil工程,点击以下按钮,

在这里插入图片描述

然后添加三个组及其对应的源文件,注意这里不需要添加头文件,后面给头文件设置搜索目录即可

在这里插入图片描述

添加完毕后点击OK,然后添加搜索目录,如下图2个步骤,
在这里插入图片描述
在弹出界面里填入以下目录,
在这里插入图片描述
最后点击OK,这样工程就配置好了。

main.c内容如下,

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "tim.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "canfestival.h"
#include "slavedic.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */void CANFilter_Config(void);
void CAN_Start_Init(void);
void CAN1_Send_Test(void);/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_CAN2_Init();MX_TIM3_Init();/* USER CODE BEGIN 2 */initTimer(); // 初始化定时器canInit(&slavedic_ObjDictData, 500000); // 设置速率为500KHAL_TIM_Base_Start_IT(&htim3);CANFilter_Config();CAN_Start_Init();setNodeId(&slavedic_ObjDictData, 1); // 设置Canopen id为1setState(&slavedic_ObjDictData, Initialisation); // NMT状态设置为InitialisationsetState(&slavedic_ObjDictData, Pre_operational); // NMT状态设置为Pre_operationalsetState(&slavedic_ObjDictData, Operational); // NMT状态设置为Operational/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 4;RCC_OscInitStruct.PLL.PLLN = 168;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 */// static CAN_TxHeaderTypeDef TxMessage; //CAN发�?�的消息的消息头
// static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息�???void CANFilter_Config(void)
{CAN_FilterTypeDef  sFilterConfig;sFilterConfig.FilterBank = 0;                       //CAN过滤器编号,范围0-27sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //CAN过滤器模式,掩码模式或列表模�???sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //CAN过滤器尺度,16位或32�???sFilterConfig.FilterIdHigh = 0x000 << 5;      //32位下,存储要过滤ID的高16�???sFilterConfig.FilterIdLow = 0x0000;          //32位下,存储要过滤ID的低16�???sFilterConfig.FilterMaskIdHigh = 0x0000;      //掩码模式下,存储的是掩码sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;        //报文通过过滤器的匹配后,存储到哪个FIFOsFilterConfig.FilterActivation = CAN_FILTER_ENABLE;        //�???活过滤器sFilterConfig.SlaveStartFilterBank = 0;if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) {Error_Handler();}}void CAN_Start_Init(void)
{if (HAL_CAN_Start(&hcan2) != HAL_OK) {Error_Handler();}if (HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) !=  HAL_OK){Error_Handler();}
}void CAN1_Send_Test(void)
{uint32_t TxMailbox;CAN_TxHeaderTypeDef TxMessage;uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};TxMessage.IDE = CAN_ID_STD;     //设置ID类型TxMessage.StdId = 0x111;        //设置ID�???TxMessage.RTR = CAN_RTR_DATA;   //设置传�?�数据帧TxMessage.DLC = 4;              //设置数据长度if (HAL_CAN_AddTxMessage(&hcan2, &TxMessage, data, &TxMailbox) != HAL_OK){Error_Handler();}  
}// void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
// {
//   uint8_t  data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
//   HAL_StatusTypeDef  status;
//   CAN_RxHeaderTypeDef RxMessage;//   if (hcan == &hcan2)
//   {  
//     status = HAL_CAN_GetRxMessage(&hcan2, CAN_RX_FIFO0, &RxMessage, data);
//     if (HAL_OK == status)
//     {
//         // printf("--->Data Receieve!\r\n");
//         // printf("RxMessage.StdId is %#x\r\n",  RxMessage.StdId);
//         // printf("data[0] is 0x%02x\r\n", data[0]);
//         // printf("data[1] is 0x%02x\r\n", data[1]);
//         // printf("data[2] is 0x%02x\r\n", data[2]);
//         // printf("data[3] is 0x%02x\r\n", data[3]);
//         // printf("<---\r\n");//         __nop();//     }
//   }
// }/* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

然后编译,烧录到板子上运行,如下,可以看到TPDO1每隔500毫秒发一次
在这里插入图片描述
由前面配置可知,TPDO1对应0x2003_00,这里通过PCAN view来发送SDO去修改这个对象值,
在这里插入图片描述
发送完后,可以看出TPDO1发出的值就变了,变成我们通过SDO写的值
在这里插入图片描述
然后通过PCAN View发一个RPDO1给板子,
在这里插入图片描述
发完之后通过SDO去读取0x2000_00, 0x2001_00和0x2002_00的值,如下,可以看出与RPDO1发出的值相等
在这里插入图片描述


四 总结

本文讲述了如何把CanFestival移植到STM32 F4系列芯片上,由于本人优化了CanFestival库,所以移植起来比较简单。

了解过程后,对于master或移植到CM3、CM0都很容易了。

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

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

相关文章

Cursor+Devbox AI开发快速入门

1. 前言 今天无意间了解到 Cursor 和 Devbox 两大开发神器,初步尝试以后发现确实能够大幅度提升开发效率,特此想要整理成博客以供大家快速入门. 简单理解 Cursor 就是一款结合AI大模型的代码编辑器,你可以将自己的思路告诉AI,剩下的目录结构的搭建以及项目代码的实现均由AI帮…

Redis常见问题总结

Redis常见问题总结 1.Redis分布式存储方案 分布式存储核心特点主从&#xff08;Master/Slave&#xff09;模式一主多从&#xff0c;故障时手动切换。哨兵&#xff08;Sentinel&#xff09;模式有哨兵的一主多从&#xff0c;主节点故障自动选择新的主节点。集群&#xff08;Cl…

Svn如何切换删除账号

记录Svn清除切换账号 1.首先打开小乌龟的设置如下图 打开设置后单击已保存数据&#xff0c;然后选择清除 接上图选择清除后&#xff0c;就可以打勾选择清除已保存的账号&#xff0c;我们再次检出的就可以切换账号了 &#x1f449;总结 本次记录Svn清除切换账号 如能帮助到你…

电子应用设计方案-38:智能语音系统方案设计

智能语音系统方案设计 一、引言 智能语音系统作为一种便捷、自然的人机交互方式&#xff0c;正逐渐在各个领域得到广泛应用。本方案旨在设计一个高效、准确、功能丰富的智能语音系统。 二、系统概述 1. 系统目标 - 实现高准确率的语音识别和自然流畅的语音合成。 - 支持多种语…

红外跟随避障模块详解

在智能车、机器人和自动化等领域避障技术是确保安全和高效运行的关键。红外避障模块作为一种常见的避障解决方案&#xff0c;因其非接触、响应速度快和抗干扰能力强等优点而备受青睐。本文将详细介绍红外避障模块的特点、工作原理、以及应用案例&#xff0c;帮助您更好地了解这…

数据下载实践教程系列:跨过数据获取障碍---TCIA和TCGA数据下载

1.前言 作为一个医工交叉领域的工科学者&#xff0c;我想你必定听说过TCGA数据库和TCIA数据库&#xff0c;但是身边不少生信学者和医生是会用的&#xff0c;但大都将此作为护城河而讳莫如深&#xff01;有了数据&#xff0c;工科小伙伴也可以摆脱数据依赖而独立进行研究了。作为…

期权懂|场内个股期权开户流程有哪些?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 场内个股期权开户流程有哪些&#xff1f; 场内个股期权开户第一步开户‌&#xff1a; 投资者首先需要在具有期权交易资格的证券公司开立期权账户。 ‌场内个股期权开户第二步选…

Qt复习学习

https://www.bilibili.com/video/BV1Jp4y167R9/?spm_id_from333.999.0.0&vd_sourceb3723521e243814388688d813c9d475f https://subingwen.cn/qt/qt-primer/#1-4-Qt%E6%A1%88%E4%BE%8B https://subingwen.cn/qt/ https://download.qt.io/archive/qt/1.1Qt的特点 1.2QT中的…

Qt开源控件:图像刻度轴绘制器 (附源码)工程项目私信博主

项目简介 图像刻度轴绘制器是一款基于 Qt/C 开发的小型绘图工具&#xff0c;旨在实现带有刻度轴的图像显示功能。该项目主要用于需要精确测量或标注图像坐标的场景。通过左侧和底部的坐标轴以及对应的刻度线&#xff0c;可以直观地了解图像内容在二维空间中的位置。 项目功能 …

【Transformer序列预测】Pytorch中构建Transformer对序列进行预测源代码

Python&#xff0c;Pytorch中构建Transformer进行序列预测源程序。包含所有的源代码和数据&#xff0c;程序能够一键运行。此程序是完整的Transformer&#xff0c;即使用了Encoder、Decoder和Embedding所有模块。源程序是用jupyterLab所写&#xff0c;建议分块运行。也整理了.p…

mac 安装python3和配置环境变量

mac 安装python3和配置环境变量 前言怎样选择python3的版本python3的安装1、去官网下载安装包2、下载完成后直接解压,检查安装是否成功 前言 在学习python的第一步就是安装它和配置他的环境变量&#xff0c;那么选择哪个版本的python你可曾知道&#xff0c;下面就讲解怎样选择…

基于MFC实现的人机对战五子棋游戏

基于MFC实现的人机对战五子棋游戏 1、引言 此报告将详细介绍本次课程设计的动机、设计思路及编写技术的详细过程&#xff0c;展现我所学过的C知识以及我通过本次课程设计所学到例如MFC等知识。在文档最后我也会记录我所编写过程遇到的问题以及解决方案。 1.1 背景 五子棋是…

6.824/6.5840 Lab 4: Fault-tolerant Key/Value Service

We are the champions my friend And well keep on fighting till the end We are the champions ——We Are The Champions 完整代码见&#xff1a; GitHub - SnowLegend-star/6.824: As we advance, the trials grow ever more arduous, and now we stand before an even mig…

ShardingSphere 数据库中间件

数据库中的数据量猛增&#xff0c;访问性能也变慢了&#xff0c;优化迫在眉睫 ? 1. 关系型数据库本身比较容易成为系统瓶颈&#xff1a;单机存储容量、数据库连接数、处理能力都有限。 2. 当单表的数据量达到 1000W 或 100G 以后&#xff0c;由于查询维度较多&#xff0c;即使…

Webpack Tree Shaking 技术原理及应用实战,优化代码,精简产物

前言 在前端开发中&#xff0c;优化代码体积和提升应用性能是至关重要的课题。Webpack 提供了多种优化手段来帮助开发者实现这一目标&#xff0c;Tree Shaking 就是其中一种非常重要的优化技术&#xff0c;它通过在编译阶段移除未被使用的代码模块&#xff0c;从而显著减小最终…

【热门主题】000075 探索嵌入式硬件设计的奥秘

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

[保姆式教程]使用目标检测模型YOLO11 OBB进行旋转目标检测:训练自己的数据集(基于卫星和无人机的农业大棚数据集)

之前写了一个基于YOLOv8z做旋转目标检测的文章&#xff0c;内容写得不够好&#xff0c;内容也比较杂乱。现如今YOLO已经更新到11了&#xff0c;数据集也集齐了无人机和卫星的农业大棚&#xff0c;所以这次就写一个基于YOLO11 OBB的农业大棚旋转检测。 1. 下载源码配置环境 在h…

Matplotlib 内置的170种颜色映射(colormap)

Matplotlib 提供了许多内置的颜色映射&#xff08;colormap&#xff09;选项&#xff0c;可以将数值数据映射到色彩范围——热力图、温度图、地图等可视化经常会用到。 # colormap 有两种引用形式plt.imshow(data, cmapBlues)plt.imshow(data, cmapcm.Blues) 颜色映射可以分为…

工业—使用Flink处理Kafka中的数据_ProduceRecord1

1 、 使用 Flink 消费 Kafka 中 ProduceRecord 主题的数据,统计在已经检验的产品中,各设备每 5 分钟 生产产品总数,将结果存入Redis 中, key 值为

剑指offer(专项突破)---字符串

总目录&#xff1a;剑指offer&#xff08;专项突破&#xff09;---目录-CSDN博客 1.字符串的基本知识 C语言中&#xff1a; 函数名功能描述strcpy(s1, s2)将字符串s2复制到字符串s1中&#xff0c;包括结束符\0&#xff0c;要求s1有足够空间容纳s2的内容。strncpy(s1, s2, n)…